Tue, 10 Aug 2010 14:41:06 +0100
add refresh timer and refresh FSM logic
wb_sdram.v | file | annotate | diff | revisions |
1.1 --- a/wb_sdram.v Tue Aug 10 13:23:58 2010 +0100 1.2 +++ b/wb_sdram.v Tue Aug 10 14:41:06 2010 +0100 1.3 @@ -32,7 +32,7 @@ 1.4 inout [31:0] sdram_dq, // SDRAM data bus 1.5 1.6 // Debugging 1.7 - output reg [2:0] debug // debug bits 1.8 + output /*reg*/ [2:0] debug // debug bits 1.9 ); 1.10 1.11 1.12 @@ -84,6 +84,32 @@ 1.13 1.14 1.15 /**** 1.16 + * Refresh Timer 1.17 + ****/ 1.18 +parameter REFRESH_INTERVAL = 32'd390 - 32'd1; 1.19 +reg [31:0] refresh_timer; 1.20 +reg refresh_req, refresh_ack, refresh_timer_en; 1.21 +always @(posedge wb_clk_i) begin 1.22 + if (wb_rst_i | !refresh_timer_en) begin 1.23 + // Reset; clear timer, unset REFRESH REQUEST 1.24 + refresh_req <= 1'b0; 1.25 + refresh_timer <= REFRESH_INTERVAL; 1.26 + end else if (refresh_ack) begin 1.27 + // Refresh Ack, clear Refresh Request. 1.28 + refresh_req <= 1'b0; 1.29 + end else if (refresh_timer == 0) begin 1.30 + // Refresh timer timed out, make a Refresh Request and reload the timer 1.31 + refresh_req <= 1'b1; 1.32 + refresh_timer <= REFRESH_INTERVAL; 1.33 + end else begin 1.34 + // Otherwise just decrement the timer 1.35 + refresh_timer <= refresh_timer - 32'd1; 1.36 + end 1.37 +end 1.38 + 1.39 +assign debug = { 1'b0, refresh_req, refresh_ack }; 1.40 + 1.41 +/**** 1.42 * Finite State Machine 1.43 ****/ 1.44 localparam ST_INIT1 = 32'd0; 1.45 @@ -97,15 +123,21 @@ 1.46 localparam ST_AutoRefresh2_Wait = 32'd8; 1.47 localparam ST_LoadModeRegister = 32'd9; 1.48 localparam ST_LoadModeRegister_Wait = 32'd10; 1.49 -localparam ST_Spin = 32'd999; 1.50 +localparam ST_Spin = 32'd11; // <<== main 'spin' / 'idle' state 1.51 +localparam ST_Refresh = 32'd12; 1.52 +localparam ST_Refresh_Wait = 32'd13; 1.53 1.54 reg [31:0] state; 1.55 always @(posedge wb_clk_i) begin 1.56 if (wb_rst_i) begin 1.57 // Initialise state machine and timer 1.58 state <= ST_INIT1; 1.59 - debug <= 3'd0; 1.60 +// debug <= 3'd0; 1.61 timer <= 32'd0; 1.62 + 1.63 + // Clear REFRESH ACK flag and disable refresh timer 1.64 + refresh_ack <= 1'b0; 1.65 + refresh_timer_en <= 1'b0; 1.66 1.67 // Initialisation state for SDRAM 1.68 sdram_cke <= 1'b0; 1.69 @@ -149,7 +181,7 @@ 1.70 // keep waiting for the timer to actually expire. 1.71 sdram_cke <= 1'b1; 1.72 state <= ST_INIT2; 1.73 - debug <= 3'd1; 1.74 +// debug <= 3'd1; 1.75 end 1.76 sdram_mode <= M_Inhibit; 1.77 end 1.78 @@ -241,8 +273,38 @@ 1.79 end 1.80 1.81 ST_Spin: begin 1.82 + // Enable refresh timer 1.83 + refresh_timer_en <= 1'b1; 1.84 + 1.85 sdram_mode <= M_Inhibit; 1.86 - state <= ST_Spin; 1.87 + 1.88 + if (refresh_req) begin 1.89 + // Refresh request received. Ack it and do a refresh. 1.90 + refresh_ack <= 1'b1; 1.91 + state <= ST_Refresh; 1.92 + end else begin 1.93 + state <= ST_Spin; 1.94 + end 1.95 + end 1.96 + 1.97 + ST_Refresh: begin 1.98 + // Refresh timer timed out; do a refresh run 1.99 + // Start by clearing the ACK flag (which was set by the Spin state) 1.100 + refresh_ack <= 1'b0; 1.101 + // Tell the SDRAM to do a Refresh 1.102 + sdram_mode <= M_AutoRefresh; 1.103 + // Wait for T_rfc 1.104 + timer <= 32'd1; // wait Trfc (70ns ideally, we give 80ns) ---> TIMER HERE 1.105 + state <= ST_Refresh_Wait; 1.106 + end 1.107 + 1.108 + ST_Refresh_Wait: begin 1.109 + // Wait for T_rfc 1.110 + sdram_mode <= M_Nop; 1.111 + if (timer == 32'd0) begin 1.112 + // Timer hit zero. Go back to spin state. 1.113 + state <= ST_Spin; 1.114 + end 1.115 end 1.116 endcase 1.117 end