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