add refresh timer and refresh FSM logic

Tue, 10 Aug 2010 14:41:06 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 10 Aug 2010 14:41:06 +0100
changeset 3
6a724779fb48
parent 2
ceaa61ebf8a2
child 4
96badb38531d

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