head 1.3; access; symbols sdram_8Mb_2Mx32_020200:1.3 sdram_8Mb_2Mx32:1.2 sdram:1.1.1.1 sdram_30_nov_1999:1.1.1.1 opencores:1.1.1; locks; strict; comment @# @; 1.3 date 2001.02.03.04.42.14; author jlee; state Exp; branches; next 1.2; 1.2 date 2001.01.13.03.09.25; author jlee; state Exp; branches; next 1.1; 1.1 date 2001.11.30.22.08.22; author jlee; state Exp; branches 1.1.1.1; next ; 1.1.1.1 date 2001.11.30.22.08.22; author jlee; state Exp; branches; next ; desc @@ 1.3 log @2Mx32 updated on 020200 @ text @`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 @ 1.2 log @Working version of 2Mx32 organization @ text @d4 1 a4 1 // 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 d132 2 a133 1 reg_sd_data d190 1 a202 1 reg [10:0] reg_modeset_i; d365 1 a365 1 always @@(sd_addx10_mux or reg_mp_data or reg_mp_addx) d369 1 a369 1 2'b10: sd_addx[10] <= reg_mp_data[10]; @ 1.1 log @Initial revision @ text @d3 82 d86 1 a86 10 ** HOSTCONT.v ** ** This module is the host controller whic sits between the host ** (usually a micro) and the sdramcnt.v ** ** ** ** */ d102 1 d106 2 a107 1 sd_data, a108 1 sd_wr_l, a113 1 sd_data_ena, a117 1 next_state, d121 5 a126 2 // bus type select smart_h d130 3 a132 3 ,dumb_busy_out ,dumb_busy_clk, reg_mp_data_mux d148 3 a150 3 input [19:0] mp_addx; // 20 bits for the addx input [15:0] mp_data_in; // 16 bits of data bus input output [15:0] mp_data_out; // 16 bits of data bus output d156 1 d160 4 a163 3 inout [15:0] sd_data; // 16 bits of bidirectional SDRAM data bus output sd_ba; // bank select output to the SDRAM input sd_wr_l; a168 1 input sd_data_ena; a172 1 input [3:0] next_state; d176 6 a182 4 // other inputs input smart_h; // If high, indicates that writes are non // blocking if SDRAM is not busy. Else, // all IO are blocked d186 3 a188 3 output dumb_busy_clk; output dumb_busy_out; output [15:0] reg_mp_data_mux; d196 4 a199 6 reg [19:0] reg_mp_addx; reg [15:0] reg_mp_data; reg [15:0] reg_sd_data; `ifdef simulate_mp wire [10:0] reg_modeset; `else d201 1 a201 1 `endif d205 1 d207 8 a214 6 reg sd_ba; reg rst_do_write; wire [15:0] sd_data; wire [15:0] sd_data_buff; wire [15:0] reg_mp_data_mux; wire [15:0] mp_data_out; d217 1 d219 2 d222 1 a222 1 wire modereg_ena; d226 1 d228 2 a229 5 wire dumb_busy_clk; wire dumb_busy_rst; reg rst_dumb_busy; reg dumb_busy_out; wire dumb_busy; a231 1 assign mp_data_out = reg_sd_data; d236 3 a238 2 assign read_busy = do_read; assign write_busy = do_write; d255 5 a259 1 assign sdram_busy_l = ~(read_busy | write_busy | dumb_busy | doing_refresh); d265 35 a299 8 // mp_rd_l or mp_wr_l always @@(do_write or sys_rst_l or mp_addx) if (~sys_rst_l) reg_mp_addx <= 20'h00000; else if (~do_write) // hold the addx if do_write==`HI reg_mp_addx <= mp_addx; else reg_mp_addx <= reg_mp_addx; d304 21 a324 10 always @@(posedge mp_wr_l or negedge sys_rst_l) if (~sys_rst_l) reg_mp_data <= 16'h0000; else if (~mp_cs_l) reg_mp_data <= mp_data_in; // MODE REG LATCH `ifdef simulate_mp assign reg_modeset = 11'h0020; d326 2 a327 7 assign modereg_ena = ~mp_cs_l & ~sdram_mode_set_l; always @@(posedge mp_wr_l or negedge sys_rst_l) if (~sys_rst_l) reg_modeset <= 11'h0020; // default modeset reg value has this settings: // burst length=1, cas latency=2 else if (modereg_ena) reg_modeset <= mp_data_in; d331 17 a347 1 // SD DATA LATCH d350 1 a350 1 reg_sd_data <= 16'h0000; d355 8 d366 1 a366 3 // 2'b00: sd_addx[10] <= 1'b0; // 2'b01: sd_addx[10] <= reg_mp_addx[10]; 2'b00: sd_addx[10] <= reg_mp_addx[18]; d374 2 a375 4 // 2'b00: sd_addx[9:0] <= reg_mp_addx[9:0]; // 2'b01: sd_addx[9:0] <= {2'b00, reg_mp_addx[18:11]}; 2'b00: sd_addx[9:0] <= reg_mp_addx[17:8]; // ROW 2'b01: sd_addx[9:0] <= {2'b00, reg_mp_addx[7:0]}; // COLUMN d384 3 a386 3 2'b00: sd_ba <= reg_mp_addx[19]; 2'b01: sd_ba <= reg_mp_addx[19]; default: sd_ba <= 1'b0; a389 4 // SD SIDE DATA BUFFERS assign sd_data = sd_data_ena ? reg_mp_data_mux : 16'hzzzz; assign sd_data_buff = sd_data; d392 1 a392 1 assign reg_mp_data_mux = mp_data_mux ? 16'h0000 : reg_mp_data; d394 28 d424 2 a425 1 // DO_READ signal generation a426 8 // Set by falling edge of mp_rd_l // cleared by the falling edge of next_state==`state_read assign do_read_clk = ( mp_rd_l | (next_state==`state_read) ); always @@(negedge do_read_clk or negedge sys_rst_l) if (~sys_rst_l) do_read <= `LO; else do_read <= ~do_read; d428 3 a430 13 // DO_WRITE signal generation logic // This signal indicates that the SDRAM is performing a write // this is a completely asynchronous logic which does the following: // the do_write is // set at rising edge of mp_wr_l (at deassertion of micro write bus cycle) // cleared on the rising edge of sd_wr_l. That is, at the termination of // current SDRAM write cycle. This excludes the sd_wr_l generated during the // refresh cycle. assign do_write_rst = ~sys_rst_l | rst_do_write; always @@(posedge mp_wr_l or posedge do_write_rst) if (do_write_rst) d432 4 d437 86 a522 1 do_write <= `HI; a523 16 always @@(posedge sd_wr_l or posedge do_write_rst) if (do_write_rst) rst_do_write <= `LO; else if (~doing_refresh) // reset only is we're not a refresh cycle rst_do_write <= `HI; // // DO_MODESET signal generation // // needs to be triggered by falling edge of always @@(sys_clk or sys_rst_l) if (sys_rst_l) do_modeset <= `LO; else do_modeset <= `LO; d525 2 a528 39 // // DUMB BUSY SIGNAL GENERATION // // In the "dumb" mode (smart_h == 0), the SDRAM controller will // not allow the micro to do another I/O until the // present one is finished. The most notable difference is // that it will not allow a "dump-&-run" writes. // // The busy signal is asserted at the falling edge of mp_cs_l. // In the case of writes, it is deasserted when mp_rw_l goes low. This // allows the micro to deassert its wr (i.e. finish the write bus cycle) // at which point the busy is again asserted (since the SDRAM is now being written) // until the completion of the write into the SDRAM. // During reads, the busy is asserted on the falling edge of mp_cs_l, and is not // deasserted until the completion of the read. // // The busy signal is the or of DO_WRITE , DO_READ as before, but // in the smart_h=0 mode, an extra signal dumb_busy_out is also or'd. // This signal is set at the falling edge of mp_cs_l. It is cleared // on the falling edge of mp_wr_l or on the rising edge of do_read. // (mp_wr_l ^ do_read) // // It is set by the falling edge of MP_CS_L // is is cleared by the rising edge of DO_READ or // falling edge of mp_WR_L assign dumb_busy = (dumb_busy_out & ~smart_h); always @@(negedge mp_cs_l or posedge dumb_busy_rst) if (dumb_busy_rst) dumb_busy_out <= `LO; else dumb_busy_out <= `HI; assign dumb_busy_rst = ~sys_rst_l | rst_dumb_busy; assign dumb_busy_clk = do_read ^ mp_wr_l; always @@(negedge dumb_busy_clk or posedge dumb_busy_rst) if (dumb_busy_rst) rst_dumb_busy <= `LO; else rst_dumb_busy <= `HI; @ 1.1.1.1 log @Initial import. @ text @@