[wb_sdram] remove test logic and convert into a proper WISHBONE peripheral

Tue, 10 Aug 2010 18:33:25 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Tue, 10 Aug 2010 18:33:25 +0100
changeset 7
001f5282bff0
parent 6
39984d9ff640
child 8
b00018dfe8e5

[wb_sdram] remove test logic and convert into a proper WISHBONE peripheral

wb_sdram.v file | annotate | diff | revisions
     1.1 --- a/wb_sdram.v	Tue Aug 10 18:04:05 2010 +0100
     1.2 +++ b/wb_sdram.v	Tue Aug 10 18:33:25 2010 +0100
     1.3 @@ -16,7 +16,7 @@
     1.4  	input						wb_we_i,				// WISHBONE write enable (R/#W)
     1.5  	input						wb_cyc_i,			// WISHBONE cycle
     1.6  	input						wb_stb_i,			// WISHBONE strobe
     1.7 -	output					wb_ack_o,			// WISHBONE cycle acknowledge (data available, DTACK)
     1.8 +	output reg				wb_ack_o,			// WISHBONE cycle acknowledge (data available, DTACK)
     1.9  	output					wb_err_o,			// WISHBONE bus error
    1.10  	output					wb_rty_o,			// WISHBONE retry-later
    1.11  	
    1.12 @@ -117,10 +117,10 @@
    1.13  wire [11:0] row_addr;
    1.14  wire [1:0] bank_addr;
    1.15  
    1.16 -// Convert a 22-bit linear address into an SDRAM address
    1.17 +// Convert a 23-bit linear address into an SDRAM address
    1.18  assign column_addr	= wb_adr_i[8:0];
    1.19  assign bank_addr		= wb_adr_i[10:9];
    1.20 -assign row_addr		= wb_adr_i[21:11];
    1.21 +assign row_addr		= wb_adr_i[22:11];
    1.22  
    1.23  
    1.24  /****
    1.25 @@ -140,17 +140,16 @@
    1.26  localparam	ST_Spin							= 32'd11;		// <<== main 'spin' / 'idle' state
    1.27  localparam	ST_Refresh						= 32'd12;
    1.28  localparam	ST_Refresh_Wait				= 32'd13;
    1.29 -localparam	ST_Test_Activate				= 32'd500;
    1.30 -localparam	ST_Test_Activate_Wait		= 32'd501;
    1.31 -localparam	ST_Test_Read					= 32'd502;
    1.32 -localparam	ST_Test_Read_Wait				= 32'd503;
    1.33 -localparam	ST_Test_Read_Finish			= 32'd504;
    1.34 -localparam	ST_Test_Write					= 32'd505;
    1.35 -localparam	ST_Test_Precharge_All		= 32'd506;
    1.36 -localparam	ST_Test_Precharge_All_Wait	= 32'd507;
    1.37 +localparam	ST_Activate						= 32'd30;
    1.38 +localparam	ST_Activate_Wait				= 32'd31;
    1.39 +localparam	ST_Write							= 32'd32;
    1.40 +localparam	ST_Read							= 32'd33;
    1.41 +localparam	ST_Read_Wait					= 32'd34;
    1.42 +localparam	ST_Wait_Trp						= 32'd35;
    1.43 +localparam	ST_Ack							= 32'd36;
    1.44 +
    1.45   
    1.46  reg [31:0] state;
    1.47 -reg [31:0] captured_data;
    1.48  always @(posedge wb_clk_i) begin
    1.49  	if (wb_rst_i) begin
    1.50  		// Initialise state machine and timer
    1.51 @@ -299,7 +298,11 @@
    1.52  					// Enable refresh timer
    1.53  					refresh_timer_en <= 1'b1;
    1.54  
    1.55 +					// Idle the SDRAM (Inhibit is lower power than NOP on some SDRAMs)
    1.56  					sdram_mode <= M_Inhibit;
    1.57 +					
    1.58 +					// Clear the WISHBONE Ack flag -- NOTE: is this required?
    1.59 +					wb_ack_o <= 1'b0;
    1.60  
    1.61  					if (refresh_req) begin
    1.62  						// Refresh request received. Ack it and do a refresh.
    1.63 @@ -307,9 +310,17 @@
    1.64  						state <= ST_Refresh;
    1.65  					end else begin
    1.66  						//state <= ST_Spin;		// NOTE: turned off to run a ram test...
    1.67 -						state <= ST_Test_Activate;
    1.68 +						//state <= ST_Test_Activate;
    1.69 +						if (wb_cyc_i & wb_stb_i) begin
    1.70 +							// CYC and STB high. A Wishbone cycle just started.
    1.71 +							state <= ST_Activate;
    1.72 +						end
    1.73  					end
    1.74  				end
    1.75 +
    1.76 +/////
    1.77 +// Refresh logic
    1.78 +/////
    1.79  				
    1.80  			ST_Refresh: begin
    1.81  					// Refresh timer timed out; do a refresh run
    1.82 @@ -330,79 +341,90 @@
    1.83  						state <= ST_Spin;
    1.84  					end
    1.85  				end
    1.86 -				
    1.87 -			ST_Test_Activate: begin
    1.88 -					// Activate bank
    1.89 +
    1.90 +//////
    1.91 +// R/W logic
    1.92 +//////
    1.93 +			ST_Activate: begin
    1.94 +					// Activate the required bank
    1.95  					sdram_mode <= M_BankActivate;
    1.96  					sdram_addr <= row_addr;
    1.97 -					sdram_ba <= bank_addr;
    1.98 -					timer <= 32'd0;	// wait Trcd (20ns ideally, this is 40ns)		---> TIMER HERE
    1.99 -					state <= ST_Test_Activate_Wait;
   1.100 +					sdram_ba   <= bank_addr;
   1.101 +					timer <= 32'd0;		// Wait T_rcd (20ns ideally, here 40ns)	---> TIMER HERE
   1.102 +					state <= ST_Activate_Wait;
   1.103  				end
   1.104  				
   1.105 -			ST_Test_Activate_Wait: begin
   1.106 -					// Wait for Activate Bank to complete
   1.107 +			ST_Activate_Wait: begin
   1.108 +					// Wait for T_rcd
   1.109  					sdram_mode <= M_Nop;
   1.110  					if (timer == 32'd0) begin
   1.111 -						state <= ST_Test_Read;
   1.112 +						if (wb_we_i) begin
   1.113 +							// Write cycle.
   1.114 +							state <= ST_Write;
   1.115 +						end else begin
   1.116 +							// Read cycle
   1.117 +							state <= ST_Read;
   1.118 +						end
   1.119  					end
   1.120  				end
   1.121  				
   1.122 -			ST_Test_Read: begin
   1.123 -					// Do the Read operation
   1.124 -					sdram_mode <= M_Read;
   1.125 -					sdram_addr <= column_addr;
   1.126 -					sdram_dqm <= 4'b0000;		// Allow data through (DQM = OE# = 1 to mask off, 0 to allow)
   1.127 -					timer <= 32'd2 - 32'd1;		// wait CAS# Latency (2 clock cycles)	---> TIMER HERE
   1.128 -					state <= ST_Test_Read_Wait;
   1.129 +			ST_Write: begin
   1.130 +					// Write cycle handler
   1.131 +					sdram_mode	<= M_WritePrecharge;
   1.132 +					sdram_addr	<= column_addr;
   1.133 +					sdram_dq_r	<= wb_dat_i;
   1.134 +					sdram_dq_oe	<= 1'b1;		// FPGA drives the DQ bus
   1.135 +					sdram_dqm	<= 4'b0000;	// TODO: use WB_SEL_I to set these
   1.136 +					
   1.137 +					// Wait T_rp (20ns)
   1.138 +					timer <= 32'd0;	// wait 1tcy (40ns)   ---> TIMER HERE
   1.139 +					state <= ST_Wait_Trp;
   1.140 +				end
   1.141 +
   1.142 +			ST_Read: begin
   1.143 +					// Read cycle handler
   1.144 +					sdram_mode	<= M_ReadPrecharge;
   1.145 +					sdram_addr	<= column_addr;
   1.146 +					sdram_dq_oe	<= 1'b0;		// SDRAM drives the DQ bus
   1.147 +					sdram_dqm	<= 4'b0000;	// Grab all the data (it's just easier that way...)
   1.148 +					timer <= 32'd2 - 32'd1;	// CAS# Latency ---> TIMER HERE
   1.149 +					state <= ST_Read_Wait;
   1.150  				end
   1.151  				
   1.152 -			ST_Test_Read_Wait: begin
   1.153 -					// Wait for CAS latency
   1.154 -					sdram_mode <= M_Nop;
   1.155 -					sdram_dqm <= 4'b1111;		// Disable SDRAM output buffers
   1.156 +			ST_Read_Wait: begin
   1.157 +					// Wait for CAS# latency
   1.158 +					sdram_mode	<= M_Nop;
   1.159 +					sdram_dqm	<= 4'b1111;	// Make SDRAM DQ bus float
   1.160  					if (timer == 32'd0) begin
   1.161 -						state <= ST_Test_Read_Finish;
   1.162 -						captured_data <= sdram_dq;
   1.163 +						// Latch data
   1.164 +						wb_dat_o <= sdram_dq;
   1.165 +						// Wait T_rp (20ns)
   1.166 +						timer <= 32'd0;	// wait 1tcy (40ns)   ---> TIMER HERE
   1.167 +						state <=	ST_Wait_Trp;
   1.168  					end
   1.169  				end
   1.170  
   1.171 -			ST_Test_Read_Finish: begin
   1.172 -					// Additional NOP after read to avoid bus contention if next transaction is a write
   1.173 -					sdram_mode <= M_Nop;
   1.174 -					sdram_dqm <= 4'b1111;	// Disable SDRAM output buffers
   1.175 -					state <= ST_Test_Write;
   1.176 -				end
   1.177 -			
   1.178 -			ST_Test_Write: begin
   1.179 -					// Write to SDRAM
   1.180 -					sdram_mode <= M_Write;
   1.181 -					sdram_addr <= column_addr;
   1.182 -					sdram_dq_r <= ~captured_data; //32'h55AA_BCDE;
   1.183 -					sdram_dq_oe <= 1'b1;		// output enable
   1.184 -					sdram_dqm <= 4'b0000;		// Allow data through (DQM = OE# = 1 to mask off, 0 to allow)
   1.185 -					state <= ST_Test_Precharge_All;
   1.186 -				end
   1.187 -				
   1.188 -			ST_Test_Precharge_All: begin
   1.189 -					// Precharge All
   1.190 -					sdram_mode <= M_PrechargeAll;
   1.191 -					sdram_addr <= 12'd0;
   1.192 -					sdram_dq_oe <= 1'b0;		// output disable
   1.193 -					sdram_dqm <= 4'b1111;		// Disable SDRAM output buffers
   1.194 -					sdram_dq_r <= 32'd0;
   1.195 -					state <= ST_Spin;
   1.196 -					// Wait T_rp (20ns)
   1.197 -					timer <= 32'd0;	// wait 1tcy (40ns)   ---> TIMER HERE
   1.198 -					state <= ST_Test_Precharge_All_Wait;
   1.199 +			ST_Wait_Trp: begin
   1.200 +					// Wait for T_rp, then ack
   1.201 +					if (timer == 32'd0) begin
   1.202 +						state <= ST_Ack;
   1.203 +					end
   1.204  				end
   1.205  
   1.206 -			ST_Test_Precharge_All_Wait: begin
   1.207 -					// Wait for T_rp after Precharge All
   1.208 -					sdram_mode <= M_Nop;
   1.209 -					if (timer == 32'd0) begin
   1.210 -						// Timer hit zero. Continue
   1.211 -						state <= ST_Spin;
   1.212 +			ST_Ack: begin
   1.213 +					// Ack the transfer to the WISHBONE host
   1.214 +					sdram_mode	<= M_Nop;
   1.215 +					sdram_addr	<= 32'd0;
   1.216 +					sdram_dq_r	<= 32'd0;
   1.217 +					sdram_dq_oe	<= 1'b0;		// SDRAM drives the DQ bus
   1.218 +					sdram_dqm	<= 4'b1111;	// mask off DQM
   1.219 +					if (wb_cyc_i & wb_stb_i) begin
   1.220 +						// CYC and STB high, ack the transfer
   1.221 +						wb_ack_o		<= 1'b1;
   1.222 +						state			<= ST_Ack;
   1.223 +					end else begin
   1.224 +						// CYC and STB low, back to the start again...
   1.225 +						state			<= ST_Spin;
   1.226  					end
   1.227  				end
   1.228  		endcase