`include "inc.h" // // SDRAMCNT.v // // SDRAM controller. // This module can control Synchronous DRAMS such as // Samsumg's KM416S1020/KM416S1120 1MB X 16 // NEC's uPD451616 1MB X 16 // Oki's MSM56V16160 // // The SDRAM's internal MODE REGISTER is also programmable. // // module sdramcnt( // system level stuff sys_rst_l, sys_clk, // SDRAM connections sd_clke, sd_wr_l, sd_cs_l, sd_ras_l, sd_cas_l, sd_ldqm, sd_udqm, // 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, // debug next_state, autorefresh_cntr, autorefresh_cntr_l, pwrup, cntr_limit ); // **************************************** // // 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 sd_ldqm; output sd_udqm; output sd_clke; // 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; // Debug output [3:0] next_state; output [12:0] autorefresh_cntr; output autorefresh_cntr_l; output pwrup; 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 sd_ldqm; reg sd_udqm; 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 [12:0] autorefresh_cntr; reg autorefresh_cntr_l; assign sd_clke = `HI; // clk always enabled // State Machine always @(posedge sys_clk or negedge sys_rst_l) if (~sys_rst_l) begin next_state autorefresh_cntr_l refresh_cntr_l pwrup sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_data_ena sd_addx_mux sd_addx10_mux sd_rd_ena mp_data_mux // refresh_cntr burst_cntr_ena doing_refresh end else case (next_state) // Power Up state `state_powerup: begin next_state sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_data_ena sd_addx_mux sd_rd_ena pwrup burst_cntr_ena refresh_cntr_l end // PRECHARGE both banks `state_precharge: begin // refresh_cntr sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_addx10_mux if ( (refresh_cntr == cntr_limit) & (pwrup == `HI) ) begin doing_refresh // refresh_cntr refresh_cntr_l next_state pwrup end else begin doing_refresh next_state end end // Autorefresh `state_auto_refresh: begin sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_addx10_mux next_state autorefresh_cntr_l end // Autor Refresh Delay -- extends the AutoRefresh CMD by // AUTO_REFRESH_WIDTH counts `state_auto_refresh_dly: begin if (autorefresh_cntr == `AUTO_REFRESH_WIDTH) begin autorefresh_cntr_l sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm // If all refresh is done if ((refresh_cntr == cntr_limit) & (pwrup == `LO)) begin doing_refresh // refresh_cntr refresh_cntr_l if (do_write | do_read) next_state else next_state end // IF refresh cycles not done yet.. else next_state end end // MODE SET state `state_modeset: begin next_state sd_wr_l sd_cs_l sd_ras_l sd_cas_l if (~pwrup) begin // select a10-a0 to be the data from mode set reg sd_addx_mux sd_addx10_mux end end // IDLE state `state_idle: begin sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_data_ena sd_addx10_mux mp_data_mux if (do_write | do_read ) next_state else if (do_mode_set) next_state else if (do_refresh) begin next_state refresh_cntr_l end end // SET RAS state `state_set_ras: begin sd_cs_l sd_ras_l sd_addx_mux next_state end // RAS delay state. This state may not be necessary for most // cases. Fow now, it is here to kill 1-cycle time `state_ras_dly: begin sd_cs_l sd_ras_l if (do_write) next_state else next_state end // WRITE state `state_write: begin sd_cs_l sd_cas_l sd_addx_mux // remember that the mp_addr[19] is the sd_ba sd_addx10_mux sd_data_ena sd_wr_l sd_ldqm sd_udqm next_state end // SET CAS state `state_set_cas: begin sd_cs_l sd_cas_l sd_addx_mux sd_addx10_mux sd_ldqm sd_udqm next_state end `state_cas_latency1: begin sd_cs_l sd_cas_l if (modereg_cas_latency==3'b010) begin next_state burst_cntr_ena end else next_state end `state_cas_latency2: begin next_state burst_cntr_ena end `state_read: begin if (burst_length_cntr == modereg_burst_count) begin burst_cntr_ena sd_rd_ena next_state end else sd_rd_ena end `state_cool_off: begin sd_wr_l sd_cs_l sd_ras_l sd_cas_l sd_ldqm sd_udqm sd_addx10_mux mp_data_mux next_state end endcase // This counter is used to extend the width of the Auto Refresh // command. It was found that if the AutoRefresh CMD set to be the default of // 1 SDRAM_CLK cycle, then an AutoRefresh CMD in the middle of a burst read // would mess-up the remining burst reads. By extending the Auto Refresh cycle // to 2 or more, this burst read problem was solved. As to why this happens // I did not investigate further. always @(posedge sys_clk or negedge autorefresh_cntr_l) if (~autorefresh_cntr_l) autorefresh_cntr else autorefresh_cntr // This mux selects the cycle limit value for the // auto refresh counter always @(pwrup) case (pwrup) /* `HI: cntr_limit default: cntr_limit */ 1'b1: cntr_limit default: 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 else burst_length_cntr // // REFRESH_CNTR // always @(posedge sys_clk or negedge refresh_cntr_l) if (~refresh_cntr_l) refresh_cntr else if (next_state == `state_auto_refresh) refresh_cntr // // BURST LENGTH SELECTOR // always @(modereg_burst_length) case (modereg_burst_length) 3'b000: modereg_burst_count 3'b001: modereg_burst_count 3'b010: modereg_burst_count default modereg_burst_count 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 refresh_timer 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) refresh_timer else refresh_state // 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 // 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 refresh_timer end endcase endmodule