URL
https://opencores.org/ocsvn/sdram/sdram/trunk
Subversion Repositories sdram
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 6 to Rev 7
- ↔ Reverse comparison
Rev 6 → Rev 7
/tags/sdram_8Mb_2Mx32_020200/inc.h
0,0 → 1,220
//******************************************************************************* |
// S Y N T H E S I Z A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
|
|
// Uncomment below to use the microprocessor bus simulator |
// This will turn this IP into a "SDRAM" tester. |
// Once you enable this option, choose the test mode in |
// the file "tst_inc.h" |
// ==================== |
//`define simulate_mp |
|
// Uncomment the below to enable the debug pins |
// If you are in an FPGA/CPLD platform be *CAREFULL*. This will |
// generate a lot of pins. Use it with causion. |
// ==================== |
//`define show_debug |
|
|
// Common definition stuff |
`define HI 1'b1 |
`define LO 1'b0 |
`define X 1'bx |
|
//*********************************************************** |
// U S E R M O D I F I A B L E S |
//*********************************************************** |
|
// The number of refreshses done at power up. 16 by default |
`define power_up_ref_cntr_limit 3 |
|
// The number of refreshes done during normal refresh cycle. |
// Set this to be 2048 for "burst" refreshes, and |
// set this to be 1 for "regular" refreshes |
`define auto_ref_cntr_limit 1 |
|
// Refresh Frequency in Hz. |
// For burst refresh use 33Hz (30mS) |
// For normal refresh use 66666Hz (15uS) |
`define Frefresh 66666 |
|
// Type of Data Bus |
// Unididrectiona: the top hierachy module SDRAM.V will have seperate 32 bit |
// data buses for reads and writes. This is useful for embedding the |
// core in a larger core. |
// Birectional: the top hierarchy module SDRAM.V will have a biredirectional 32bit |
// data bus. This is useful if the SDRAM controller core is to be a |
// stand-alone module. |
// |
// Comment the below for bidirectional bus, and UNcomment for unidirectional |
`define databus_is_unidirectional |
|
// SDRAM DATA BUS TYPE |
// |
// |
`define sdram_data_bus_is_unidirectional |
|
|
// DATA BUS ALIGNING |
// With this option enabled (uncomment below) half-word accesses are aligned to lower |
// bus DATA[15:0], and byte accesses are aligned to DATA[7:0]. This is ideal when a |
// 8 bit micro or host wants to access all of the space of the 16/32 bit SDRAM. |
|
// data bus aligning ON: (uncomment the below define) |
// a 16 bit write should have the data to the SDRAM controller on D[15:0]. |
// a 16 bit read will have the data returned by the SDRAM conroller on D[15:0]. |
// a 8 bit write should have the data to the SDRAM controller on D[7:0]. |
// a 8 bit read will have the data returned by the SDRAM controller on D[7:0]. |
// |
// data bus aligning OFF: (comment the below define) |
// a 16 bit write should have the data to the SDRAM controller on D[31:16] or |
// D[15:0] depending on the state of A[1] (A[1]=1, on D[31:16], A[1]=0 on |
// D[15:0]. |
// a 16 bit read will have the data returned by the SDRAM controller on D[31:16] |
// or D[15:0], based on the state of A[1]. |
// similar thought process for 8 bit write and reads. |
// |
//`define align_data_bus |
|
|
// SDRAM clock frequency in Hz. |
// Set this to whatever the clock rate is |
`define Fsystem 2000000 |
//`define Fsystem 100000000 |
|
|
|
|
// DEFAULT MODE-REGISTER values |
// The below is programmed to the mode regsiter at |
// powerup |
`define default_mode_reg_BURST_LENGHT 3'b000 |
`define defulat_mode_reg_BURST_TYPE 1'b0 |
`define default_mode_reg_CAS_LATENCY 3'b010 |
|
|
//*********************************************************** |
// D O N O T M O D I F Y |
//*********************************************************** |
// Interval between refreshes in SDRAM clk ticks |
`define RC `Fsystem/`Frefresh |
|
// Width of the refresh counter. Default 20. log2(`RC)/log2 |
// use 8 bits for 15uS interval with 12.5MHz clock |
//`define BW 8 |
`define BW 20 |
|
// The refresh delay counter width |
`define RD 3 |
|
// This sets the number of delay cycles right after the refresh command |
`define AUTO_REFRESH_WIDTH 1 |
|
// MAin SDRAM controller state machine definition |
`define TS 4 |
`define TSn `TS-1 |
|
`define state_idle `TS'b0001 |
`define state_set_ras `TS'b0011 |
`define state_ras_dly `TS'b0010 |
`define state_set_cas `TS'b0110 |
`define state_cas_latency1 `TS'b0111 |
`define state_cas_latency2 `TS'b0101 |
`define state_write `TS'b0100 |
`define state_read `TS'b1100 |
`define state_auto_refresh `TS'b1101 |
`define state_auto_refresh_dly `TS'b1111 |
`define state_precharge `TS'b1110 |
`define state_powerup `TS'b1010 |
`define state_modeset `TS'b1011 |
`define state_delay_Trp `TS'b0000 |
`define state_delay_Tras1 `TS'b1000 |
`define state_delay_Tras2 `TS'b1001 |
|
// Fresh timer states |
`define state_count 3'b001 |
`define state_halt 3'b010 |
`define state_reset 3'b100 |
|
/tags/sdram_8Mb_2Mx32_020200/sdramcnt.v
0,0 → 1,644
`include "inc.h" |
|
|
//******************************************************************************* |
// S Y N T H E S I Z A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
|
|
|
module sdramcnt( |
// system level stuff |
sys_rst_l, |
sys_clk, |
|
// SDRAM connections |
sd_wr_l, |
sd_cs_l, |
sd_ras_l, |
sd_cas_l, |
sd_dqm, |
|
// Host Controller connections |
do_mode_set, |
do_read, |
do_write, |
doing_refresh, |
sd_addx_mux, |
sd_addx10_mux, |
sd_rd_ena, |
sd_data_ena, |
modereg_cas_latency, |
modereg_burst_length, |
mp_data_mux, |
decoded_dqm, |
do_write_ack, |
do_read_ack, |
do_modeset_ack, |
pwrup, |
|
// debug |
next_state, |
autorefresh_cntr, |
autorefresh_cntr_l, |
cntr_limit |
|
); |
|
parameter N1 = 4; |
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
|
|
// System level stuff |
input sys_rst_l; |
input sys_clk; |
|
// SDRAM connections |
output sd_wr_l; |
output sd_cs_l; |
output sd_ras_l; |
output sd_cas_l; |
output [(N1-1):0] sd_dqm; |
|
// Host Controller connections |
input do_mode_set; |
input do_read; |
input do_write; |
output doing_refresh; |
output [1:0] sd_addx_mux; |
output [1:0] sd_addx10_mux; |
output sd_rd_ena; |
output sd_data_ena; |
input [2:0] modereg_cas_latency; |
input [2:0] modereg_burst_length; |
output mp_data_mux; |
input [3:0] decoded_dqm; |
output do_write_ack; |
output do_read_ack; |
output do_modeset_ack; |
output pwrup; |
|
// Debug |
output [3:0] next_state; |
output [3:0] autorefresh_cntr; |
output autorefresh_cntr_l; |
output [12:0] cntr_limit; |
|
// **************************************** |
// |
// Memory Elements |
// |
// **************************************** |
// |
reg [3:0] next_state; |
reg [7:0] refresh_timer; |
reg sd_wr_l; |
reg sd_cs_l; |
reg sd_ras_l; |
reg sd_cas_l; |
reg [3:0] sd_dqm; |
reg [1:0] sd_addx_mux; |
reg [1:0] sd_addx10_mux; |
reg sd_data_ena; |
reg pwrup; // this variable holds the power up condition |
reg [12:0] refresh_cntr; // this is the refresh counter |
reg refresh_cntr_l; // this is the refresh counter reset signal |
reg [3:0] burst_length_cntr; |
reg burst_cntr_ena; |
reg sd_rd_ena; // read latch gate, active high |
reg [12:0] cntr_limit; |
reg [3:0] modereg_burst_count; |
reg [2:0] refresh_state; |
reg mp_data_mux; |
wire do_refresh; // this bit indicates autorefresh is due |
reg doing_refresh; // this bit indicates that the state machine is |
// doing refresh. |
reg [3:0] autorefresh_cntr; |
reg autorefresh_cntr_l; |
reg do_write_ack; |
reg do_read_ack; |
reg do_modeset_ack; |
reg do_refresh_ack; |
|
wire Trc_expired, Ref_expired; |
|
assign Trc_expired = (autorefresh_cntr == 4'h6); |
assign Ref_expired = (refresh_cntr == cntr_limit); |
|
// State Machine |
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
next_state <= `state_powerup; |
autorefresh_cntr_l <= `LO; |
refresh_cntr_l <= `LO; |
pwrup <= `HI; // high indicates we've just power'd up or RESET |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_dqm <= 4'hF; |
sd_data_ena <= `LO; |
sd_addx_mux <= 2'b10; // select the mode reg default value |
sd_addx10_mux <= 2'b11; // select 1 as default |
sd_rd_ena <= `LO; |
mp_data_mux <= `LO; |
// refresh_cntr<= 13'h0000; |
burst_cntr_ena <= `LO; // do not enable the burst counter |
doing_refresh <= `LO; |
do_write_ack <= `LO; // do not ack as reset default |
do_read_ack <= `LO; // do not ack as reset default |
do_modeset_ack <= `LO; // do not ack as reset default |
do_refresh_ack <= `LO; |
end |
else case (next_state) |
// Power Up state |
`state_powerup: begin |
next_state <= `state_precharge; |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_dqm <= 4'hF; |
sd_data_ena <= `LO; |
sd_addx_mux <= 2'b10; |
sd_rd_ena <= `LO; |
pwrup <= `HI; // this is the power up run |
burst_cntr_ena <= `LO; // do not enable the burst counter |
refresh_cntr_l <= `HI; // allow the refresh cycle counter to count |
end |
|
// PRECHARGE both (or all) banks |
`state_precharge: begin |
sd_wr_l <= `LO; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `HI; |
sd_dqm <= 4'hF; |
sd_addx10_mux <= 2'b11; // A10 = 1'b1 |
next_state <= `state_idle; |
if (do_write_ack) |
do_write_ack<= `LO; // done acknowledging the write request |
if (do_read_ack) |
do_read_ack <= `LO; // done acknowledging the read request |
end |
|
// Delay Trp |
// this delay is needed to meet the minimum precharge to new command |
// delay. For most parts, this is 20nS, which means you need 1 clock cycle |
// of NOP at 100MHz |
`state_delay_Trp: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
if ( (refresh_cntr == cntr_limit) & (pwrup == `HI) ) begin |
doing_refresh <= `LO; // refresh cycle is done |
refresh_cntr_l <= `LO; // ..reset refresh counter |
next_state <= `state_modeset; // if this was power-up, then go and set mode reg |
end else begin |
doing_refresh <= `HI; // indicate that we're doing refresh |
next_state <= `state_auto_refresh; |
end |
end |
|
|
// Autorefresh |
`state_auto_refresh: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `LO; |
sd_addx10_mux <= 2'b01; // A10 = 0 |
next_state <= `state_auto_refresh_dly; |
autorefresh_cntr_l <= `HI; //allow refresh delay cntr (Trc) to tick |
do_refresh_ack <= `HI; // acknowledge refresh request |
end |
|
// This state generates the Trc delay. |
// this delay is the delay from the refresh command to the next valid command |
// most parts require this to be 60 to 70nS. So at 100MHz, we need at least |
// 6 NOPs. |
`state_auto_refresh_dly: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_addx10_mux <= 2'b00; // select ROW again A10 = A20 |
/* |
casex ( {Trc_expired, Ref_expired, pwrup, (do_write|do_read)} ) |
// Trc not expired yet |
4'b0xxx: begin |
next_state <= `state_auto_refresh_dly; |
do_refresh_ack <= `LO; |
end |
|
// Back-back refreshes not done yet |
4'b10xx: begin |
autorefresh_cntr_l <= `LO; // reset Trc delay counter |
next_state <= `state_auto_refresh; |
end |
|
// This is powerup run, so go and set modereg |
4'b110x: begin |
autorefresh_cntr_l <= `LO; // reset Trc delay counter |
doing_refresh <= `LO; // refresh cycle is done |
refresh_cntr_l <= `LO; // ..reset refresh counter |
next_state <= `state_modeset; |
end |
|
4'b1111: begin |
autorefresh_cntr_l <= `LO; // reset Trc delay counter |
doing_refresh <= `LO; // refresh cycle is done |
refresh_cntr_l <= `LO; // ..reset refresh counter |
next_state <= `state_set_ras; // go service a pending read or write if any |
end |
|
4'b1110: begin |
autorefresh_cntr_l <= `LO; // reset Trc delay counter |
doing_refresh <= `LO; // refresh cycle is done |
refresh_cntr_l <= `LO; // ..reset refresh counter |
next_state <= `state_idle; // go service a pending read or write if any |
end |
endcase |
*/ |
// Wait for Trc |
if (autorefresh_cntr == 4'h6) begin |
autorefresh_cntr_l <= `LO; // reset Trc delay counter |
// Check if the number of specified back-back refreshes are done |
if (refresh_cntr == cntr_limit) begin |
doing_refresh <= `LO; // refresh cycle is done |
refresh_cntr_l <= `LO; // ..reset refresh counter |
// if this is not a power-up sequence, and there are pending |
// requests, then service it. |
if (~pwrup) |
if (do_write | do_read) |
next_state <= `state_set_ras; // go service a pending read or write if any |
else |
next_state <= `state_idle; // if there are no peding RD or WR, then go to idle state |
// if this is part of power-up sequencing, we need to go and |
// set mode register. |
else |
next_state <= `state_modeset; |
end |
// IF refresh cycles not done yet, keep issuing autorefresh commands |
else |
next_state <= `state_auto_refresh; |
end |
// If Trc has not expired |
else begin |
next_state <= `state_auto_refresh_dly; |
do_refresh_ack <= `LO; |
end |
|
|
|
end |
|
|
// MODE SET state |
`state_modeset: begin |
next_state <= `state_idle; |
sd_wr_l <= `LO; |
sd_cs_l <= `LO; |
sd_ras_l <= `LO; |
sd_cas_l <= `LO; |
sd_addx_mux <= 2'b10; |
sd_addx10_mux <= 2'b10; |
doing_refresh <= `LO; // deassert |
if (pwrup) |
pwrup <= `LO; // ..no more in power up mode |
if (do_mode_set) |
do_modeset_ack <= `LO; |
end |
|
|
|
// IDLE state |
`state_idle: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_data_ena <= `LO; // turn off the data bus drivers |
mp_data_mux <= `LO; // drive the SD data bus with normal data |
sd_addx_mux <= 2'b00; // select ROW (A[19:10]) of mp_addx to SDRAM |
sd_addx10_mux <= 2'b00; // select ROW (A[20]) " " |
|
// if we've just come out of system reset (or powerup) |
// then we need to go and do initialization sequence. |
// Or, if a refresh is requested, go and service it. |
if (do_refresh | pwrup) begin |
doing_refresh <= `HI; // indicate that we're doing refresh |
refresh_cntr_l <= `HI; // allow refresh cycle counter to count up |
next_state <= `state_auto_refresh; |
end |
|
// if a single word rad or write request is pending, go and service it |
else if (do_write | do_read ) |
next_state <= `state_set_ras; |
|
// if a mode register set is requested, go and service it |
else if (do_mode_set) begin |
do_modeset_ack <= `HI; // acknowledge the mode set request |
next_state <= `state_modeset; |
doing_refresh <= `HI; // techincally we're not doing refresh, but |
end // this signal is used to prevent the do_write be deasserted |
// by the mode_set command. |
|
end |
|
// SET RAS state |
`state_set_ras: begin |
sd_cs_l <= `LO; // enable SDRAM |
sd_ras_l <= `LO; // enable the RAS |
next_state <= `state_ras_dly; // wait for a bit |
end |
|
// RAS delay state. |
// This delay is needed to meet Trcd delay. This is the RAS to CAS delay. |
// for most parts this is 20nS. So for 100MHz operation, there needs to be |
// at least 1 NOP cycle. |
`state_ras_dly: begin |
sd_cs_l <= `HI; // disable SDRAM |
sd_ras_l <= `HI; // disble the RAS |
sd_addx_mux <= 2'b01; // select COLUMN |
sd_addx10_mux <= 2'b01; // select COLUMN |
if (do_write) begin |
sd_data_ena <= `HI; // turn on the data bus drivers |
sd_dqm <= decoded_dqm; // masks the data which is meant to be |
next_state <= `state_write; // if write, do the write |
end else begin |
sd_dqm <= 4'h0; |
next_state <= `state_set_cas; // if read, do the read |
end |
end |
|
// WRITE state |
`state_write: begin |
sd_cs_l <= `LO; // enable SDRAM |
sd_cas_l <= `LO; // enable the CAS |
sd_wr_l <= `LO; // enable the write |
do_write_ack<= `HI; // acknowledge the write request |
sd_dqm <= 4'hF; |
next_state <= `state_delay_Tras1; |
end |
|
`state_delay_Tras1: begin |
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_dqm <= 4'hF; |
sd_addx_mux <= 2'b00; // send ROW (A[19:10]) of mp_addx to SDRAM |
sd_addx10_mux <= 2'b00; // send ROW (A[20]) " " |
mp_data_mux <= `HI; // drive the SD data bus with all zeros |
next_state <= `state_delay_Tras2; |
end |
|
`state_delay_Tras2: begin |
next_state <= `state_precharge; |
end |
|
|
// SET CAS state |
`state_set_cas: begin |
sd_cs_l <= `LO; |
sd_cas_l <= `LO; |
sd_dqm <= 4'hF; |
next_state <= `state_cas_latency1; |
end |
|
`state_cas_latency1: begin |
sd_cs_l <= `HI; // disable CS |
sd_cas_l <= `HI; // disable CAS |
if (modereg_cas_latency==3'b010) begin |
do_read_ack <= `HI; // acknowledge the read request (do it here due to the latency) |
next_state <= `state_read; // 2 cycles of lantency done. |
burst_cntr_ena <= `HI; // enable he burst lenght counter |
end else |
next_state <= `state_cas_latency2; // 3 cycles of latency |
end |
|
`state_cas_latency2: begin |
next_state <= `state_read; |
burst_cntr_ena <= `HI; // enable the burst lenght counter |
do_read_ack <= `HI; // acknowledge the read request (do it here due to the latency) |
end |
|
`state_read: begin |
if (burst_length_cntr == modereg_burst_count) begin |
burst_cntr_ena <= `LO; // done counting; |
sd_rd_ena <= `LO; // done with the reading |
next_state <= `state_precharge; |
|
sd_wr_l <= `HI; |
sd_cs_l <= `HI; |
sd_ras_l <= `HI; |
sd_cas_l <= `HI; |
sd_addx_mux <= 2'b00; // send ROW (A[19:10]) of mp_addx to SDRAM |
sd_addx10_mux <= 2'b00; // send ROW (A[20]) " " |
mp_data_mux <= `HI; // drive the SD data bus with all zeros |
|
end else begin |
sd_rd_ena <= `HI; // enable the read latch on the next state |
next_state <= `state_read; |
end |
end |
|
endcase |
|
|
// This counter is used to generate a delay right after the |
// auto-refresh command is issued to the SDRAM |
always @(posedge sys_clk or negedge autorefresh_cntr_l) |
if (~autorefresh_cntr_l) |
autorefresh_cntr <= 4'h0; |
else |
autorefresh_cntr <= autorefresh_cntr + 1; |
|
|
|
// This mux selects the cycle limit value for the |
// auto refresh counter. |
// During power-up sequencing, we need to do `power_up_ref_cntr_limit |
// number of back=back refreshes. |
// During regular operation, we need to do `auto_ref_cntr_limit number of |
// back-back refreshes. This, for most cases is just 1, but if we're doing |
// "burst" type of refreshes, it could be more than 1. |
always @(pwrup) |
case (pwrup) |
`HI: cntr_limit <= `power_up_ref_cntr_limit; |
default: cntr_limit <= `auto_ref_cntr_limit; |
endcase |
|
|
// |
// BURST LENGHT COUNTER |
// |
// This is the burst length counter. |
always @(posedge sys_clk or negedge burst_cntr_ena) |
if (~burst_cntr_ena) |
burst_length_cntr <= 3'b000; // reset whenever 'burst_cntr_ena' is low |
else |
burst_length_cntr <= burst_length_cntr + 1; |
|
// |
// REFRESH_CNTR |
// |
// This counter keeps track of the number of back-back refreshes we're |
// doing. For most cases this would just be 1, but it allows "burst" |
// refresh, where all refrehses are done back to back. |
always @(posedge sys_clk or negedge refresh_cntr_l) |
if (~refresh_cntr_l) |
refresh_cntr <= 13'h0000; |
else if (next_state == `state_auto_refresh) |
refresh_cntr <= refresh_cntr + 1; |
|
// |
// BURST LENGTH SELECTOR |
// |
always @(modereg_burst_length) |
case (modereg_burst_length) |
3'b000: modereg_burst_count <= 4'h1; |
3'b001: modereg_burst_count <= 4'h2; |
3'b010: modereg_burst_count <= 4'h4; |
default modereg_burst_count <= 4'h8; |
endcase |
|
|
// |
// REFRESH Request generator |
// |
assign do_refresh = (refresh_state == `state_halt); |
|
|
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
refresh_state <= `state_count; |
refresh_timer <= 8'h00; |
end |
else case (refresh_state) |
// COUNT |
// count up the refresh interval counter. If the |
// timer reaches the refresh-expire time, then go next state |
`state_count: |
if (refresh_timer != `RC) begin |
refresh_timer <= refresh_timer + 1; |
refresh_state <= `state_count; |
end else begin |
refresh_state <= `state_halt; |
refresh_timer <= 0; |
end |
|
// HALT |
// wait for the SDRAM to complete any ongoing reads or |
// writes. If the SDRAM has acknowledged the do_refresh, |
// (i.e. it is now doing the refresh) |
// then go to next state |
`state_halt: |
/* if (next_state==`state_auto_refresh | |
next_state==`state_auto_refresh_dly | |
next_state==`state_precharge ) |
refresh_state <= `state_reset; |
*/ |
if (do_refresh_ack) |
refresh_state <= `state_count; |
|
// RESET |
// if the SDRAM refresh is completed, then reset the counter |
// and start counting up again. |
`state_reset: |
if (next_state==`state_idle) begin |
refresh_state <= `state_count; |
refresh_timer <= 8'h00; |
end |
endcase |
|
|
endmodule |
|
/tags/sdram_8Mb_2Mx32_020200/hostcont.v
0,0 → 1,532
`include "inc.h" |
|
//******************************************************************************* |
// S Y N T H E S I Z A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
|
module hostcont ( |
// system connections |
sys_rst_l, |
sys_clk, |
|
// microprocessor side connections |
mp_addx, |
mp_data_in, |
mp_data_out, |
mp_rd_l, |
mp_wr_l, |
mp_cs_l, |
sdram_mode_set_l, |
sdram_busy_l, |
mp_size, |
|
// SDRAM side connections |
sd_addx, |
sd_data_out, |
sd_data_in, |
sd_ba, |
|
// SDRAMCNT side |
sd_addx10_mux, |
sd_addx_mux, |
sd_rd_ena, |
do_read, |
do_write, |
doing_refresh, |
do_modeset, |
modereg_cas_latency, |
modereg_burst_length, |
mp_data_mux, |
decoded_dqm, |
do_write_ack, |
do_read_ack, |
do_modeset_ack, |
pwrup, |
|
|
// debug |
// rd_wr_clk |
reg_mp_data_mux, |
reg_mp_addx, |
reg_sd_data, |
reg_modeset |
|
); |
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
|
// system connections |
input sys_rst_l; // asynch active low reset |
input sys_clk; // clock source to the SDRAM |
|
// microprocessor side connections |
input [22:0] mp_addx; // ABW bits for the addx |
input [31:0] mp_data_in; // DBW bits of data bus input (see INC.H) |
output [31:0] mp_data_out; // DBW bits of data bus output (see INC.H) |
input mp_rd_l; // micro bus read , active low |
input mp_wr_l; // micro bus write, active low |
input mp_cs_l; |
input sdram_mode_set_l; // acive low request for SDRAM mode set |
output sdram_busy_l; // active low busy output |
input [1:0] mp_size; |
|
// SDRAM side connections |
output [10:0] sd_addx; // 11 bits of muxed SDRAM addx |
input [31:0] sd_data_in; |
output [31:0] sd_data_out; |
output [1:0] sd_ba; // bank select output to the SDRAM |
input pwrup; |
|
// SDRAMCNT side |
input [1:0] sd_addx10_mux; |
input [1:0] sd_addx_mux; |
input sd_rd_ena; |
output do_write; |
output do_read; |
input doing_refresh; |
output do_modeset; |
output [2:0] modereg_cas_latency; |
output [2:0] modereg_burst_length; |
input mp_data_mux; |
output [3:0] decoded_dqm; // this is the decoded DQM according to the size. Used during writes |
input do_write_ack; // acknowledge signal from sdramcont state machine |
// saying that it is now ok to clear 'do_write' signal |
input do_read_ack; // acknowledge signal from sdramcont state machine |
// saying that is is now ok to clear 'do_read' signal |
input do_modeset_ack; |
|
|
//debug |
//output rd_wr_clk; |
output [31:0] reg_mp_data_mux; |
output [22:0] reg_mp_addx; |
output [31:0] reg_sd_data; |
output [10:0] reg_modeset; |
|
// **************************************** |
// |
// Memory Elements |
// |
// **************************************** |
// |
wire [22:0] reg_mp_addx; |
reg [31:0] reg_mp_data; |
reg [31:0] reg_sd_data; |
reg [3:0] decoded_dqm; |
reg [10:0] reg_modeset; |
reg [10:0] sd_addx; |
reg do_read; |
reg do_write; |
reg [2:0] do_state; |
reg do_modeset; |
reg [1:0] sd_ba; |
reg busy_a_ena; |
|
//wire [31:0] sd_data; |
wire [31:0] sd_data_buff; |
wire [31:0] reg_mp_data_mux; |
reg [31:0] mp_data_out; |
wire busy_a; |
wire mp_data_ena; |
wire do_read_clk; |
wire do_read_rst_clk; |
wire do_write_clk; |
wire do_modeset_clk; |
wire do_modeset_rst_clk; |
wire clock_xx; |
wire modereg_ena; |
wire read_busy; |
wire write_busy; |
wire refresh_busy; |
wire modeset_busy; |
wire do_write_rst; |
wire do_read_rst; |
wire do_modeset_rst; |
|
|
assign mp_data_ena = ~mp_rd_l; |
assign modereg_cas_latency = reg_modeset[6:4]; |
assign modereg_burst_length = reg_modeset[2:0]; |
|
assign read_busy = do_read | (~mp_rd_l & busy_a_ena); |
assign write_busy = do_write | (~mp_wr_l & busy_a_ena); |
assign modeset_busy = do_modeset; |
assign refresh_busy = `LO; |
|
// SDRAM BUSY SIGNAL GENERATION |
// |
// The BUSY signal is NOR'd of READ_BUSY, WRITE_BUSY and DUMB_BUSY. |
// READ_BUSY is generated while the SDRAM is performing a read. This |
// does not necessarily have to he synchronous to the micro's read. |
// The WRITE_BUSY is generated while the SDRAM is performing WRITE. |
// Again, due to the "dump-n-run" mode (only in SMART_H=1) the micro's |
// write bus cycle does not necessarily align with SDRAM's write cycle. |
// DUMB_BUSY is a signal which generates the BUSY at the falling edge of |
// micro's SDRAM_CS. This is used for those microprocessors which |
// require a device BUSY as soon as the address is placed on its bus. For |
// example, most Intel microcontrollers and small processors do have this |
// requirement. This means that one will fofeit on the dump-n-go feature. |
// |
assign sdram_busy_l = ~( read_busy | |
write_busy | |
(doing_refresh & ~mp_cs_l)| |
(modeset_busy & ~mp_cs_l) |
); |
|
|
// MP ADDRESS LATCH |
// Transparent latch |
// Used to hold the addx from the micro. Latch on the falling edge of |
// do_write. |
// BAsed on the way "do_write" is generated, we only need to latch on the writes |
// since the write can be queued, but since all reads are blocked, the latch |
// will not latch the addx on reads. |
assign reg_mp_addx = mp_addx; |
|
|
// |
// DECODED DQM LATCH |
// generate the proper DQM[3:0] masks based on the address and on the mp_size |
// |
always @(do_write or sys_rst_l or mp_addx or mp_size) |
// 32 bit masks |
// all masks are enabled (LOW) |
if (mp_size==2'b00) |
decoded_dqm <= 4'h0; |
// 16 bit masks |
// enable the masks accorsing to the half-word selected |
else if (mp_size==2'b10) |
case (mp_addx[1]) |
`LO: decoded_dqm <= 4'b1100; // lower half-word enabled |
default: decoded_dqm <= 4'b0011; // upper half-word enabled |
endcase |
// 8 bit masks |
// enablethe masks according to the byte specified. |
else if (mp_size==2'b01) |
case (mp_addx[1:0]) |
2'b00: decoded_dqm <= 4'b1110; |
2'b01: decoded_dqm <= 4'b1101; |
2'b10: decoded_dqm <= 4'b1011; |
default: decoded_dqm <= 4'b0111; |
endcase |
else |
decoded_dqm <= 4'bxxxx; |
|
|
// MP DATA LATCH |
// Used to hold the data from the micro. Latch on the rising edge |
// of mp_wr_l |
// |
`ifdef align_data_bus |
always @(mp_data_in or reg_mp_addx) |
// 32 bit writes |
if (mp_size==2'b00) |
reg_mp_data <= mp_data_in; |
// 16 bit writes |
else if (mp_size==2'b10) |
case(reg_mp_addx[1]) |
`LO: reg_mp_data[15:0] <= mp_data_in[15:0]; |
default: reg_mp_data[31:16] <= mp_data_in[15:0]; |
endcase |
// 8 bit writes |
else if (mp_size==2'b01) |
case(reg_mp_addx[1:0]) |
2'b00: reg_mp_data[7:0] <= mp_data_in[7:0]; |
2'b01: reg_mp_data[15:8] <= mp_data_in[7:0]; |
2'b10: reg_mp_data[23:16] <= mp_data_in[7:0]; |
default: reg_mp_data[31:24] <= mp_data_in[7:0]; |
endcase |
//---------------------------------- if data aligning is not desired ------------------- |
`else |
always @(mp_data_in) |
reg_mp_data <= mp_data_in; |
`endif |
|
|
// |
// MODE REG REG |
// |
`define default_mode_reg {4'b0000,`default_mode_reg_CAS_LATENCY,`defulat_mode_reg_BURST_TYPE,`default_mode_reg_BURST_LENGHT} |
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) |
reg_modeset <= 10'h000; |
else |
if (pwrup) |
reg_modeset <= `default_mode_reg; |
else |
if (~sdram_mode_set_l & ~mp_cs_l & ~mp_wr_l) |
reg_modeset <= mp_data_in[10:0]; |
|
// SD DATA REGISTER |
// This register holds in the data from the SDRAM |
// |
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) |
reg_sd_data <= 32'h00000000; |
else if (sd_rd_ena) |
reg_sd_data <= sd_data_buff; |
|
|
// |
// SD DATA BUS BUFFERS |
// |
assign sd_data_out = reg_mp_data; |
assign sd_data_buff = sd_data_in; |
|
|
|
// SDRAM SIDE ADDX |
always @(sd_addx10_mux or reg_mp_data or reg_mp_addx or reg_modeset) |
case (sd_addx10_mux) |
2'b00: sd_addx[10] <= reg_mp_addx[20]; |
2'b01: sd_addx[10] <= 1'b0; |
2'b10: sd_addx[10] <= reg_modeset[10]; |
default: sd_addx[10] <= 1'b1; |
endcase |
|
always @(sd_addx_mux or reg_modeset or reg_mp_addx) |
case (sd_addx_mux) |
2'b00: sd_addx[9:0] <= reg_mp_addx[19:10]; // ROW |
2'b01: sd_addx[9:0] <= {2'b00, reg_mp_addx[9:2]}; // COLUMN |
2'b10: sd_addx[9:0] <= reg_modeset[9:0]; |
default: sd_addx[9:0] <= 10'h000; |
endcase |
|
|
// SD_BA |
always @(sd_addx_mux or reg_mp_addx) |
case (sd_addx_mux) |
2'b00: sd_ba <= reg_mp_addx[22:21]; |
2'b01: sd_ba <= reg_mp_addx[22:21]; |
default: sd_ba <= 2'b00; |
endcase |
|
|
|
// Micro data mux |
assign reg_mp_data_mux = mp_data_mux ? 32'h00000000 : reg_mp_data; |
|
// MP_DATA_OUT mux |
// ------------------------------- do this only if the DATA aligning is desired ------- |
`ifdef align_data_bus |
always @(mp_size or reg_sd_data or mp_addx) |
case (mp_size) |
// 32 bit reads |
2'b00: |
mp_data_out <= reg_sd_data; |
// 16 bit reads |
2'b10: |
if (mp_addx[1]) |
mp_data_out[15:0] <= reg_sd_data[31:16]; |
else |
mp_data_out[15:0] <= reg_sd_data[15:0]; |
// 8 bit reads |
default: |
case (mp_addx[1:0]) |
2'b00: mp_data_out[7:0] <= reg_sd_data[7:0]; |
2'b01: mp_data_out[7:0] <= reg_sd_data[15:0]; |
2'b10: mp_data_out[7:0] <= reg_sd_data[23:16]; |
default: mp_data_out[7:0] <= reg_sd_data[31:24]; |
endcase |
endcase |
`else |
//---------------------------------- if data aligning is not desired ------------------- |
always @(reg_sd_data) |
mp_data_out <= reg_sd_data; |
`endif |
|
// |
// DO_READ DO_WRITE DO_MODESET |
// signal generation |
// |
|
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
do_read <= `LO; |
do_write <= `LO; |
do_modeset <= `LO; |
do_state <= 3'b000; |
busy_a_ena <= `HI; |
end |
else |
case (do_state) |
// hang in here until a read or write is requested |
// (mp_rd_l = 1'b0) or (mp_wr_l = 1'b0) |
3'b000: begin |
// a read request |
if (~mp_rd_l & ~mp_cs_l) begin |
do_read <= `HI; |
do_state <= 3'b001; |
end |
// a write request |
else if (~mp_wr_l & ~mp_cs_l & sdram_mode_set_l) begin |
do_write <= `HI; |
do_state <= 3'b001; |
end |
// a mode set request |
else if (~mp_wr_l & ~mp_cs_l & ~sdram_mode_set_l) begin |
do_modeset <= `HI; |
do_state <= 3'b001; |
end |
else |
do_state <= 3'b000; |
end |
|
// This cycle is dummy cycle. Just to extend 'busy_ena_a' |
// to a total of 2 cycles |
3'b001: |
begin |
busy_a_ena <= `LO; // disable busy_a generation |
if (do_write) |
do_state <= 3'b011; |
else if (do_read) |
do_state <= 3'b010; |
else if (do_modeset) |
do_state <= 3'b110; |
else |
do_state <= 3'b001; |
end |
|
// hang in here until the sdramcnt has acknowledged the |
// read |
3'b010: |
if (do_read_ack) begin |
do_read <= `LO; |
do_state <= 3'b100; |
end |
else |
do_state <= 3'b010; |
|
// hang in here until the sdramcnt has acknowledged the |
// write |
3'b011: |
if (do_write_ack) begin |
do_write <= `LO; |
do_state <= 3'b101; |
end |
else |
do_state <= 3'b011; |
|
// wait in here until the host has read the data |
// (i.e. has raised its mp_rd_l high) |
3'b100: |
if (mp_rd_l) begin |
busy_a_ena <= `HI; // re-enable busy_a generation |
do_state <= 3'b000; |
end |
else |
do_state <= 3'b100; |
|
// wait in here until the host has relinquieshed the write bus |
// (i.e. has raised its mp_wr_l high) |
3'b101: |
if (mp_wr_l) begin |
busy_a_ena <= `HI; // re-enable busy_a generation |
do_state <= 3'b000; |
end |
else |
do_state <= 3'b101; |
|
// hang in here until the sdramcnt has acknowledged the |
// mode set |
3'b110: |
if (do_modeset_ack) begin |
do_modeset <= `LO; |
do_state <= 3'b101; |
end else |
do_state <= 3'b110; |
|
|
endcase |
|
|
|
|
endmodule |
|
/tags/sdram_8Mb_2Mx32_020200/micro.v
0,0 → 1,327
`include "tst_inc.h" |
`include "inc.h" |
|
|
//******************************************************************************* |
// S Y N T H E S I Z A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
module micro( |
// system connections |
sys_clk, |
sys_rst_l, |
|
// Connections to the HOSTCONT.V |
sdram_busy_l, |
mp_addx, |
mp_data_out, |
mp_data_in, |
mp_wr_l, |
mp_rd_l, |
mp_cs_l, |
mp_size, |
next_state, |
data_is_correct, |
sdram_mode_set_l, |
|
// debug |
top_state |
); |
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
// system connections |
input sys_clk; // main system clock |
input sys_rst_l; // main system reset |
|
// connections to the SDRAM CONTROLLER |
input sdram_busy_l; |
output [22:0] mp_addx; |
output mp_wr_l; |
output mp_rd_l; |
output mp_cs_l; |
output [1:0] mp_size; |
input [3:0] next_state; |
output [31:0] mp_data_out; // data bus to the SDRAM controller |
input [31:0] mp_data_in; // data bus from the SDRAM controller |
output data_is_correct; |
output sdram_mode_set_l; |
|
// debug |
output [3:0] top_state; |
|
// Intermodule connections |
wire [7:0] bus_state; |
wire data_ena; |
wire [31:0] mp_data_out; |
wire [31:0] mp_data_in; |
wire [1:0] mp_size; |
|
// Memory element definitions |
reg [3:0] top_state; |
reg mp_cs_l; |
reg mp_wr_l; |
reg mp_rd_l; |
reg [31:0] reg_mp_data_out; |
reg [22:0] reg_mp_addx; |
reg [22:0] reg_byte_counter; |
reg data_is_correct; |
reg sdram_mode_set_l; |
|
|
/* |
** SINGLE WRITE FOLLOWED BY GAP THEN FOLLOWED BY SINGLE READ TEST |
** |
*/ |
`ifdef do_read_write_test |
`endif |
|
|
/* |
** BURST WRITE FOLLOWED BY GAP THEN FOLLOWED BY BURST READ TEST |
** |
*/ |
`ifdef do_burst_write_read_test |
|
`endif |
|
|
/* |
** A ONE-TIME BURST WRITE FOLLOWED BY GAP THEN FOLLOWED BY MANY BURST READ TEST |
** |
*/ |
`ifdef do_single_burst_write_read_test |
|
// the number of write/read in the test |
`define RW_COUNT 23'h000015 |
// number of clock ticks between the reads. |
`define GAP_DELAY 23'h000030 |
// define the amount of address delta |
`define MP_ADDX_DELTA 23'h000001 |
// define the amount of data delta |
`define MP_DATA_DELTA 32'h01010101 |
|
|
// Micro Simulator State Machine State Definitions |
`define powerup_delay 4'h0 |
`define burst_write_cs 4'h1 |
`define burst_write_assert_wr 4'h2 |
`define burst_write_wait_4_busy 4'h3 |
`define burst_write_deassert_wr 4'h4 |
`define burst_wr_rd_delay 4'h5 |
`define burst_read_cs 4'h6 |
`define burst_read_assert_rd 4'h7 |
`define burst_read_wait_4_busy 4'h8 |
`define burst_read_deassert_rd 4'h9 |
`define request_modereg 4'ha |
|
`define SIZE_IS_BYTE 2'b01 |
`define SIZE_IS_HALF_WORD 2'b10 |
`define SIZE_IS_WORD 2'b00 |
|
|
assign mp_size = `SIZE_IS_BYTE; |
assign mp_addx = reg_mp_addx; |
assign mp_data_out = reg_mp_data_out; |
|
always @(posedge sys_clk or negedge sys_rst_l) |
if (~sys_rst_l) begin |
top_state <= `powerup_delay; // initialze state |
mp_cs_l <= `HI; |
mp_wr_l <= `HI; |
mp_rd_l <= `HI; |
reg_mp_addx <= 23'h000000; // reset address counter |
reg_mp_data_out <= 32'h00000000; // reset data counter |
reg_byte_counter <= 23'h000000; // clear byte counter |
data_is_correct <= `HI; // correct by default |
sdram_mode_set_l <= `HI; // do not issue mode reg change by default |
end |
else case (top_state) |
|
// Wait until the SDRAM has completed its power-up sequences |
`powerup_delay: begin |
sdram_mode_set_l <= `HI; |
if (next_state==`state_idle) |
top_state <= `burst_write_cs;// go and do burst write |
else |
top_state <= `powerup_delay; |
end |
|
// Assert MP CS to begin the write |
`burst_write_cs: begin |
mp_cs_l <= `LO; |
top_state <= `burst_write_assert_wr; |
end |
|
// Assert MP WR |
`burst_write_assert_wr: begin |
mp_wr_l <= `LO; |
top_state <= `burst_write_wait_4_busy; |
end |
|
// Wait until the SDRAM controller is no longer busy |
`burst_write_wait_4_busy: |
if (~sdram_busy_l) |
top_state <= `burst_write_wait_4_busy; |
else |
top_state <= `burst_write_deassert_wr; |
|
// Deassert the WR, and check to see if it has completed all writes |
`burst_write_deassert_wr: begin |
mp_wr_l <= `HI; // deassert WR |
if (reg_byte_counter == `RW_COUNT) begin |
reg_mp_addx <= 0; |
reg_mp_data_out <= 0; |
reg_byte_counter <= 0; // reset the counter |
mp_cs_l <= `HI; |
top_state <= `burst_wr_rd_delay; |
end else begin |
reg_mp_addx <= reg_mp_addx + `MP_ADDX_DELTA; |
reg_mp_data_out <= reg_mp_data_out + `MP_DATA_DELTA; |
reg_byte_counter <= reg_byte_counter + 1; // one IO done |
top_state <= `burst_write_assert_wr; |
end |
end |
|
// Wait here and kill GAP_DELAY number of cycles |
`burst_wr_rd_delay: |
if (reg_byte_counter != `GAP_DELAY) begin |
reg_byte_counter <= reg_byte_counter + 1; |
top_state <= `burst_wr_rd_delay; |
end else begin |
reg_byte_counter <= 23'h000000; |
top_state <= `burst_read_cs; |
end |
|
// Assert MP CS to prepare for reads |
`burst_read_cs: begin |
mp_cs_l <= `LO; // assert CS |
top_state <= `burst_read_assert_rd; |
end |
|
// Assert MP RD |
`burst_read_assert_rd: begin |
mp_rd_l <= `LO; |
top_state <= `burst_read_wait_4_busy; |
end |
|
// Wait until the SDRAM Controller is no longer busy |
`burst_read_wait_4_busy: |
if (~sdram_busy_l) |
top_state <= `burst_read_wait_4_busy; |
else |
top_state <= `burst_read_deassert_rd; |
|
|
// Deassert MP RD and Prepare for the next resd, |
`burst_read_deassert_rd: begin |
if (mp_data_in != reg_mp_data_out) begin |
data_is_correct <= `LO; |
end |
mp_rd_l <= `HI; // deassert RD |
if (reg_byte_counter == `RW_COUNT) begin |
reg_mp_addx <= 0; |
reg_mp_data_out <= 0; |
reg_byte_counter <= 0; // reset the counter |
mp_cs_l <= `HI; |
top_state <= `burst_wr_rd_delay; |
end else begin |
reg_mp_addx <= reg_mp_addx + `MP_ADDX_DELTA; // increment addx |
reg_mp_data_out <= reg_mp_data_out + `MP_DATA_DELTA; // increment data expected |
reg_byte_counter <= reg_byte_counter + 1; // one IO done |
top_state <= `burst_read_assert_rd; |
end |
end |
|
endcase |
|
|
`endif |
|
|
endmodule |
|
/tags/sdram_8Mb_2Mx32_020200/tst_inc.h
0,0 → 1,106
//******************************************************************************* |
// S Y N T H E Z I A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
|
|
/* |
** SELECT TEST TO PERFORM |
** Select only one of the below comment |
** |
*/ |
|
// *************************************************************** |
// This test does a one time burst write, followed by a delay (enough to |
// fit a few refresh cycles) then burst read of the same memory |
// areas. The burst reads are repeating. |
// *************************************************************** |
`define do_single_burst_write_read_test |
|
|
|
// C O M M O N S T U F F |
`define HI 1'b1 |
`define LO 1'b0 |
|
|
/tags/sdram_8Mb_2Mx32_020200/sdram.v
0,0 → 1,483
`include "inc.h" |
|
//******************************************************************************* |
// S Y N T H E Z I A B L E S D R A M C O N T R O L L E R C O R E |
// |
// This core adheres to the GNU Public License |
// |
// This is a synthesizable Synchronous DRAM controller Core. As it stands, |
// it is ready to work with 8Mbyte SDRAMs, organized as 2M x 32 at 100MHz |
// and 125MHz. For example: Samsung KM432S2030CT, Fujitsu MB81F643242B. |
// |
// The core has been carefully coded so as to be "platform-independent". |
// It has been successfully compiled and simulated under three separate |
// FPGA/CPLD platforms: |
// Xilinx Foundation Base Express V2.1i |
// Altera Max+PlusII V9.21 |
// Lattice ispExpert V7.0 |
// |
// The interface to the host (i.e. microprocessor, DSP, etc) is synchronous |
// and supports ony one transfer at a time. That is, burst-mode transfers |
// are not yet supported. In may ways, the interface to this core is much |
// like that of a typical SRAM. The hand-shaking between the host and the |
// SDRAM core is done through the "sdram_busy_l" signal generated by the |
// core. Whenever this signal is active low, the host must hold the address, |
// data (if doing a write), size and the controls (cs, rd/wr). |
// |
// Connection Diagram: |
// SDRAM side: |
// sd_wr_l connect to -WR pin of SDRAM |
// sd_cs_l connect to -CS pin of SDRAM |
// sd_ras_l connect to -RAS pin of SDRAM |
// sd_cas_l connect to -CAS pin of SDRAM |
// sd_dqm[3:0] connect to the DQM3,DQM2,DQM1,DQM0 pins |
// sd_addx[10:0] connect to the Address bus [10:0] |
// sd_data[31:0] connect to the data bus [31:0] |
// sd_ba[1:0] connect to BA1, BA0 pins of SDRAM |
// |
// HOST side: |
// mp_addx[22:0] connect to the address bus of the host. |
// 23 bit address bus give access to 8Mbyte |
// of the SDRAM, as byte, half-word (16bit) |
// or word (32bit) |
// mp_data_in[31:0] Unidirectional bus connected to the data out |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data_out[31:0] Unidirectional bus connected to the data in |
// of the host. To use this, enable |
// "databus_is_unidirectional" in INC.H |
// mp_data[31:0] Bi-directional bus connected to the host's |
// data bus. To use the bi-directionla bus, |
// disable "databus_is_unidirectional" in INC.H |
// mp_rd_l Connect to the -RD output of the host |
// mp_wr_l Connect to the -WR output of the host |
// mp_cs_l Connect to the -CS of the host |
// mp_size[1:0] Connect to the size output of the host |
// if there is one. When set to 0 |
// all trasnfers are 32 bits, when set to 1 |
// all transfers are 8 bits, and when set to |
// 2 all xfers are 16 bits. If you want the |
// data to be lower order aligned, turn on |
// "align_data_bus" option in INC.H |
// sdram_busy_l Connect this to the wait or hold equivalent |
// input of the host. The host, must hold the |
// bus if it samples this signal as low. |
// sdram_mode_set_l When a write occurs with this set low, |
// the SDRAM's mode set register will be programmed |
// with the data supplied on the data_bus[10:0]. |
// |
// |
// Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com |
// |
//******************************************************************************* |
// |
// Hierarchy: |
// |
// SDRAM.V Top Level Module |
// HOSTCONT.V Controls the interfacing between the micro and the SDRAM |
// SDRAMCNT.V This is the SDRAM controller. All data passed to and from |
// is with the HOSTCONT. |
// optional |
// MICRO.V This is the built in SDRAM tester. This module generates |
// a number of test logics which is used to test the SDRAM |
// It is basically a Micro bus generator. |
// |
/* |
*/ |
|
|
|
module sdram( |
// SYSTEM LEVEL CONNECTIONS |
sys_rst_l, |
sys_clk, |
// SDRAM CONNECTIONS |
sd_wr_l, |
sd_cs_l, |
sd_ras_l, |
sd_cas_l, |
sd_dqm, |
sd_addx, |
sd_data, |
sd_ba, |
// MICROPORCESSOR CONNECTION |
mp_addx |
`ifdef databus_is_unidirectional |
, |
mp_data_in, |
mp_data_out, |
`else |
, |
mp_data, |
`endif |
mp_rd_l, |
mp_wr_l, |
mp_cs_l, |
sdram_mode_set_l, |
sdram_busy_l, |
mp_size, |
next_state |
|
// DEBUG |
`ifdef show_debug |
, |
next_state, |
mp_data_out_sd, |
mp_data_gate |
do_write, |
reg_mp_addx, |
reg_mp_data_mux, |
sd_addx_mux, |
sd_addx10_mux, |
next_state, |
doing_refresh, |
do_modeset, |
do_read, |
sd_addx_mux, |
sd_addx10_mux, |
autorefresh_cntr, |
autorefresh_cntr_l, |
pwrup, |
top_state, |
wr_cntr, |
mp_data_micro, |
mp_data_mux, |
sd_data_ena, |
mp_data_out, |
sd_addx_mux, |
sd_addx10_mux, |
sd_rd_ena |
`endif |
); |
|
|
|
|
|
// **************************************** |
// |
// I/O DEFINITION |
// |
// **************************************** |
// SYSTEM LEVEL CONNECTIONS |
input sys_clk; // global system clock. Runs the sdram state machine |
input sys_rst_l; // global active low asynchronous system reset |
// SDRAM CONNECTIONS |
output sd_wr_l; // SDRAM active low WRITE signal |
output sd_cs_l; // SDRAM active low chip select signal |
output sd_ras_l; // SDRAM active low RAS |
output sd_cas_l; // SDRAM active low CAS |
output [3:0] sd_dqm; // SDRAM data masks |
output [10:0] sd_addx; // SDRAM multiplexed address bus |
inout [31:0] sd_data; // SDRAM birectional data bus 32 bit |
output [1:0] sd_ba; // SDRAM bank address , aka A11 |
// MICROPROCESSOR CONNECTION |
`ifdef databus_is_unidirectional |
input [31:0] mp_data_in; |
output [31:0] mp_data_out; |
`else |
`ifdef simulate_mp |
inout [31:0] mp_data; |
`else |
output [31:0] mp_data; |
`endif |
`endif |
`ifdef simulate_mp |
output [22:0] mp_addx; // HOST address bus. 23 bits for 8Mb |
output mp_rd_l; // HOST active low READ |
output mp_wr_l; // HOST active low WRITE |
output mp_cs_l; // HOST active low chip select |
output sdram_mode_set_l; |
output [1:0] mp_size; // 00=32bits, 10=16bits, 01=8bits |
`else |
input [22:0] mp_addx; // HOST address bus. 23 bits for 8Mb |
input mp_rd_l; // HOST active low READ |
input mp_wr_l; // HOST active low WRITE |
input mp_cs_l; // HOST active low chip select |
input sdram_mode_set_l; |
input [1:0] mp_size; // 00=32bits, 10=16bits, 01=8bits |
`endif |
output sdram_busy_l; |
output [3:0] next_state; |
// DEBUG |
`ifdef show_debug |
output [31:0] mp_data_out_sd; |
output mp_data_gate; |
output do_write; |
output [22:0] reg_mp_addx; |
output [31:0] reg_mp_data_mux; |
output sd_addx_mux; |
output sd_addx10_mux; |
output do_modeset; |
output do_read; |
output doing_refresh; |
output [3:0] next_state; |
output [12:0] autorefresh_cntr; |
output autorefresh_cntr_l; |
output pwrup; |
output [3:0] top_state; |
output [7:0] wr_cntr; |
//output[31:0] mp_data_micro; |
output [31:0] mp_data_out; |
//output mp_data_mux; |
output sd_data_ena; |
output sd_rd_ena; |
`endif |
|
|
// INTER-MODULE CONNECTIONS |
wire do_modeset; |
wire do_read; |
wire do_write; |
wire doing_refresh; |
wire sd_addx_ena; |
wire [1:0] sd_addx_mux; |
wire [1:0] sd_addx10_mux; |
wire sd_rd_ena; |
wire sd_data_ena; |
wire [2:0] modereg_cas_latency; |
wire [2:0] modereg_burst_length; |
wire [3:0] next_state; |
wire [31:0] mp_data_out_sd; |
wire [31:0] mp_data_in; |
//wire [31:0] sd_data; |
wire mp_cs_l; |
wire mp_wr_l; |
wire mp_rd_l; |
wire mp_data_mux; |
wire [3:0] autorefresh_cntr; |
wire autorefresh_cntr_l; |
wire pwrup; |
wire [3:0] top_state; |
wire [22:0] reg_mp_addx; |
wire [3:0] decoded_dqm; |
wire do_write_ack; |
wire do_read_ack; |
wire do_modeset_ack; |
wire [31:0] reg_mp_data_mux; |
wire [31:0] sd_data_in; |
wire [31:0] sd_data_out; |
wire [31:0] reg_sd_data; |
wire sdram_mode_set_l; |
wire sys_clk; |
wire sdram_busy_l; |
wire mp_data_gate; |
wire [31:0] mp_simulator_data; |
|
// |
// HOST sie DATA BUS DRISVERS |
// |
// |
// |
assign mp_data_gate = (~mp_rd_l & ~mp_cs_l); |
// --- Unidirectional Data bus Mos |
`ifdef databus_is_unidirectional |
`ifdef simulate_mp |
assign mp_data_out = mp_data_gate ? mp_data_out_sd : mp_simulator_data; |
`else |
assign mp_data_out = mp_data_gate ? mp_data_out_sd : 32'h00000000; |
`endif |
// --- Bi-Directional Data bus Mode |
`else |
`ifdef simulate_mp |
assign mp_data = mp_data_gate ? mp_data_out_sd : mp_simulator_data; |
`else |
bufif1 m0 (mp_data[0], mp_data_out_sd[0], mp_data_gate); |
bufif1 m1 (mp_data[1], mp_data_out_sd[1], mp_data_gate); |
bufif1 m2 (mp_data[2], mp_data_out_sd[2], mp_data_gate); |
bufif1 m3 (mp_data[3], mp_data_out_sd[3], mp_data_gate); |
bufif1 m4 (mp_data[4], mp_data_out_sd[4], mp_data_gate); |
bufif1 m5 (mp_data[5], mp_data_out_sd[5], mp_data_gate); |
bufif1 m6 (mp_data[6], mp_data_out_sd[6], mp_data_gate); |
bufif1 m7 (mp_data[7], mp_data_out_sd[7], mp_data_gate); |
bufif1 m8 (mp_data[8], mp_data_out_sd[8], mp_data_gate); |
bufif1 m9 (mp_data[9], mp_data_out_sd[9], mp_data_gate); |
bufif1 m10 (mp_data[10], mp_data_out_sd[10], mp_data_gate); |
bufif1 m11 (mp_data[11], mp_data_out_sd[11], mp_data_gate); |
bufif1 m12 (mp_data[12], mp_data_out_sd[12], mp_data_gate); |
bufif1 m13 (mp_data[13], mp_data_out_sd[13], mp_data_gate); |
bufif1 m14 (mp_data[14], mp_data_out_sd[14], mp_data_gate); |
bufif1 m15 (mp_data[15], mp_data_out_sd[15], mp_data_gate); |
bufif1 m16 (mp_data[16], mp_data_out_sd[16], mp_data_gate); |
bufif1 m17 (mp_data[17], mp_data_out_sd[17], mp_data_gate); |
bufif1 m18 (mp_data[18], mp_data_out_sd[18], mp_data_gate); |
bufif1 m19 (mp_data[19], mp_data_out_sd[19], mp_data_gate); |
bufif1 m20 (mp_data[20], mp_data_out_sd[20], mp_data_gate); |
bufif1 m21 (mp_data[21], mp_data_out_sd[21], mp_data_gate); |
bufif1 m22 (mp_data[22], mp_data_out_sd[22], mp_data_gate); |
bufif1 m23 (mp_data[23], mp_data_out_sd[23], mp_data_gate); |
bufif1 m24 (mp_data[24], mp_data_out_sd[24], mp_data_gate); |
bufif1 m25 (mp_data[25], mp_data_out_sd[25], mp_data_gate); |
bufif1 m26 (mp_data[26], mp_data_out_sd[26], mp_data_gate); |
bufif1 m27 (mp_data[27], mp_data_out_sd[27], mp_data_gate); |
bufif1 m28 (mp_data[28], mp_data_out_sd[28], mp_data_gate); |
bufif1 m29 (mp_data[29], mp_data_out_sd[29], mp_data_gate); |
bufif1 m30 (mp_data[30], mp_data_out_sd[30], mp_data_gate); |
bufif1 m31 (mp_data[31], mp_data_out_sd[31], mp_data_gate); |
assign mp_data_in = mp_data; |
`endif |
`endif |
|
|
// |
// SDRAM side bidirectional data bus drivers |
//assign sd_data = sd_data_ena ? sd_data_out : 32'hzzzzzzzz; |
// |
bufif1 b0 (sd_data[0], sd_data_out[0], sd_data_ena); |
bufif1 b1 (sd_data[1], sd_data_out[1], sd_data_ena); |
bufif1 b2 (sd_data[2], sd_data_out[2], sd_data_ena); |
bufif1 b3 (sd_data[3], sd_data_out[3], sd_data_ena); |
bufif1 b4 (sd_data[4], sd_data_out[4], sd_data_ena); |
bufif1 b5 (sd_data[5], sd_data_out[5], sd_data_ena); |
bufif1 b6 (sd_data[6], sd_data_out[6], sd_data_ena); |
bufif1 b7 (sd_data[7], sd_data_out[7], sd_data_ena); |
bufif1 b8 (sd_data[8], sd_data_out[8], sd_data_ena); |
bufif1 b9 (sd_data[9], sd_data_out[9], sd_data_ena); |
bufif1 b10 (sd_data[10], sd_data_out[10], sd_data_ena); |
bufif1 b11 (sd_data[11], sd_data_out[11], sd_data_ena); |
bufif1 b12 (sd_data[12], sd_data_out[12], sd_data_ena); |
bufif1 b13 (sd_data[13], sd_data_out[13], sd_data_ena); |
bufif1 b14 (sd_data[14], sd_data_out[14], sd_data_ena); |
bufif1 b15 (sd_data[15], sd_data_out[15], sd_data_ena); |
bufif1 b16 (sd_data[16], sd_data_out[16], sd_data_ena); |
bufif1 b17 (sd_data[17], sd_data_out[17], sd_data_ena); |
bufif1 b18 (sd_data[18], sd_data_out[18], sd_data_ena); |
bufif1 b19 (sd_data[19], sd_data_out[19], sd_data_ena); |
bufif1 b20 (sd_data[20], sd_data_out[20], sd_data_ena); |
bufif1 b21 (sd_data[21], sd_data_out[21], sd_data_ena); |
bufif1 b22 (sd_data[22], sd_data_out[22], sd_data_ena); |
bufif1 b23 (sd_data[23], sd_data_out[23], sd_data_ena); |
bufif1 b24 (sd_data[24], sd_data_out[24], sd_data_ena); |
bufif1 b25 (sd_data[25], sd_data_out[25], sd_data_ena); |
bufif1 b26 (sd_data[26], sd_data_out[26], sd_data_ena); |
bufif1 b27 (sd_data[27], sd_data_out[27], sd_data_ena); |
bufif1 b28 (sd_data[28], sd_data_out[28], sd_data_ena); |
bufif1 b29 (sd_data[29], sd_data_out[29], sd_data_ena); |
bufif1 b30 (sd_data[30], sd_data_out[30], sd_data_ena); |
bufif1 b31 (sd_data[31], sd_data_out[31], sd_data_ena); |
assign sd_data_in = sd_data; |
|
|
|
|
// |
// INSTANTIATE THE SDRAM STATE MACHINE |
// |
sdramcnt MYSDRAMCNT( |
// system level stuff |
.sys_rst_l(sys_rst_l), |
.sys_clk(sys_clk), |
|
// SDRAM connections |
.sd_wr_l(sd_wr_l), |
.sd_cs_l(sd_cs_l), |
.sd_ras_l(sd_ras_l), |
.sd_cas_l(sd_cas_l), |
.sd_dqm(sd_dqm), |
|
// Host Controller connections |
.do_mode_set(do_modeset), |
.do_read(do_read), |
.do_write(do_write), |
.doing_refresh(doing_refresh), |
.sd_addx_mux(sd_addx_mux), |
.sd_addx10_mux(sd_addx10_mux), |
.sd_rd_ena(sd_rd_ena), |
.sd_data_ena(sd_data_ena), |
.modereg_cas_latency(modereg_cas_latency), |
.modereg_burst_length(modereg_burst_length), |
.mp_data_mux(mp_data_mux), |
.decoded_dqm(decoded_dqm), |
.do_write_ack(do_write_ack), |
.do_read_ack(do_read_ack), |
.do_modeset_ack(do_modeset_ack), |
.pwrup(pwrup), |
|
// debug |
.next_state(next_state), |
.autorefresh_cntr(autorefresh_cntr), |
.autorefresh_cntr_l(autorefresh_cntr_l) |
); |
|
|
|
// |
// INSTANTIATE THE HOST INTERFACE LOGIC |
// |
hostcont MYHOSTCONT( |
// system connections |
.sys_rst_l(sys_rst_l), |
.sys_clk(sys_clk), |
|
// microprocessor side connections |
.mp_addx(mp_addx), |
`ifdef simulate_mp |
.mp_data_in(mp_simulator_data), |
`else |
.mp_data_in(mp_data_in), |
`endif |
.mp_data_out(mp_data_out_sd), |
.mp_rd_l(mp_rd_l), |
.mp_wr_l(mp_wr_l), |
.mp_cs_l(mp_cs_l), |
.sdram_mode_set_l(sdram_mode_set_l), |
.sdram_busy_l(sdram_busy_l), |
.mp_size(mp_size), |
|
// SDRAM side connections |
.sd_addx(sd_addx), |
.sd_data_in(sd_data), |
.sd_data_out(sd_data_out), |
.sd_ba(sd_ba), |
|
// SDRAMCNT side |
.sd_addx10_mux(sd_addx10_mux), |
.sd_addx_mux(sd_addx_mux), |
.sd_rd_ena(sd_rd_ena), |
.do_read(do_read), |
.do_write(do_write), |
.doing_refresh(doing_refresh), |
.do_modeset(do_modeset), |
.modereg_cas_latency(modereg_cas_latency), |
.modereg_burst_length(modereg_burst_length), |
.mp_data_mux(mp_data_mux), |
.decoded_dqm(decoded_dqm), |
.do_write_ack(do_write_ack), |
.do_read_ack(do_read_ack), |
.do_modeset_ack(do_modeset_ack), |
.pwrup(pwrup), |
|
// debug |
.reg_mp_data_mux(reg_mp_data_mux), |
.reg_mp_addx(reg_mp_addx), |
.reg_sd_data(reg_sd_data) |
); |
|
|
`ifdef simulate_mp |
micro SDRAM_TESTER( |
// system connections |
.sys_clk(sys_clk), |
.sys_rst_l(sys_rst_l), |
|
// Connections to the HOSTCONT.V |
.sdram_busy_l(sdram_busy_l), |
.mp_addx(mp_addx), |
.mp_data_out(mp_simulator_data), |
.mp_data_in(mp_data_out_sd), |
.mp_wr_l(mp_wr_l), |
.mp_rd_l(mp_rd_l), |
.mp_cs_l(mp_cs_l), |
.mp_size(mp_size), |
.next_state(next_state), |
.data_is_correct(data_is_correct), |
.sdram_mode_set_l(sdram_mode_set_l), |
|
// debug |
.top_state(top_state) |
); |
`endif |
|
endmodule |
|
|