`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). // // // Author: Jeung Joon Lee joon.lee@quantum.com, cmosexod@ix.netcom.com // // modified by : Dirk Leinenbach dirkl@wjpserver.cs.uni-sb.de // //******************************************************************************* // // 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_dqm0, sd_dqm1, sd_dqm2, sd_dqm3, // 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_dqm0, decoded_dqm1, decoded_dqm2, decoded_dqm3, 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 [1:0] sd_dqm0; output [1:0] sd_dqm1; output [1:0] sd_dqm2; output [1:0] sd_dqm3; // 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 [1:0] decoded_dqm0; input [1:0] decoded_dqm1; input [1:0] decoded_dqm2; input [1:0] decoded_dqm3; 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 [1:0] sd_dqm0; reg [1:0] sd_dqm1; reg [1:0] sd_dqm2; reg [1:0] sd_dqm3; 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 // $strobe("LLL1 %t : State Sys-Reset",$time); next_state <= #100 `state_powerup; autorefresh_cntr_l <= #100 `LO; refresh_cntr_l <= #100 `LO; pwrup <= #100 `HI; // high indicates we've just power'd up or RESET sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_dqm0 <= #100 2'b11; sd_dqm1 <= #100 2'b11; sd_dqm2 <= #100 2'b11; sd_dqm3 <= #100 2'b11; sd_data_ena <= #100 `LO; sd_addx_mux <= #100 2'b10; // select the mode reg default value sd_addx10_mux <= #100 2'b11; // select 1 as default sd_rd_ena <= #100 `LO; mp_data_mux <= #100 `LO; // refresh_cntr<= #100 13'h0000; burst_cntr_ena <= #100 `LO; // do not enable the burst counter doing_refresh <= #100 `LO; do_write_ack <= #100 `LO; // do not ack as reset default do_read_ack <= #100 `LO; // do not ack as reset default do_modeset_ack <= #100 `LO; // do not ack as reset default do_refresh_ack <= #100 `LO; end else case (next_state) // Power Up state `state_powerup: begin // $strobe ("LLL1 %t : State Powerup",$time); next_state <= #100 `state_precharge; sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_dqm0 <= #100 2'b11; sd_dqm1 <= #100 2'b11; sd_dqm2 <= #100 2'b11; sd_dqm3 <= #100 2'b11; sd_data_ena <= #100 `LO; sd_addx_mux <= #100 2'b10; sd_rd_ena <= #100 `LO; pwrup <= #100 `HI; // this is the power up run burst_cntr_ena <= #100 `LO; // do not enable the burst counter refresh_cntr_l <= #100 `HI; // allow the refresh cycle counter to count end // PRECHARGE both (or all) banks `state_precharge: begin // $strobe ("LLL1 %t : State Precharge",$time); sd_wr_l <= #100 `LO; sd_cs_l <= #100 `LO; sd_ras_l <= #100 `LO; sd_cas_l <= #100 `HI; sd_dqm0 <= #100 2'b11; sd_dqm1 <= #100 2'b11; sd_dqm2 <= #100 2'b11; sd_dqm3 <= #100 2'b11; sd_addx10_mux <= #100 2'b11; // A10 = 1'b1 next_state <= #100 `state_idle; if (do_write_ack) do_write_ack<= #100 `LO; // done acknowledging the write request if (do_read_ack) do_read_ack <= #100 `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 // $strobe ("LLL1 %t : State Delay-Trp",$time); sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; if ( (refresh_cntr == cntr_limit) & (pwrup == `HI) ) begin doing_refresh <= #100 `LO; // refresh cycle is done refresh_cntr_l <= #100 `LO; // ..reset refresh counter next_state <= #100 `state_modeset; // if this was power-up, then go and set mode reg end else begin doing_refresh <= #100 `HI; // indicate that we're doing refresh next_state <= #100 `state_auto_refresh; end end // Autorefresh `state_auto_refresh: begin // $strobe ("LLL1 %t : State Auto-Refresh",$time); sd_wr_l <= #100 `HI; sd_cs_l <= #100 `LO; sd_ras_l <= #100 `LO; sd_cas_l <= #100 `LO; sd_addx10_mux <= #100 2'b01; // A10 = 0 next_state <= #100 `state_auto_refresh_dly; autorefresh_cntr_l <= #100 `HI; //allow refresh delay cntr (Trc) to tick do_refresh_ack <= #100 `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 // $strobe ("LLL1 %t : State Auto-Refresh Delay",$time); sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_addx10_mux <= #100 2'b00; // select ROW again A10 = A20 // Wait for Trc if (autorefresh_cntr == 4'h6) begin autorefresh_cntr_l <= #100 `LO; // reset Trc delay counter // Check if the number of specified back-back refreshes are done if (refresh_cntr == cntr_limit) begin doing_refresh <= #100 `LO; // refresh cycle is done refresh_cntr_l <= #100 `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 <= #100 `state_set_ras; // go service a pending read or write if any else next_state <= #100 `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 <= #100 `state_modeset; end // IF refresh cycles not done yet, keep issuing autorefresh commands else next_state <= #100 `state_auto_refresh; end // If Trc has not expired else begin next_state <= #100 `state_auto_refresh_dly; do_refresh_ack <= #100 `LO; end end // MODE SET state `state_modeset: begin // $strobe ("LLL1 %t : State Modeset",$time); next_state <= #100 `state_idle; sd_wr_l <= #100 `LO; sd_cs_l <= #100 `LO; sd_ras_l <= #100 `LO; sd_cas_l <= #100 `LO; sd_addx_mux <= #100 2'b10; sd_addx10_mux <= #100 2'b10; doing_refresh <= #100 `LO; // deassert if (pwrup) pwrup <= #100 `LO; // ..no more in power up mode if (do_mode_set) do_modeset_ack <= #100 `LO; end // IDLE state `state_idle: begin // $strobe ("LLL1 %t : State Idle",$time); sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_data_ena <= #100 `LO; // turn off the data bus drivers mp_data_mux <= #100 `LO; // drive the SD data bus with normal data sd_addx_mux <= #100 2'b00; // select ROW (A[19:10]) of mp_addx to SDRAM sd_addx10_mux <= #100 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 <= #100 `HI; // indicate that we're doing refresh refresh_cntr_l <= #100 `HI; // allow refresh cycle counter to count up next_state <= #100 `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 <= #100 `state_set_ras; // if a mode register set is requested, go and service it else if (do_mode_set) begin do_modeset_ack <= #100 `HI; // acknowledge the mode set request next_state <= #100 `state_modeset; doing_refresh <= #100 `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 // $strobe ("LLL1 %t : State Set RAS",$time); sd_cs_l <= #100 `LO; // enable SDRAM sd_ras_l <= #100 `LO; // enable the RAS next_state <= #100 `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 // $strobe ("LLL1 %t : State RAS Delay",$time); sd_cs_l <= #100 `HI; // disable SDRAM sd_ras_l <= #100 `HI; // disble the RAS sd_addx_mux <= #100 2'b01; // select COLUMN sd_addx10_mux <= #100 2'b01; // select COLUMN if (do_write) begin sd_data_ena <= #100 `HI; // turn on the data bus drivers // sd_dqm braucht erst im naechsten Takt gesetzt zu werden // sd_dqm0 <= #100 decoded_dqm0; // masks the data which is meant to be // sd_dqm1 <= #100 decoded_dqm1; // masks the data which is meant to be //sd_dqm2 <= #100 decoded_dqm2; // masks the data which is meant to be //sd_dqm3 <= #100 decoded_dqm3; // masks the data which is meant to be next_state <= #100 `state_write; // if write, do the write end else begin sd_dqm0 <= #100 2'b00; // gelesen werden immer alle Bits sd_dqm1 <= #100 2'b00; // gelesen werden immer alle Bits sd_dqm2 <= #100 2'b00; // gelesen werden immer alle Bits sd_dqm3 <= #100 2'b00; // gelesen werden immer alle Bits next_state <= #100 `state_set_cas; // if read, do the read end end // WRITE state `state_write: begin // $strobe ("LLL1 %t : State Write",$time); sd_cs_l <= #100 `LO; // enable SDRAM sd_cas_l <= #100 `LO; // enable the CAS sd_wr_l <= #100 `LO; // enable the write do_write_ack<= #100 `HI; // acknowledge the write request // sd_dqm0 <= #100 2'b11; // damit die mask-bits einen Takt // sd_dqm1 <= #100 2'b11; // damit die mask-bits einen Takt // sd_dqm2 <= #100 2'b11; // damit die mask-bits einen Takt // sd_dqm3 <= #100 2'b11; // damit die mask-bits einen Takt sd_dqm0 <= #100 decoded_dqm0; // sd_dqm wurde einen Takt zu frueh gesetzt sd_dqm1 <= #100 decoded_dqm1; // sd_dqm wurde einen Takt zu frueh gesetzt sd_dqm2 <= #100 decoded_dqm2; // sd_dqm wurde einen Takt zu frueh gesetzt sd_dqm3 <= #100 decoded_dqm3; // sd_dqm wurde einen Takt zu frueh gesetzt next_state <= #100 `state_delay_Tras1; end `state_delay_Tras1: begin // $strobe ("LLL1 %t : State Delay Tras1",$time); sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_dqm0 <= #100 2'b11; sd_dqm1 <= #100 2'b11; sd_dqm2 <= #100 2'b11; sd_dqm3 <= #100 2'b11; sd_addx_mux <= #100 2'b00; // send ROW (A[19:10]) of mp_addx to SDRAM sd_addx10_mux <= #100 2'b00; // send ROW (A[20]) " " mp_data_mux <= #100 `HI; // drive the SD data bus with all zeros next_state <= #100 `state_delay_Tras2; end `state_delay_Tras2: begin // $strobe ("LLL1 %t : State Delay Tras2",$time); next_state <= #100 `state_precharge; end // SET CAS state `state_set_cas: begin // $strobe ("LLL1 %t : State Set CAS",$time); sd_cs_l <= #100 `LO; sd_cas_l <= #100 `LO; sd_dqm0 <= #100 2'b00; sd_dqm1 <= #100 2'b00; sd_dqm2 <= #100 2'b00; sd_dqm3 <= #100 2'b00; next_state <= #100 `state_cas_latency1; end `state_cas_latency1: begin // $strobe ("LLL1 %t : State CAS Latency1",$time); sd_cs_l <= #100 `HI; // disable CS sd_cas_l <= #100 `HI; // disable CAS sd_dqm0 <= #100 2'b11; sd_dqm1 <= #100 2'b11; sd_dqm2 <= #100 2'b11; sd_dqm3 <= #100 2'b11; if (modereg_cas_latency==3'b010) begin do_read_ack <= #100 `HI; // acknowledge the read request (do it here due to the latency) next_state <= #100 `state_read; // 2 cycles of lantency done. burst_cntr_ena <= #100 `HI; // enable he burst lenght counter end else next_state <= #100 `state_cas_latency2; // 3 cycles of latency end `state_cas_latency2: begin // $strobe ("LLL1 %t : State CAS Latency2",$time); next_state <= #100 `state_read; burst_cntr_ena <= #100 `HI; // enable the burst lenght counter do_read_ack <= #100 `HI; // acknowledge the read request (do it here due to the latency) end `state_read: begin // $strobe ("LLL1 %t : State Read sd_rd_ena:%b",$time,sd_rd_ena); if (burst_length_cntr == modereg_burst_count) begin burst_cntr_ena <= #100 `LO; // done counting; sd_rd_ena <= #100 `LO; // done with the reading next_state <= #100 `state_precharge; sd_wr_l <= #100 `HI; sd_cs_l <= #100 `HI; sd_ras_l <= #100 `HI; sd_cas_l <= #100 `HI; sd_addx_mux <= #100 2'b00; // send ROW (A[19:10]) of mp_addx to SDRAM sd_addx10_mux <= #100 2'b00; // send ROW (A[20]) " " mp_data_mux <= #100 `HI; // drive the SD data bus with all zeros end else begin sd_rd_ena <= #100 `HI; // enable the read latch on the next state next_state <= #100 `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 <= #100 4'h0; else autorefresh_cntr <= #100 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 <= #100 `power_up_ref_cntr_limit; default: cntr_limit <= #100 `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 <= #100 3'b000; // reset whenever 'burst_cntr_ena' is low else burst_length_cntr <= #100 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 <= #100 13'h0000; else if (next_state == `state_auto_refresh) refresh_cntr <= #100 refresh_cntr + 1; // // BURST LENGTH SELECTOR // always @(modereg_burst_length) case (modereg_burst_length) 3'b000: modereg_burst_count <= #100 4'h1; 3'b001: modereg_burst_count <= #100 4'h2; 3'b010: modereg_burst_count <= #100 4'h4; default modereg_burst_count <= #100 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 <= #100 `state_count; refresh_timer <= #100 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 <= #100 refresh_timer + 1; refresh_state <= #100 `state_count; end else begin refresh_state <= #100 `state_halt; refresh_timer <= #100 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 <= #100 `state_reset; */ if (do_refresh_ack) refresh_state <= #100 `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 <= #100 `state_count; refresh_timer <= #100 8'h00; end endcase endmodule