wb_sdram.v

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
permissions
-rw-r--r--

add clock generator DCM and preliminary homebrew WISHBONE SDRAM controller

philpem@0 1 /****************************************************************************
philpem@0 2 *
philpem@0 3 *
philpem@0 4 ****************************************************************************/
philpem@0 5
philpem@0 6 module wb_sdram (
philpem@0 7 // Clocks and resets
philpem@0 8 input wb_clk_i, // WISHBONE clock
philpem@0 9 input wb_rst_i, // WISHBONE reset
philpem@0 10
philpem@0 11 // WISHBONE bus
philpem@0 12 input [31:0] wb_adr_i, // WISHBONE address
philpem@0 13 input [31:0] wb_dat_i, // WISHBONE data in
philpem@0 14 output reg [31:0] wb_dat_o, // WISHBONE data out
philpem@0 15 input [3:0] wb_sel_i, // WISHBONE byte select
philpem@0 16 input wb_we_i, // WISHBONE write enable (R/#W)
philpem@0 17 input wb_cyc_i, // WISHBONE cycle
philpem@0 18 input wb_stb_i, // WISHBONE strobe
philpem@0 19 output wb_ack_o, // WISHBONE cycle acknowledge (data available, DTACK)
philpem@0 20 output wb_err_o, // WISHBONE bus error
philpem@0 21 output wb_rty_o, // WISHBONE retry-later
philpem@0 22
philpem@0 23 // SDRAM
philpem@0 24 output reg sdram_cke, // SDRAM clock enable
philpem@0 25 output sdram_cs_n, // SDRAM chip select (active low)
philpem@0 26 output sdram_ras_n, // SDRAM row address strobe (active low)
philpem@0 27 output sdram_cas_n, // SDRAM column address strobe (active low)
philpem@0 28 output sdram_we_n, // SDRAM write enable (active low)
philpem@0 29 output [11:0] sdram_a, // SDRAM address
philpem@0 30 output reg [1:0] sdram_ba, // SDRAM bank address
philpem@0 31 output reg [3:0] sdram_dqm, // SDRAM data mask (OE#; 0=active, 1=disabled)
philpem@0 32 inout [31:0] sdram_dq, // SDRAM data bus
philpem@0 33
philpem@0 34 // Debugging
philpem@0 35 output reg [2:0] debug // debug bits
philpem@0 36 );
philpem@0 37
philpem@0 38
philpem@0 39 /****
philpem@0 40 * SDRAM data output buffer
philpem@0 41 ****/
philpem@0 42 // OE=1 for output mode, 0 for input
philpem@0 43 reg sdram_dq_oe;
philpem@0 44 // SDRAM output register
philpem@0 45 reg [31:0] sdram_dq_r;
philpem@0 46 assign sdram_dq = sdram_dq_oe ? sdram_dq_r : 32'hZZZZ;
philpem@0 47
philpem@0 48
philpem@0 49
philpem@0 50 /****
philpem@0 51 * State timer
philpem@0 52 * This is used to ensure that the state machine abides by RAM timing
philpem@0 53 * restrictions.
philpem@0 54 ****/
philpem@0 55 reg [31:0] timer;
philpem@0 56
philpem@0 57
philpem@0 58 /****
philpem@0 59 * MODE logic
philpem@0 60 ****/
philpem@0 61 reg [5:0] sdram_mode;
philpem@0 62 reg [11:0] sdram_addr;
philpem@0 63 assign sdram_cs_n = sdram_mode[3];
philpem@0 64 assign sdram_ras_n = sdram_mode[2];
philpem@0 65 assign sdram_cas_n = sdram_mode[1];
philpem@0 66 assign sdram_we_n = sdram_mode[0];
philpem@0 67 assign sdram_a = {sdram_addr[11], (sdram_mode[5] ? sdram_mode[4] : sdram_addr[10]), sdram_addr[9:0]};
philpem@0 68
philpem@0 69 // SDRAM chip instructions
philpem@0 70 // The bit order is as specified in the ISSI datasheet: A10 Override, A10, CS#, RAS#, CAS#, WE#.
philpem@0 71 // If A10 Override is set, then A10 will be overridden to the value specified in the M_ constant.
philpem@0 72 localparam M_BankActivate = 6'b0X0011;
philpem@0 73 localparam M_PrechargeBank = 6'b100010;
philpem@0 74 localparam M_PrechargeAll = 6'b110010;
philpem@0 75 localparam M_Write = 6'b100100;
philpem@0 76 localparam M_WritePrecharge = 6'b110100;
philpem@0 77 localparam M_Read = 6'b100101;
philpem@0 78 localparam M_ReadPrecharge = 6'b110101;
philpem@0 79 localparam M_ModeRegister = 6'b0X0000;
philpem@0 80 localparam M_Nop = 6'b0X0111;
philpem@0 81 localparam M_BurstStop = 6'b0X0110;
philpem@0 82 localparam M_Inhibit = 6'b0X1XXX; // maybe X1111?
philpem@0 83 localparam M_AutoRefresh = 6'b0X0001;
philpem@0 84
philpem@0 85
philpem@0 86 /****
philpem@0 87 * Finite State Machine
philpem@0 88 ****/
philpem@0 89 localparam ST_INIT1 = 32'd0;
philpem@0 90 localparam ST_INIT2 = 32'd1;
philpem@0 91 localparam ST_NOP = 32'd999;
philpem@0 92
philpem@0 93 reg [31:0] state;
philpem@0 94 always @(posedge wb_clk_i) begin
philpem@0 95 if (wb_rst_i) begin
philpem@0 96 // Initialise state machine and timer
philpem@0 97 state <= ST_INIT1;
philpem@0 98 debug <= 3'd0;
philpem@0 99 timer <= 32'd0;
philpem@0 100
philpem@0 101 // Initialisation state for SDRAM
philpem@0 102 sdram_cke <= 1'b0;
philpem@0 103 sdram_mode <= M_Inhibit;
philpem@0 104 sdram_addr <= 12'h000;
philpem@0 105 sdram_ba <= 2'b00;
philpem@0 106 sdram_dqm <= 4'b0000;
philpem@0 107 sdram_dq_oe <= 1'b0; // data output disabled
philpem@0 108 sdram_dq_r <= 32'd0;
philpem@0 109 end else begin
philpem@0 110 // timer logic
philpem@0 111 if (timer > 32'd0) begin
philpem@0 112 timer <= timer - 32'd1;
philpem@0 113 end
philpem@0 114
philpem@0 115 // state machine logic
philpem@0 116 case (state)
philpem@0 117 ST_INIT1: begin
philpem@0 118 // INIT1: Set up for initial power-up wait
philpem@0 119 state <= ST_INIT2;
philpem@0 120 timer <= 32'd50_000; // TODO: dependent on core clock rate. Needs to be >= 100us
philpem@0 121
philpem@0 122 // SDRAM state
philpem@0 123 sdram_cke <= 1'b0; // clock disabled
philpem@0 124 sdram_mode <= M_Inhibit;
philpem@0 125 sdram_addr <= 12'h000;
philpem@0 126 sdram_ba <= 2'b00;
philpem@0 127 sdram_dqm <= 4'b1111;
philpem@0 128 sdram_dq_oe <= 1'b0; // data output disabled
philpem@0 129 sdram_dq_r <= 32'd0;
philpem@0 130 end
philpem@0 131
philpem@0 132 ST_INIT2: begin
philpem@0 133 // INIT2: Power-up wait. Keep CKE low until ~50 cycles before
philpem@0 134 // the end of the power-up wait, then bring CKE high.
philpem@0 135 if (timer == 32'd0) begin
philpem@0 136 // Timer hit zero. Send a NOP.
philpem@0 137 state <= ST_NOP;
philpem@0 138 end else if (timer <= 32'd50) begin
philpem@0 139 // Timer value is more than zero but less than 50; CKE is on, but
philpem@0 140 // keep waiting for the timer to actually expire.
philpem@0 141 sdram_cke <= 1'b1;
philpem@0 142 state <= ST_INIT2;
philpem@0 143 debug <= 3'd1;
philpem@0 144 end
philpem@0 145 sdram_mode <= M_Inhibit;
philpem@0 146 end
philpem@0 147
philpem@0 148 ST_NOP: begin
philpem@0 149 // Spinstate. Hold SDRAM in NOP.
philpem@0 150 debug <= 3'd7;
philpem@0 151 state <= ST_NOP;
philpem@0 152 end
philpem@0 153 endcase
philpem@0 154 end
philpem@0 155 end
philpem@0 156
philpem@0 157 endmodule