Tue, 10 Aug 2010 13:23:58 +0100
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