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