implement (almost) complete SDRAM init sequence

Tue, 10 Aug 2010 13:23:58 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 10 Aug 2010 13:23:58 +0100
changeset 2
ceaa61ebf8a2
parent 1
05af11892ed8
child 3
6a724779fb48

implement (almost) complete SDRAM init sequence

wb_sdram.v file | annotate | diff | revisions
     1.1 diff -r 05af11892ed8 -r ceaa61ebf8a2 wb_sdram.v
     1.2 --- a/wb_sdram.v	Tue Aug 10 12:58:34 2010 +0100
     1.3 +++ b/wb_sdram.v	Tue Aug 10 13:23:58 2010 +0100
     1.4 @@ -76,7 +76,7 @@
     1.5  localparam M_WritePrecharge	= 6'b110100;
     1.6  localparam M_Read					= 6'b100101;
     1.7  localparam M_ReadPrecharge		= 6'b110101;
     1.8 -localparam M_ModeRegister		= 6'b0X0000;
     1.9 +localparam M_LoadModeRegister	= 6'b0X0000;
    1.10  localparam M_Nop					= 6'b0X0111;
    1.11  localparam M_BurstStop			= 6'b0X0110;
    1.12  localparam M_Inhibit				= 6'b0X1XXX;		// maybe X1111?
    1.13 @@ -86,9 +86,18 @@
    1.14  /****
    1.15   * Finite State Machine
    1.16   ****/
    1.17 -localparam	ST_INIT1			= 32'd0;
    1.18 -localparam	ST_INIT2			= 32'd1;
    1.19 -localparam	ST_NOP			= 32'd999;
    1.20 +localparam	ST_INIT1							= 32'd0;
    1.21 +localparam	ST_INIT2							= 32'd1;
    1.22 +localparam	ST_NOP1							= 32'd2;
    1.23 +localparam	ST_PrechargeAll				= 32'd3;
    1.24 +localparam	ST_PrechargeAll_Wait			= 32'd4;
    1.25 +localparam	ST_AutoRefresh1				= 32'd5;
    1.26 +localparam	ST_AutoRefresh1_Wait			= 32'd6;
    1.27 +localparam	ST_AutoRefresh2				= 32'd7;
    1.28 +localparam	ST_AutoRefresh2_Wait			= 32'd8;
    1.29 +localparam	ST_LoadModeRegister			= 32'd9;
    1.30 +localparam	ST_LoadModeRegister_Wait	= 32'd10;
    1.31 +localparam	ST_Spin							= 32'd999;
    1.32   
    1.33  reg [31:0] state;
    1.34  always @(posedge wb_clk_i) begin
    1.35 @@ -134,7 +143,7 @@
    1.36  					// the end of the power-up wait, then bring CKE high.
    1.37  					if (timer == 32'd0) begin
    1.38  						// Timer hit zero. Send a NOP.
    1.39 -						state <= ST_NOP;
    1.40 +						state <= ST_NOP1;
    1.41  					end else if (timer < 32'd50) begin
    1.42  						// Timer value is more than zero but less than 50; CKE is on, but
    1.43  						// keep waiting for the timer to actually expire.
    1.44 @@ -145,11 +154,95 @@
    1.45  					sdram_mode <= M_Inhibit;
    1.46  				end
    1.47  				
    1.48 -			ST_NOP: begin
    1.49 -					// Spinstate. Hold SDRAM in NOP.
    1.50 -					debug <= 3'd7;
    1.51 +			ST_NOP1: begin
    1.52 +					// Apply one or more NOP commands to the SDRAM
    1.53 +					sdram_mode <= M_Nop;
    1.54 +					state <= ST_PrechargeAll;
    1.55 +				end
    1.56 +				
    1.57 +			ST_PrechargeAll: begin
    1.58 +					// Precharge All, then wait T_rp (20ns)
    1.59 +					sdram_mode <= M_PrechargeAll;
    1.60 +					timer <= 32'd0;	// wait 1tcy (40ns)   ---> TIMER HERE
    1.61 +					state <= ST_PrechargeAll_Wait;
    1.62 +				end
    1.63 +
    1.64 +			ST_PrechargeAll_Wait: begin
    1.65 +					// Wait for T_rp after Precharge All
    1.66 +					sdram_mode <= M_Nop;
    1.67 +					if (timer == 32'd0) begin
    1.68 +						// Timer hit zero. Continue
    1.69 +						state <= ST_AutoRefresh1;
    1.70 +					end
    1.71 +				end
    1.72 +				
    1.73 +			ST_AutoRefresh1: begin
    1.74 +					// Auto Refresh 1 of 2, wait T_rfc (70ns) after each
    1.75 +					sdram_mode <= M_AutoRefresh;
    1.76 +					timer <= 32'd1;	// wait 2tcy (80ns)  ---> TIMER HERE
    1.77 +					state <= ST_AutoRefresh1_Wait;
    1.78 +				end
    1.79 +				
    1.80 +			ST_AutoRefresh1_Wait: begin
    1.81 +					// Wait for T_rfc
    1.82  					sdram_mode <= M_Nop;
    1.83 -					state <= ST_NOP;
    1.84 +					if (timer == 32'd0) begin
    1.85 +						// Timer hit zero. Continue
    1.86 +						state <= ST_AutoRefresh2;
    1.87 +					end
    1.88 +				end
    1.89 +				
    1.90 +			ST_AutoRefresh2: begin
    1.91 +					// Auto Refresh 2 of 2, wait T_rfc (70ns) after each
    1.92 +					sdram_mode <= M_AutoRefresh;
    1.93 +					timer <= 32'd1;	// wait 2tcy (80ns)  ---> TIMER HERE
    1.94 +					state <= ST_AutoRefresh2_Wait;
    1.95 +				end
    1.96 +				
    1.97 +			ST_AutoRefresh2_Wait: begin
    1.98 +					// Wait for T_rfc
    1.99 +					sdram_mode <= M_Nop;
   1.100 +					if (timer == 32'd0) begin
   1.101 +						// Timer hit zero. Continue
   1.102 +						state <= ST_LoadModeRegister;
   1.103 +					end
   1.104 +				end
   1.105 +
   1.106 +			ST_LoadModeRegister: begin
   1.107 +					// Load Mode Register
   1.108 +					/**
   1.109 +					 * Mode register:
   1.110 +					 *   - BS0,1  = 00  [RFU]
   1.111 +					 *   - A11,10 = 00  [RFU]
   1.112 +					 *   - A9     = 0   [WBL -- write burst length same as read burst length]
   1.113 +					 *   - A8,7   = 00  [Test Mode off]
   1.114 +					 *   - A6..4  = 010 [CAS Latency = 2 clocks]
   1.115 +					 *   - A3     = 0   [Burst type = sequential]
   1.116 +					 *   - A2..0  = 000 [Burst length = 1 word]
   1.117 +					 */
   1.118 +					sdram_ba <= 2'b00;
   1.119 +					sdram_addr <= 12'b00_0_00_010_000;
   1.120 +					sdram_mode <= M_LoadModeRegister;
   1.121 +
   1.122 +					// Wait T_mrd (2 clock cycles)
   1.123 +					timer <= 32'd1;	// (2cy)-1  ---> TIMER HERE
   1.124 +					state <= ST_LoadModeRegister_Wait;
   1.125 +				end
   1.126 +
   1.127 +			ST_LoadModeRegister_Wait: begin
   1.128 +					// Wait for LMR to complete
   1.129 +					sdram_mode <= M_Nop;
   1.130 +					sdram_ba <= 2'd0;
   1.131 +					sdram_addr <= 12'd0;
   1.132 +					if (timer == 32'd0) begin
   1.133 +						// Timer hit zero. Continue
   1.134 +						state <= ST_Spin;
   1.135 +					end
   1.136 +				end
   1.137 +
   1.138 +			ST_Spin: begin
   1.139 +					sdram_mode <= M_Inhibit;
   1.140 +					state <= ST_Spin;
   1.141  				end
   1.142  		endcase
   1.143  	end