wb_sdram.v

Wed, 18 Aug 2010 14:10:48 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Wed, 18 Aug 2010 14:10:48 +0100
changeset 17
ac979332d5fd
parent 16
49f3a5bd860e
child 18
275105a6a36b
permissions
-rw-r--r--

parameterise data and addr. buses, tidy up

Parameterised the width of the data and address buses, and the number of
COLUMN, ROW and BANK address bits.

Tidied up code to (hopefully!) work when bus widths are changed.

philpem@17 1 /****************************************************************************
philpem@0 2 *
philpem@0 3 *
philpem@0 4 ****************************************************************************/
philpem@0 5
philpem@17 6 module wb_sdram #(
philpem@17 7 parameter DATA_BITS = 32, // Width of SDRAM data bus
philpem@17 8 parameter COLADDR_BITS = 9, // Number of SDRAM Column Address bits
philpem@17 9 parameter BANKADDR_BITS = 2, // Number of SDRAM Bank Address bits
philpem@17 10 parameter ROWADDR_BITS = 12 // Number of SDRAM Row Address bits
philpem@17 11 ) (
philpem@0 12 // Clocks and resets
philpem@17 13 input wb_clk_i, // WISHBONE clock
philpem@17 14 input wb_rst_i, // WISHBONE reset
philpem@0 15
philpem@0 16 // WISHBONE bus
philpem@17 17 input [31:0] wb_adr_i, // WISHBONE address
philpem@17 18 input [DATA_BITS-1:0] wb_dat_i, // WISHBONE data in
philpem@17 19 output reg [DATA_BITS-1:0] wb_dat_o, // WISHBONE data out
philpem@17 20 input [(DATA_BITS/4)-1:0] wb_sel_i, // WISHBONE byte select
philpem@17 21 input wb_we_i, // WISHBONE write enable (R/#W)
philpem@17 22 input wb_cyc_i, // WISHBONE cycle
philpem@17 23 input wb_stb_i, // WISHBONE strobe
philpem@17 24 output reg wb_ack_o, // WISHBONE cycle acknowledge (data available, DTACK)
philpem@17 25 output wb_err_o, // WISHBONE bus error
philpem@17 26 output wb_rty_o, // WISHBONE retry-later
philpem@0 27
philpem@0 28 // SDRAM
philpem@17 29 output reg sdram_cke, // SDRAM clock enable
philpem@17 30 output sdram_cs_n, // SDRAM chip select (active low)
philpem@17 31 output sdram_ras_n, // SDRAM row address strobe (active low)
philpem@17 32 output sdram_cas_n, // SDRAM column address strobe (active low)
philpem@17 33 output sdram_we_n, // SDRAM write enable (active low)
philpem@17 34 output [ROWADDR_BITS-1:0] sdram_a, // SDRAM address
philpem@17 35 output reg [BANKADDR_BITS-1:0] sdram_ba, // SDRAM bank address
philpem@17 36 output reg [(DATA_BITS/4)-1:0] sdram_dqm, // SDRAM data mask (OE#; 0=active, 1=disabled)
philpem@17 37 inout [DATA_BITS-1:0] sdram_dq // SDRAM data bus
philpem@0 38 );
philpem@0 39
philpem@0 40
philpem@0 41 /****
philpem@10 42 * Timer values
philpem@10 43 ****/
philpem@13 44 // CAS latency -- either 2 or 3 [2010-08-10: tested with CL=3, worked fine]
philpem@12 45 parameter CAS_LATENCY = 3'd2;
philpem@15 46 // System clock frequency
philpem@15 47 parameter CLOCK_RATE = 25_000_000;
philpem@15 48
philpem@15 49 // SDRAM timings in nanoseconds
philpem@16 50 // Precharge to refresh/row activate command (same bank) -- Trp
philpem@15 51 parameter TIME_Trp = 20;
philpem@16 52 // RAS# to CAS# delay -- Trcd
philpem@15 53 parameter TIME_Trcd = 20;
philpem@16 54 // Row cycle time -- Trfc, also known as Trc
philpem@15 55 parameter TIME_Trfc = 70;
philpem@16 56 // Time between refresh cycles -- refresh interval divided by number of rows to refresh (in this case, 64e-3/4096*1e9 --> 15.625us or 15,625ns)
philpem@15 57 parameter TIME_Refresh = 15_625;
philpem@16 58 // 2ms power-up init period
philpem@16 59 parameter TIME_InitDelay = 2_000_000;
philpem@16 60 // 2us before the end of the init period, raise CKE
philpem@16 61 parameter TIME_InitFinal = 2_000;
philpem@15 62
philpem@15 63 // Calculate clock period in nanoseconds
philpem@15 64 localparam CLOCK_PERIOD = 1_000_000_000 / CLOCK_RATE;
philpem@15 65
philpem@10 66 // T_rp ==> 20ns
philpem@15 67 localparam TCY_Trp = (TIME_Trp+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@10 68 // T_rcd ==> 20ns
philpem@15 69 localparam TCY_Trcd = (TIME_Trcd+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@10 70 // T_rfc (a.k.a. T_rc) ==> 70ns
philpem@15 71 localparam TCY_Trfc = (TIME_Trfc+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@10 72 // T_mrd ==> 2 clock cycles
philpem@15 73 localparam TCY_Tmrd = 32'd2;
philpem@12 74 // Maximum allowed time between two refresh cycles
philpem@15 75 localparam TCY_Refresh = (TIME_Refresh+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@15 76
philpem@15 77 localparam TCY_InitDelay = (TIME_InitDelay+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@15 78 localparam TCY_InitFinal = (TIME_InitFinal+CLOCK_PERIOD-1) / CLOCK_PERIOD - 1;
philpem@10 79
philpem@10 80
philpem@10 81 /****
philpem@8 82 * WISHBONE status pins
philpem@8 83 ****/
philpem@8 84 // Can't raise bus errors
philpem@8 85 assign wb_err_o = 1'b0;
philpem@8 86 // Can't request retries
philpem@8 87 assign wb_rty_o = 1'b0;
philpem@8 88
philpem@14 89
philpem@8 90 /****
philpem@0 91 * SDRAM data output buffer
philpem@0 92 ****/
philpem@0 93 // OE=1 for output mode, 0 for input
philpem@0 94 reg sdram_dq_oe;
philpem@0 95 // SDRAM output register
philpem@17 96 reg [DATA_BITS-1:0] sdram_dq_r;
philpem@17 97 assign sdram_dq = sdram_dq_oe ? sdram_dq_r : {DATA_BITS{1'bZ}};
philpem@0 98
philpem@0 99
philpem@0 100 /****
philpem@0 101 * State timer
philpem@0 102 * This is used to ensure that the state machine abides by RAM timing
philpem@0 103 * restrictions.
philpem@0 104 ****/
philpem@0 105 reg [31:0] timer;
philpem@0 106
philpem@0 107
philpem@0 108 /****
philpem@0 109 * MODE logic
philpem@0 110 ****/
philpem@0 111 reg [5:0] sdram_mode;
philpem@0 112 reg [11:0] sdram_addr;
philpem@0 113 assign sdram_cs_n = sdram_mode[3];
philpem@0 114 assign sdram_ras_n = sdram_mode[2];
philpem@0 115 assign sdram_cas_n = sdram_mode[1];
philpem@0 116 assign sdram_we_n = sdram_mode[0];
philpem@0 117 assign sdram_a = {sdram_addr[11], (sdram_mode[5] ? sdram_mode[4] : sdram_addr[10]), sdram_addr[9:0]};
philpem@0 118
philpem@0 119 // SDRAM chip instructions
philpem@0 120 // The bit order is as specified in the ISSI datasheet: A10 Override, A10, CS#, RAS#, CAS#, WE#.
philpem@0 121 // If A10 Override is set, then A10 will be overridden to the value specified in the M_ constant.
philpem@0 122 localparam M_BankActivate = 6'b0X0011;
philpem@0 123 localparam M_PrechargeBank = 6'b100010;
philpem@0 124 localparam M_PrechargeAll = 6'b110010;
philpem@0 125 localparam M_Write = 6'b100100;
philpem@0 126 localparam M_WritePrecharge = 6'b110100;
philpem@0 127 localparam M_Read = 6'b100101;
philpem@0 128 localparam M_ReadPrecharge = 6'b110101;
philpem@2 129 localparam M_LoadModeRegister = 6'b0X0000;
philpem@0 130 localparam M_Nop = 6'b0X0111;
philpem@0 131 localparam M_BurstStop = 6'b0X0110;
philpem@0 132 localparam M_Inhibit = 6'b0X1XXX; // maybe X1111?
philpem@0 133 localparam M_AutoRefresh = 6'b0X0001;
philpem@0 134
philpem@0 135
philpem@0 136 /****
philpem@3 137 * Refresh Timer
philpem@3 138 ****/
philpem@3 139 reg [31:0] refresh_timer;
philpem@3 140 reg refresh_req, refresh_ack, refresh_timer_en;
philpem@3 141 always @(posedge wb_clk_i) begin
philpem@3 142 if (wb_rst_i | !refresh_timer_en) begin
philpem@3 143 // Reset; clear timer, unset REFRESH REQUEST
philpem@3 144 refresh_req <= 1'b0;
philpem@15 145 refresh_timer <= TCY_Refresh - 32'd1;
philpem@3 146 end else if (refresh_ack) begin
philpem@3 147 // Refresh Ack, clear Refresh Request.
philpem@3 148 refresh_req <= 1'b0;
philpem@3 149 end else if (refresh_timer == 0) begin
philpem@3 150 // Refresh timer timed out, make a Refresh Request and reload the timer
philpem@3 151 refresh_req <= 1'b1;
philpem@15 152 refresh_timer <= TCY_Refresh - 32'd1;
philpem@3 153 end else begin
philpem@3 154 // Otherwise just decrement the timer
philpem@3 155 refresh_timer <= refresh_timer - 32'd1;
philpem@3 156 end
philpem@3 157 end
philpem@3 158
philpem@4 159
philpem@4 160 /****
philpem@4 161 * Address decoder
philpem@4 162 ****/
philpem@17 163 wire [COLADDR_BITS-1:0] column_addr;
philpem@17 164 wire [ROWADDR_BITS-1:0] row_addr;
philpem@17 165 wire [BANKADDR_BITS-1:0] bank_addr;
philpem@4 166
philpem@7 167 // Convert a 23-bit linear address into an SDRAM address
philpem@17 168 assign column_addr = wb_adr_i[COLADDR_BITS-1:0];
philpem@17 169 assign bank_addr = wb_adr_i[COLADDR_BITS+BANKADDR_BITS-1:COLADDR_BITS];
philpem@17 170 assign row_addr = wb_adr_i[COLADDR_BITS+BANKADDR_BITS+ROWADDR_BITS-1:COLADDR_BITS+BANKADDR_BITS];
philpem@4 171
philpem@4 172
philpem@3 173 /****
philpem@0 174 * Finite State Machine
philpem@0 175 ****/
philpem@2 176 localparam ST_INIT1 = 32'd0;
philpem@2 177 localparam ST_INIT2 = 32'd1;
philpem@2 178 localparam ST_NOP1 = 32'd2;
philpem@2 179 localparam ST_PrechargeAll = 32'd3;
philpem@2 180 localparam ST_PrechargeAll_Wait = 32'd4;
philpem@2 181 localparam ST_AutoRefresh1 = 32'd5;
philpem@2 182 localparam ST_AutoRefresh1_Wait = 32'd6;
philpem@2 183 localparam ST_AutoRefresh2 = 32'd7;
philpem@2 184 localparam ST_AutoRefresh2_Wait = 32'd8;
philpem@2 185 localparam ST_LoadModeRegister = 32'd9;
philpem@2 186 localparam ST_LoadModeRegister_Wait = 32'd10;
philpem@3 187 localparam ST_Spin = 32'd11; // <<== main 'spin' / 'idle' state
philpem@3 188 localparam ST_Refresh = 32'd12;
philpem@3 189 localparam ST_Refresh_Wait = 32'd13;
philpem@7 190 localparam ST_Activate = 32'd30;
philpem@7 191 localparam ST_Activate_Wait = 32'd31;
philpem@7 192 localparam ST_Write = 32'd32;
philpem@7 193 localparam ST_Read = 32'd33;
philpem@7 194 localparam ST_Read_Wait = 32'd34;
philpem@7 195 localparam ST_Wait_Trp = 32'd35;
philpem@7 196 localparam ST_Ack = 32'd36;
philpem@7 197
philpem@0 198
philpem@0 199 reg [31:0] state;
philpem@0 200 always @(posedge wb_clk_i) begin
philpem@0 201 if (wb_rst_i) begin
philpem@0 202 // Initialise state machine and timer
philpem@0 203 state <= ST_INIT1;
philpem@0 204 timer <= 32'd0;
philpem@3 205
philpem@3 206 // Clear REFRESH ACK flag and disable refresh timer
philpem@3 207 refresh_ack <= 1'b0;
philpem@3 208 refresh_timer_en <= 1'b0;
philpem@0 209
philpem@0 210 // Initialisation state for SDRAM
philpem@0 211 sdram_cke <= 1'b0;
philpem@0 212 sdram_mode <= M_Inhibit;
philpem@17 213 sdram_addr <= 0;
philpem@17 214 sdram_ba <= 0;
philpem@17 215 sdram_dqm <= 0;
philpem@17 216 sdram_dq_oe <= 0; // data output disabled
philpem@17 217 sdram_dq_r <= 0;
philpem@0 218 end else begin
philpem@0 219 // timer logic
philpem@0 220 if (timer > 32'd0) begin
philpem@0 221 timer <= timer - 32'd1;
philpem@0 222 end
philpem@0 223
philpem@0 224 // state machine logic
philpem@0 225 case (state)
philpem@0 226 ST_INIT1: begin
philpem@0 227 // INIT1: Set up for initial power-up wait
philpem@0 228 state <= ST_INIT2;
philpem@15 229 timer <= TCY_InitDelay; // Needs to be >= 100us
philpem@0 230
philpem@0 231 // SDRAM state
philpem@0 232 sdram_cke <= 1'b0; // clock disabled
philpem@0 233 sdram_mode <= M_Inhibit;
philpem@17 234 sdram_addr <= 0;
philpem@17 235 sdram_ba <= 0;
philpem@17 236 sdram_dqm <= {(DATA_BITS/4){1'b1}};
philpem@17 237 sdram_dq_oe <= 0; // data output disabled
philpem@17 238 sdram_dq_r <= 0;
philpem@0 239 end
philpem@0 240
philpem@0 241 ST_INIT2: begin
philpem@0 242 // INIT2: Power-up wait. Keep CKE low until ~50 cycles before
philpem@0 243 // the end of the power-up wait, then bring CKE high.
philpem@0 244 if (timer == 32'd0) begin
philpem@0 245 // Timer hit zero. Send a NOP.
philpem@2 246 state <= ST_NOP1;
philpem@15 247 end else if (timer < TCY_InitFinal) begin
philpem@0 248 // Timer value is more than zero but less than 50; CKE is on, but
philpem@0 249 // keep waiting for the timer to actually expire.
philpem@0 250 sdram_cke <= 1'b1;
philpem@0 251 state <= ST_INIT2;
philpem@0 252 end
philpem@0 253 sdram_mode <= M_Inhibit;
philpem@0 254 end
philpem@0 255
philpem@2 256 ST_NOP1: begin
philpem@2 257 // Apply one or more NOP commands to the SDRAM
philpem@2 258 sdram_mode <= M_Nop;
philpem@2 259 state <= ST_PrechargeAll;
philpem@2 260 end
philpem@2 261
philpem@2 262 ST_PrechargeAll: begin
philpem@2 263 // Precharge All, then wait T_rp (20ns)
philpem@2 264 sdram_mode <= M_PrechargeAll;
philpem@15 265 timer <= TCY_Trp - 32'd1;
philpem@2 266 state <= ST_PrechargeAll_Wait;
philpem@2 267 end
philpem@2 268
philpem@2 269 ST_PrechargeAll_Wait: begin
philpem@2 270 // Wait for T_rp after Precharge All
philpem@2 271 sdram_mode <= M_Nop;
philpem@2 272 if (timer == 32'd0) begin
philpem@2 273 // Timer hit zero. Continue
philpem@2 274 state <= ST_AutoRefresh1;
philpem@2 275 end
philpem@2 276 end
philpem@2 277
philpem@2 278 ST_AutoRefresh1: begin
philpem@2 279 // Auto Refresh 1 of 2, wait T_rfc (70ns) after each
philpem@2 280 sdram_mode <= M_AutoRefresh;
philpem@15 281 timer <= TCY_Trfc - 32'd1;
philpem@2 282 state <= ST_AutoRefresh1_Wait;
philpem@2 283 end
philpem@2 284
philpem@2 285 ST_AutoRefresh1_Wait: begin
philpem@2 286 // Wait for T_rfc
philpem@1 287 sdram_mode <= M_Nop;
philpem@2 288 if (timer == 32'd0) begin
philpem@2 289 // Timer hit zero. Continue
philpem@2 290 state <= ST_AutoRefresh2;
philpem@2 291 end
philpem@2 292 end
philpem@2 293
philpem@2 294 ST_AutoRefresh2: begin
philpem@2 295 // Auto Refresh 2 of 2, wait T_rfc (70ns) after each
philpem@2 296 sdram_mode <= M_AutoRefresh;
philpem@15 297 timer <= TCY_Trfc - 32'd1;
philpem@2 298 state <= ST_AutoRefresh2_Wait;
philpem@2 299 end
philpem@2 300
philpem@2 301 ST_AutoRefresh2_Wait: begin
philpem@2 302 // Wait for T_rfc
philpem@2 303 sdram_mode <= M_Nop;
philpem@2 304 if (timer == 32'd0) begin
philpem@2 305 // Timer hit zero. Continue
philpem@2 306 state <= ST_LoadModeRegister;
philpem@2 307 end
philpem@2 308 end
philpem@2 309
philpem@2 310 ST_LoadModeRegister: begin
philpem@2 311 // Load Mode Register
philpem@2 312 /**
philpem@2 313 * Mode register:
philpem@2 314 * - BS0,1 = 00 [RFU]
philpem@2 315 * - A11,10 = 00 [RFU]
philpem@2 316 * - A9 = 0 [WBL -- write burst length same as read burst length]
philpem@2 317 * - A8,7 = 00 [Test Mode off]
philpem@10 318 * - A6..4 = 010 [CAS Latency = 2 or 3 clocks, set above]
philpem@2 319 * - A3 = 0 [Burst type = sequential]
philpem@2 320 * - A2..0 = 000 [Burst length = 1 word]
philpem@2 321 */
philpem@17 322 sdram_ba <= 0;
philpem@10 323 sdram_addr <= {5'b00_0_00, CAS_LATENCY[2:0], 3'b000};
philpem@2 324 sdram_mode <= M_LoadModeRegister;
philpem@2 325
philpem@2 326 // Wait T_mrd (2 clock cycles)
philpem@15 327 timer <= TCY_Tmrd - 32'd1;
philpem@2 328 state <= ST_LoadModeRegister_Wait;
philpem@2 329 end
philpem@2 330
philpem@2 331 ST_LoadModeRegister_Wait: begin
philpem@2 332 // Wait for LMR to complete
philpem@2 333 sdram_mode <= M_Nop;
philpem@17 334 sdram_ba <= 0;
philpem@17 335 sdram_addr <= 0;
philpem@2 336 if (timer == 32'd0) begin
philpem@2 337 // Timer hit zero. Continue
philpem@2 338 state <= ST_Spin;
philpem@2 339 end
philpem@2 340 end
philpem@2 341
philpem@2 342 ST_Spin: begin
philpem@3 343 // Enable refresh timer
philpem@3 344 refresh_timer_en <= 1'b1;
philpem@3 345
philpem@7 346 // Idle the SDRAM (Inhibit is lower power than NOP on some SDRAMs)
philpem@2 347 sdram_mode <= M_Inhibit;
philpem@3 348
philpem@9 349 // Check if a refresh is due (these have highest priority)
philpem@3 350 if (refresh_req) begin
philpem@3 351 // Refresh request received. Ack it and do a refresh.
philpem@3 352 refresh_ack <= 1'b1;
philpem@3 353 state <= ST_Refresh;
philpem@3 354 end else begin
philpem@7 355 if (wb_cyc_i & wb_stb_i) begin
philpem@7 356 // CYC and STB high. A Wishbone cycle just started.
philpem@7 357 state <= ST_Activate;
philpem@7 358 end
philpem@3 359 end
philpem@3 360 end
philpem@7 361
philpem@7 362 /////
philpem@7 363 // Refresh logic
philpem@7 364 /////
philpem@3 365
philpem@3 366 ST_Refresh: begin
philpem@3 367 // Refresh timer timed out; do a refresh run
philpem@3 368 // Start by clearing the ACK flag (which was set by the Spin state)
philpem@3 369 refresh_ack <= 1'b0;
philpem@3 370 // Tell the SDRAM to do a Refresh
philpem@3 371 sdram_mode <= M_AutoRefresh;
philpem@3 372 // Wait for T_rfc
philpem@15 373 timer <= TCY_Trfc;
philpem@3 374 state <= ST_Refresh_Wait;
philpem@3 375 end
philpem@3 376
philpem@3 377 ST_Refresh_Wait: begin
philpem@3 378 // Wait for T_rfc
philpem@3 379 sdram_mode <= M_Nop;
philpem@3 380 if (timer == 32'd0) begin
philpem@3 381 // Timer hit zero. Go back to spin state.
philpem@3 382 state <= ST_Spin;
philpem@3 383 end
philpem@0 384 end
philpem@7 385
philpem@7 386 //////
philpem@7 387 // R/W logic
philpem@7 388 //////
philpem@7 389 ST_Activate: begin
philpem@7 390 // Activate the required bank
philpem@4 391 sdram_mode <= M_BankActivate;
philpem@4 392 sdram_addr <= row_addr;
philpem@7 393 sdram_ba <= bank_addr;
philpem@15 394 timer <= TCY_Trcd - 32'd1;
philpem@7 395 state <= ST_Activate_Wait;
philpem@4 396 end
philpem@4 397
philpem@7 398 ST_Activate_Wait: begin
philpem@7 399 // Wait for T_rcd
philpem@4 400 sdram_mode <= M_Nop;
philpem@4 401 if (timer == 32'd0) begin
philpem@7 402 if (wb_we_i) begin
philpem@7 403 // Write cycle.
philpem@7 404 state <= ST_Write;
philpem@7 405 end else begin
philpem@7 406 // Read cycle
philpem@7 407 state <= ST_Read;
philpem@7 408 end
philpem@4 409 end
philpem@4 410 end
philpem@4 411
philpem@7 412 ST_Write: begin
philpem@7 413 // Write cycle handler
philpem@7 414 sdram_mode <= M_WritePrecharge;
philpem@7 415 sdram_addr <= column_addr;
philpem@17 416 sdram_dq_r <= 0;
philpem@17 417 sdram_dq_oe <= 1; // FPGA drives the DQ bus
philpem@9 418 sdram_dqm <= ~wb_sel_i;
philpem@7 419
philpem@7 420 // Wait T_rp (20ns)
philpem@15 421 timer <= TCY_Trp - 32'd1;
philpem@7 422 state <= ST_Wait_Trp;
philpem@7 423 end
philpem@7 424
philpem@7 425 ST_Read: begin
philpem@7 426 // Read cycle handler
philpem@7 427 sdram_mode <= M_ReadPrecharge;
philpem@7 428 sdram_addr <= column_addr;
philpem@17 429 sdram_dq_oe <= 0; // SDRAM drives the DQ bus
philpem@17 430 sdram_dqm <= 0; // Grab all the data (easier than playing with WB_SEL...)
philpem@10 431 timer <= CAS_LATENCY - 32'd1; // CAS# Latency
philpem@7 432 state <= ST_Read_Wait;
philpem@4 433 end
philpem@4 434
philpem@7 435 ST_Read_Wait: begin
philpem@7 436 // Wait for CAS# latency
philpem@7 437 sdram_mode <= M_Nop;
philpem@17 438 sdram_dqm <= {(DATA_BITS/4){1'b1}}; // Make SDRAM DQ bus float
philpem@4 439 if (timer == 32'd0) begin
philpem@7 440 // Latch data
philpem@7 441 wb_dat_o <= sdram_dq;
philpem@7 442 // Wait T_rp (20ns)
philpem@15 443 timer <= TCY_Trp - 32'd1;
philpem@7 444 state <= ST_Wait_Trp;
philpem@4 445 end
philpem@4 446 end
philpem@5 447
philpem@7 448 ST_Wait_Trp: begin
philpem@7 449 // Wait for T_rp, then ack
philpem@7 450 if (timer == 32'd0) begin
philpem@7 451 state <= ST_Ack;
philpem@7 452 end
philpem@4 453 end
philpem@4 454
philpem@7 455 ST_Ack: begin
philpem@7 456 // Ack the transfer to the WISHBONE host
philpem@7 457 sdram_mode <= M_Nop;
philpem@17 458 sdram_addr <= 0;
philpem@17 459 sdram_dq_r <= 0;
philpem@17 460 sdram_dq_oe <= 0; // SDRAM drives the DQ bus
philpem@17 461 sdram_dqm <= {(DATA_BITS/4){1'b1}}; // mask off DQM
philpem@7 462 if (wb_cyc_i & wb_stb_i) begin
philpem@7 463 // CYC and STB high, ack the transfer
philpem@7 464 wb_ack_o <= 1'b1;
philpem@7 465 state <= ST_Ack;
philpem@7 466 end else begin
philpem@9 467 // CYC and STB low, go back and wait for another transaction
philpem@9 468 wb_ack_o <= 1'b0;
philpem@7 469 state <= ST_Spin;
philpem@4 470 end
philpem@4 471 end
philpem@0 472 endcase
philpem@0 473 end
philpem@0 474 end
philpem@0 475
philpem@0 476 endmodule