1 /*********************************************************************
3 SDRAM Controller Bank Controller
5 This file is part of the sdram controller project
6 http://www.opencores.org/cores/sdr_ctrl/
9 This module takes requests from sdrc_req_gen, checks for page hit/miss and
10 issues precharge/activate commands and then passes the request to sdrc_xfr_ctl.
16 - Dinesh Annayya, dinesha@opencores.org
17 Version : 1.0 - 8th Jan 2012
21 Copyright (C) 2000 Authors and OPENCORES.ORG
23 This source file may be used and distributed without
24 restriction provided that this copyright statement is not
25 removed from the file and that any derivative work contains
26 the original copyright notice and the associated disclaimer.
28 This source file is free software; you can redistribute it
29 and/or modify it under the terms of the GNU Lesser General
30 Public License as published by the Free Software Foundation;
31 either version 2.1 of the License, or (at your option) any
34 This source is distributed in the hope that it will be
35 useful, but WITHOUT ANY WARRANTY; without even the implied
36 warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
37 PURPOSE. See the GNU Lesser General Public License for more
40 You should have received a copy of the GNU Lesser General
41 Public License along with this source; if not, download it
42 from http://www.opencores.org/lgpl.shtml
44 *******************************************************************/
47 //`include "sdrc_define.v"
49 module sdrc_bank_fsm (clk,
52 /* Req from req_gen */
55 r2b_start, // First chunk of burst
56 r2b_last, // Last chunk of burst
58 r2b_raddr, // row address
59 r2b_caddr, // col address
61 r2b_write, // write request
65 /* Transfer request to xfr_ctl */
66 b2x_req, // Request to xfr_ctl
67 b2x_start, // first chunk of transfer
68 b2x_last, // last chunk of transfer
70 b2x_id, // Transfer ID
71 b2x_addr, // row/col address
72 b2x_len, // transfer length
73 b2x_cmd, // transfer command
74 x2b_ack, // command accepted
76 /* Status to/from xfr_ctl */
77 tras_ok, // TRAS OK for this bank
79 x2b_refresh, // We did a refresh
80 x2b_pre_ok, // OK to do a precharge (per bank)
81 x2b_act_ok, // OK to do an activate
82 x2b_rdok, // OK to do a read
83 x2b_wrok, // OK to do a write
85 /* current xfr row address of the bank */
89 tras_delay, // Active to precharge delay
90 trp_delay, // Precharge to active delay
91 trcd_delay); // Active to R/W delay
94 `define SDR_REQ_ID_W 4
96 `define SDR_RFSH_TIMER_W 12
97 `define SDR_RFSH_ROW_CNT_W 3
106 // SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N)
108 `define SDR_DESEL 4'b1111
109 `define SDR_NOOP 4'b0111
110 `define SDR_ACTIVATE 4'b0011
111 `define SDR_READ 4'b0101
112 `define SDR_WRITE 4'b0100
113 `define SDR_BT 4'b0110
114 `define SDR_PRECHARGE 4'b0010
115 `define SDR_REFRESH 4'b0001
116 `define SDR_MODE 4'b0000
120 `define TARGET_DESIGN `ASIC
121 // 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits
122 `define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width
124 parameter SDR_DW = 64; // SDR Data Width
125 parameter SDR_BW = 8; // SDR Byte Width
129 /* Req from bank_ctl */
130 input r2b_req, r2b_start, r2b_last,
132 input [`SDR_REQ_ID_W-1:0] r2b_req_id;
133 input [12:0] r2b_raddr;
134 input [12:0] r2b_caddr;
135 input [`REQ_BW-1:0] r2b_len;
140 output b2x_req, b2x_start, b2x_last,
142 output [`SDR_REQ_ID_W-1:0] b2x_id;
143 output [12:0] b2x_addr;
144 output [`REQ_BW-1:0] b2x_len;
145 output [1:0] b2x_cmd;
148 /* Status from xfr_ctl */
149 input x2b_refresh, x2b_act_ok, x2b_rdok,
150 x2b_wrok, x2b_pre_ok, xfr_ok;
152 input [3:0] tras_delay, trp_delay, trcd_delay;
154 output [12:0] bank_row;
156 /****************************************************************************/
159 `define BANK_IDLE 3'b000
160 `define BANK_PRE 3'b001
161 `define BANK_ACT 3'b010
162 `define BANK_XFR 3'b011
163 `define BANK_DMA_LAST_PRE 3'b100
165 reg [2:0] bank_st, next_bank_st;
166 wire b2x_start, b2x_last;
168 reg b2x_req, b2r_ack;
169 wire [`SDR_REQ_ID_W-1:0] b2x_id;
170 reg [`SDR_REQ_ID_W-1:0] l_id;
172 reg [`REQ_BW-1:0] l_len;
173 wire [`REQ_BW-1:0] b2x_len;
177 reg [3:0] tras_cntr, timer0;
183 reg bank_prech_page_closed;
185 wire tras_ok_internal, tras_ok, activate_bank;
187 wire page_hit, timer0_tc_t, ld_trp, ld_trcd;
189 /*** Timing Break Logic Added for FPGA - Start ****/
190 reg x2b_wrok_r, xfr_ok_r , x2b_rdok_r;
191 reg [1:0] b2x_cmd_r,timer0_tc_r,tras_ok_r,x2b_pre_ok_r,x2b_act_ok_r;
192 always @ (posedge clk)
200 x2b_pre_ok_r <= 1'b0;
201 x2b_act_ok_r <= 1'b0;
204 x2b_wrok_r <= x2b_wrok;
206 x2b_rdok_r <= x2b_rdok;
207 b2x_cmd_r <= b2x_cmd_t;
208 timer0_tc_r <= (ld_trp | ld_trcd) ? 1'b0 : timer0_tc_t;
209 tras_ok_r <= tras_ok_internal;
210 x2b_pre_ok_r <= x2b_pre_ok;
211 x2b_act_ok_r <= x2b_act_ok;
214 wire x2b_wrok_t = (`TARGET_DESIGN == `FPGA) ? x2b_wrok_r : x2b_wrok;
215 wire xfr_ok_t = (`TARGET_DESIGN == `FPGA) ? xfr_ok_r : xfr_ok;
216 wire x2b_rdok_t = (`TARGET_DESIGN == `FPGA) ? x2b_rdok_r : x2b_rdok;
217 wire [1:0] b2x_cmd = (`TARGET_DESIGN == `FPGA) ? b2x_cmd_r : b2x_cmd_t;
218 wire timer0_tc = (`TARGET_DESIGN == `FPGA) ? timer0_tc_r : timer0_tc_t;
219 assign tras_ok = (`TARGET_DESIGN == `FPGA) ? tras_ok_r : tras_ok_internal;
220 wire x2b_pre_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_pre_ok_r : x2b_pre_ok;
221 wire x2b_act_ok_t = (`TARGET_DESIGN == `FPGA) ? x2b_act_ok_r : x2b_act_ok;
223 /*** Timing Break Logic Added for FPGA - End****/
226 always @ (posedge clk)
231 bank_st <= `BANK_IDLE;
236 bank_valid <= (x2b_refresh || bank_prech_page_closed) ? 1'b0 : // force the bank status to be invalid
237 (activate_bank) ? 1'b1 : bank_valid;
239 tras_cntr <= (activate_bank) ? tras_delay :
240 (~tras_ok_internal) ? tras_cntr - 4'b1 : 4'b0;
242 timer0 <= (ld_trp) ? trp_delay :
243 (ld_trcd) ? trcd_delay :
244 (timer0 != 'h0) ? timer0 - 4'b1 : timer0;
246 bank_st <= next_bank_st;
248 end // else: !if(~reset_n)
250 always @ (posedge clk) begin
252 bank_row <= (bank_st == `BANK_ACT) ? b2x_addr : bank_row;
263 l_sdr_dma_last <= 1'b0;
267 l_start <= r2b_start;
272 l_write <= r2b_write;
273 l_raddr <= r2b_raddr;
274 l_caddr <= r2b_caddr;
275 l_sdr_dma_last <= sdr_dma_last;
279 end // always @ (posedge clk)
281 assign tras_ok_internal = ~|tras_cntr;
283 assign activate_bank = (b2x_cmd == `OP_ACT) & x2b_ack;
285 assign page_hit = (r2b_raddr == bank_row) ? bank_valid : 1'b0; // its a hit only if bank is valid
287 assign timer0_tc_t = ~|timer0;
289 assign ld_trp = (b2x_cmd == `OP_PRE) ? x2b_ack : 1'b0;
291 assign ld_trcd = (b2x_cmd == `OP_ACT) ? x2b_ack : 1'b0;
297 bank_prech_page_closed = 1'b0;
302 next_bank_st = bank_st;
307 if(`TARGET_DESIGN == `FPGA) begin // To break the timing, b2x request are generated delayed
309 next_bank_st = `BANK_IDLE;
311 else if (page_hit) begin
313 b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
314 next_bank_st = `BANK_XFR;
316 else begin // page_miss
319 next_bank_st = `BANK_PRE; // bank was precharged on l_sdr_dma_last
320 end // else: !if(page_hit)
321 end else begin // ASIC
323 bank_prech_page_closed = 1'b0;
328 next_bank_st = `BANK_IDLE;
330 else if (page_hit) begin
331 b2x_req = (r2b_write) ? x2b_wrok_t & xfr_ok_t :
332 x2b_rdok_t & xfr_ok_t;
333 b2x_cmd_t = (r2b_write) ? `OP_WR : `OP_RD;
335 b2x_addr = r2b_caddr;
336 next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_XFR; // in case of hit, stay here till xfr sm acks
338 else begin // page_miss
339 b2x_req = tras_ok & x2b_pre_ok_t;
342 b2x_addr = r2b_raddr & 13'hBFF; // Dont want to pre all banks!
343 next_bank_st = (l_sdr_dma_last) ? `BANK_PRE : (x2b_ack) ? `BANK_ACT : `BANK_PRE; // bank was precharged on l_sdr_dma_last
344 end // else: !if(page_hit)
346 end // case: `BANK_IDLE
349 b2x_req = tras_ok & x2b_pre_ok_t;
352 b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
353 bank_prech_page_closed = 1'b0;
354 next_bank_st = (x2b_ack) ? `BANK_ACT : `BANK_PRE;
355 end // case: `BANK_PRE
358 b2x_req = timer0_tc & x2b_act_ok_t;
362 bank_prech_page_closed = 1'b0;
363 next_bank_st = (x2b_ack) ? `BANK_XFR : `BANK_ACT;
364 end // case: `BANK_ACT
367 b2x_req = (l_write) ? timer0_tc & x2b_wrok_t & xfr_ok_t :
368 timer0_tc & x2b_rdok_t & xfr_ok_t;
369 b2x_cmd_t = (l_write) ? `OP_WR : `OP_RD;
372 bank_prech_page_closed = 1'b0;
373 next_bank_st = (x2b_refresh) ? `BANK_ACT :
374 (x2b_ack & l_sdr_dma_last) ? `BANK_DMA_LAST_PRE :
375 (x2b_ack) ? `BANK_IDLE : `BANK_XFR;
376 end // case: `BANK_XFR
378 `BANK_DMA_LAST_PRE : begin
379 b2x_req = tras_ok & x2b_pre_ok_t;
382 b2x_addr = l_raddr & 13'hBFF; // Dont want to pre all banks!
383 bank_prech_page_closed = 1'b1;
384 next_bank_st = (x2b_ack) ? `BANK_IDLE : `BANK_DMA_LAST_PRE;
385 end // case: `BANK_DMA_LAST_PRE
387 endcase // case(bank_st)
389 end // always @ (bank_st or ...)
391 assign b2x_start = (bank_st == `BANK_IDLE) ? r2b_start : l_start;
393 assign b2x_last = (bank_st == `BANK_IDLE) ? r2b_last : l_last;
395 assign b2x_id = (bank_st == `BANK_IDLE) ? r2b_req_id : l_id;
397 assign b2x_len = (bank_st == `BANK_IDLE) ? r2b_len : l_len;
399 assign b2x_wrap = (bank_st == `BANK_IDLE) ? r2b_wrap : l_wrap;
401 endmodule // sdr_bank_fsm