add clock generator DCM and preliminary homebrew WISHBONE SDRAM controller

Mon, 09 Aug 2010 20:45:49 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 09 Aug 2010 20:45:49 +0100
changeset 0
f797831bb66d
child 1
05af11892ed8

add clock generator DCM and preliminary homebrew WISHBONE SDRAM controller

wb_sdram.v file | annotate | diff | revisions
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/wb_sdram.v	Mon Aug 09 20:45:49 2010 +0100
     1.3 @@ -0,0 +1,157 @@
     1.4 +/****************************************************************************
     1.5 + *
     1.6 + *
     1.7 + ****************************************************************************/
     1.8 + 
     1.9 +module wb_sdram (
    1.10 +	// Clocks and resets
    1.11 +	input						wb_clk_i,			// WISHBONE clock
    1.12 +	input						wb_rst_i,			// WISHBONE reset
    1.13 +
    1.14 +	// WISHBONE bus
    1.15 +	input			[31:0]	wb_adr_i,			// WISHBONE address
    1.16 +	input			[31:0]	wb_dat_i,			// WISHBONE data in
    1.17 +	output reg	[31:0]	wb_dat_o,			// WISHBONE data out
    1.18 +	input			[3:0]		wb_sel_i,			// WISHBONE byte select
    1.19 +	input						wb_we_i,				// WISHBONE write enable (R/#W)
    1.20 +	input						wb_cyc_i,			// WISHBONE cycle
    1.21 +	input						wb_stb_i,			// WISHBONE strobe
    1.22 +	output					wb_ack_o,			// WISHBONE cycle acknowledge (data available, DTACK)
    1.23 +	output					wb_err_o,			// WISHBONE bus error
    1.24 +	output					wb_rty_o,			// WISHBONE retry-later
    1.25 +	
    1.26 +	// SDRAM
    1.27 +	output reg				sdram_cke,			// SDRAM clock enable
    1.28 +	output					sdram_cs_n,			// SDRAM chip select (active low)
    1.29 +	output					sdram_ras_n,		// SDRAM row address strobe (active low)
    1.30 +	output					sdram_cas_n,		// SDRAM column address strobe (active low)
    1.31 +	output					sdram_we_n,			// SDRAM write enable (active low)
    1.32 +	output		[11:0]	sdram_a,				// SDRAM address
    1.33 +	output reg	[1:0]		sdram_ba,			// SDRAM bank address
    1.34 +	output reg	[3:0]		sdram_dqm,			// SDRAM data mask (OE#; 0=active, 1=disabled)
    1.35 +	inout			[31:0]	sdram_dq,			// SDRAM data bus
    1.36 +
    1.37 +	// Debugging
    1.38 +	output reg	[2:0]		debug					// debug bits
    1.39 +);
    1.40 +
    1.41 +
    1.42 +/****
    1.43 + * SDRAM data output buffer
    1.44 + ****/
    1.45 +// OE=1 for output mode, 0 for input
    1.46 +reg sdram_dq_oe;
    1.47 +// SDRAM output register
    1.48 +reg [31:0] sdram_dq_r;
    1.49 +assign sdram_dq = sdram_dq_oe ? sdram_dq_r : 32'hZZZZ;
    1.50 +
    1.51 +
    1.52 +
    1.53 +/****
    1.54 + * State timer
    1.55 + * This is used to ensure that the state machine abides by RAM timing
    1.56 + * restrictions.
    1.57 + ****/
    1.58 +reg [31:0] timer;
    1.59 +
    1.60 +
    1.61 +/****
    1.62 + * MODE logic
    1.63 + ****/
    1.64 +reg  [5:0]  sdram_mode;
    1.65 +reg  [11:0]	sdram_addr;
    1.66 +assign sdram_cs_n		= sdram_mode[3];
    1.67 +assign sdram_ras_n	= sdram_mode[2];
    1.68 +assign sdram_cas_n	= sdram_mode[1];
    1.69 +assign sdram_we_n		= sdram_mode[0];
    1.70 +assign sdram_a = {sdram_addr[11], (sdram_mode[5] ? sdram_mode[4] : sdram_addr[10]), sdram_addr[9:0]};
    1.71 +
    1.72 +// SDRAM chip instructions
    1.73 +// The bit order is as specified in the ISSI datasheet: A10 Override, A10, CS#, RAS#, CAS#, WE#.
    1.74 +// If A10 Override is set, then A10 will be overridden to the value specified in the M_ constant.
    1.75 +localparam M_BankActivate		= 6'b0X0011;
    1.76 +localparam M_PrechargeBank		= 6'b100010;
    1.77 +localparam M_PrechargeAll		= 6'b110010;
    1.78 +localparam M_Write				= 6'b100100;
    1.79 +localparam M_WritePrecharge	= 6'b110100;
    1.80 +localparam M_Read					= 6'b100101;
    1.81 +localparam M_ReadPrecharge		= 6'b110101;
    1.82 +localparam M_ModeRegister		= 6'b0X0000;
    1.83 +localparam M_Nop					= 6'b0X0111;
    1.84 +localparam M_BurstStop			= 6'b0X0110;
    1.85 +localparam M_Inhibit				= 6'b0X1XXX;		// maybe X1111?
    1.86 +localparam M_AutoRefresh		= 6'b0X0001;
    1.87 +
    1.88 +
    1.89 +/****
    1.90 + * Finite State Machine
    1.91 + ****/
    1.92 +localparam	ST_INIT1			= 32'd0;
    1.93 +localparam	ST_INIT2			= 32'd1;
    1.94 +localparam	ST_NOP			= 32'd999;
    1.95 + 
    1.96 +reg [31:0] state;
    1.97 +always @(posedge wb_clk_i) begin
    1.98 +	if (wb_rst_i) begin
    1.99 +		// Initialise state machine and timer
   1.100 +		state <= ST_INIT1;
   1.101 +		debug <= 3'd0;
   1.102 +		timer <= 32'd0;
   1.103 +
   1.104 +		// Initialisation state for SDRAM
   1.105 +		sdram_cke	<= 1'b0;
   1.106 +		sdram_mode	<= M_Inhibit;
   1.107 +		sdram_addr	<= 12'h000;
   1.108 +		sdram_ba		<= 2'b00;
   1.109 +		sdram_dqm	<= 4'b0000;
   1.110 +		sdram_dq_oe	<= 1'b0;			// data output disabled
   1.111 +		sdram_dq_r	<= 32'd0;
   1.112 +	end else begin
   1.113 +		// timer logic
   1.114 +		if (timer > 32'd0) begin
   1.115 +			timer <= timer - 32'd1;
   1.116 +		end
   1.117 +	
   1.118 +		// state machine logic
   1.119 +		case (state)
   1.120 +			ST_INIT1: begin
   1.121 +					// INIT1: Set up for initial power-up wait
   1.122 +					state <= ST_INIT2;
   1.123 +					timer <= 32'd50_000;		// TODO: dependent on core clock rate. Needs to be >= 100us
   1.124 +					
   1.125 +					// SDRAM state
   1.126 +					sdram_cke	<= 1'b0;			// clock disabled
   1.127 +					sdram_mode	<= M_Inhibit;
   1.128 +					sdram_addr	<= 12'h000;
   1.129 +					sdram_ba		<= 2'b00;
   1.130 +					sdram_dqm	<= 4'b1111;
   1.131 +					sdram_dq_oe	<= 1'b0;			// data output disabled
   1.132 +					sdram_dq_r	<= 32'd0;
   1.133 +				end
   1.134 +				
   1.135 +			ST_INIT2: begin
   1.136 +					// INIT2: Power-up wait. Keep CKE low until ~50 cycles before
   1.137 +					// the end of the power-up wait, then bring CKE high.
   1.138 +					if (timer == 32'd0) begin
   1.139 +						// Timer hit zero. Send a NOP.
   1.140 +						state <= ST_NOP;
   1.141 +					end else if (timer <= 32'd50) begin
   1.142 +						// Timer value is more than zero but less than 50; CKE is on, but
   1.143 +						// keep waiting for the timer to actually expire.
   1.144 +						sdram_cke	<= 1'b1;
   1.145 +						state			<= ST_INIT2;
   1.146 +						debug <= 3'd1;
   1.147 +					end
   1.148 +					sdram_mode <= M_Inhibit;
   1.149 +				end
   1.150 +				
   1.151 +			ST_NOP: begin
   1.152 +					// Spinstate. Hold SDRAM in NOP.
   1.153 +					debug <= 3'd7;
   1.154 +					state <= ST_NOP;
   1.155 +				end
   1.156 +		endcase
   1.157 +	end
   1.158 +end
   1.159 +
   1.160 +endmodule