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 *******************************************************************/
49 module sdrc_bank_ctl (clk,
51 a2b_req_depth, // Number of requests we can buffer
53 /* Req from req_gen */
56 r2b_start, // First chunk of burst
57 r2b_last, // Last chunk of burst
59 r2b_ba, // bank address
60 r2b_raddr, // row address
61 r2b_caddr, // col address
63 r2b_write, // write request
64 b2r_arb_ok, // OK to arbitrate for next xfr
67 /* Transfer request to xfr_ctl */
68 b2x_idle, // All banks are idle
69 b2x_req, // Request to xfr_ctl
70 b2x_start, // first chunk of transfer
71 b2x_last, // last chunk of transfer
73 b2x_id, // Transfer ID
74 b2x_ba, // bank address
75 b2x_addr, // row/col address
76 b2x_len, // transfer length
77 b2x_cmd, // transfer command
78 x2b_ack, // command accepted
80 /* Status to/from xfr_ctl */
81 b2x_tras_ok, // TRAS OK for all banks
82 x2b_refresh, // We did a refresh
83 x2b_pre_ok, // OK to do a precharge (per bank)
84 x2b_act_ok, // OK to do an activate
85 x2b_rdok, // OK to do a read
86 x2b_wrok, // OK to do a write
90 sdr_req_norm_dma_last,
93 tras_delay, // Active to precharge delay
94 trp_delay, // Precharge to active delay
95 trcd_delay); // Active to R/W delay
97 `define SDR_REQ_ID_W 4
99 `define SDR_RFSH_TIMER_W 12
100 `define SDR_RFSH_ROW_CNT_W 3
109 // SDRAM Commands (CS_N, RAS_N, CAS_N, WE_N)
111 `define SDR_DESEL 4'b1111
112 `define SDR_NOOP 4'b0111
113 `define SDR_ACTIVATE 4'b0011
114 `define SDR_READ 4'b0101
115 `define SDR_WRITE 4'b0100
116 `define SDR_BT 4'b0110
117 `define SDR_PRECHARGE 4'b0010
118 `define SDR_REFRESH 4'b0001
119 `define SDR_MODE 4'b0000
123 `define TARGET_DESIGN `ASIC
124 // 12 bit subtractor is not feasibile for FPGA, so changed to 6 bits
125 `define REQ_BW (`TARGET_DESIGN == `FPGA) ? 6 : 12 // Request Width
128 parameter SDR_DW = 64; // SDR Data Width
129 parameter SDR_BW = 8; // SDR Byte Width
132 input [1:0] a2b_req_depth;
134 /* Req from bank_ctl */
135 input r2b_req, r2b_start, r2b_last,
137 input [`SDR_REQ_ID_W-1:0] r2b_req_id;
139 input [12:0] r2b_raddr;
140 input [12:0] r2b_caddr;
141 input [`REQ_BW-1:0] r2b_len;
142 output b2r_arb_ok, b2r_ack;
143 input sdr_req_norm_dma_last;
146 output b2x_idle, b2x_req, b2x_start, b2x_last,
147 b2x_tras_ok, b2x_wrap;
148 output [`SDR_REQ_ID_W-1:0] b2x_id;
150 output [12:0] b2x_addr;
151 output [`REQ_BW-1:0] b2x_len;
152 output [1:0] b2x_cmd;
155 /* Status from xfr_ctl */
156 input [3:0] x2b_pre_ok;
157 input x2b_refresh, x2b_act_ok, x2b_rdok,
160 input [3:0] tras_delay, trp_delay, trcd_delay;
162 input [1:0] xfr_bank_sel;
164 /****************************************************************************/
167 wire [3:0] r2i_req, i2r_ack, i2x_req,
168 i2x_start, i2x_last, i2x_wrap, tras_ok;
169 wire [12:0] i2x_addr0, i2x_addr1, i2x_addr2, i2x_addr3;
170 wire [`REQ_BW-1:0] i2x_len0, i2x_len1, i2x_len2, i2x_len3;
171 wire [1:0] i2x_cmd0, i2x_cmd1, i2x_cmd2, i2x_cmd3;
172 wire [`SDR_REQ_ID_W-1:0] i2x_id0, i2x_id1, i2x_id2, i2x_id3;
175 wire b2x_idle, b2x_start, b2x_last, b2x_wrap;
176 wire [`SDR_REQ_ID_W-1:0] b2x_id;
177 wire [12:0] b2x_addr;
178 wire [`REQ_BW-1:0] b2x_len;
183 reg [`SDR_REQ_ID_W-1:0] curr_id;
189 // This 8 bit register stores the bank addresses for upto 4 requests.
191 reg [3:0] rank_ba_last;
192 // This 3 bit counter counts the number of requests we have
193 // buffered so far, legal values are 0, 1, 2, 3, or 4.
195 wire [3:0] rank_req, rank_wr_sel;
196 wire rank_fifo_wr, rank_fifo_rd;
197 wire rank_fifo_full, rank_fifo_mt;
199 wire [12:0] bank0_row, bank1_row, bank2_row, bank3_row;
201 assign b2x_tras_ok = &tras_ok;
204 // Distribute the request from req_gen
206 assign r2i_req[0] = (r2b_ba == 2'b00) ? r2b_req & ~rank_fifo_full : 1'b0;
207 assign r2i_req[1] = (r2b_ba == 2'b01) ? r2b_req & ~rank_fifo_full : 1'b0;
208 assign r2i_req[2] = (r2b_ba == 2'b10) ? r2b_req & ~rank_fifo_full : 1'b0;
209 assign r2i_req[3] = (r2b_ba == 2'b11) ? r2b_req & ~rank_fifo_full : 1'b0;
212 Modified the Better FPGA Timing Purpose
213 assign b2r_ack = (r2b_ba == 2'b00) ? i2r_ack[0] :
214 (r2b_ba == 2'b01) ? i2r_ack[1] :
215 (r2b_ba == 2'b10) ? i2r_ack[2] :
216 (r2b_ba == 2'b11) ? i2r_ack[3] : 1'b0;
217 ********************/
218 // Assumption: Only one Ack Will be asserted at a time.
219 assign b2r_ack =|i2r_ack;
221 assign b2r_arb_ok = ~rank_fifo_full;
223 // Put the requests from the 4 bank_fsms into a 4 deep shift
224 // register file. The earliest request is prioritized over the
225 // later requests. Also the number of requests we are allowed to
226 // buffer is limited by a 2 bit external input
228 // Mux the req/cmd to xfr_ctl. Allow RD/WR commands from the request in
229 // rank0, allow only PR/ACT commands from the requests in other ranks
230 // If the rank_fifo is empty, send the request from the bank addressed by
233 // In FPGA Mode, to improve the timing, also send the rank_ba
234 assign xfr_ba = (`TARGET_DESIGN == `FPGA) ? rank_ba[1:0]:
235 ((rank_fifo_mt) ? r2b_ba : rank_ba[1:0]);
236 assign xfr_ba_last = (`TARGET_DESIGN == `FPGA) ? rank_ba_last[0]:
237 ((rank_fifo_mt) ? sdr_req_norm_dma_last : rank_ba_last[0]);
239 assign rank_req[0] = i2x_req[xfr_ba]; // each rank generates requests
241 assign rank_req[1] = (rank_cnt < 3'h2) ? 1'b0 :
242 (rank_ba[3:2] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
243 (rank_ba[3:2] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
244 (rank_ba[3:2] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
245 i2x_req[3] & ~i2x_cmd3[1];
247 assign rank_req[2] = (rank_cnt < 3'h3) ? 1'b0 :
248 (rank_ba[5:4] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
249 (rank_ba[5:4] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
250 (rank_ba[5:4] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
251 i2x_req[3] & ~i2x_cmd3[1];
253 assign rank_req[3] = (rank_cnt < 3'h4) ? 1'b0 :
254 (rank_ba[7:6] == 2'b00) ? i2x_req[0] & ~i2x_cmd0[1] :
255 (rank_ba[7:6] == 2'b01) ? i2x_req[1] & ~i2x_cmd1[1] :
256 (rank_ba[7:6] == 2'b10) ? i2x_req[2] & ~i2x_cmd2[1] :
257 i2x_req[3] & ~i2x_cmd3[1];
263 if(`TARGET_DESIGN == `ASIC) begin // Support Multiple Rank request only on ASIC
264 if (rank_req[0]) begin
267 end // if (rank_req[0])
268 else if (rank_req[1]) begin
270 b2x_ba = rank_ba[3:2];
271 end // if (rank_req[1])
272 else if (rank_req[2]) begin
274 b2x_ba = rank_ba[5:4];
275 end // if (rank_req[2])
276 else if (rank_req[3]) begin
278 b2x_ba = rank_ba[7:6];
279 end // if (rank_req[3])
280 end else begin // If FPGA
281 if (rank_req[0]) begin
285 end // always @ (rank_req or rank_fifo_mt or r2b_ba or rank_ba)
287 assign b2x_idle = rank_fifo_mt;
288 assign b2x_start = i2x_start[b2x_ba];
289 assign b2x_last = i2x_last[b2x_ba];
290 assign b2x_wrap = i2x_wrap[b2x_ba];
292 assign b2x_addr = (b2x_ba == 2'b11) ? i2x_addr3 :
293 (b2x_ba == 2'b10) ? i2x_addr2 :
294 (b2x_ba == 2'b01) ? i2x_addr1 : i2x_addr0;
296 assign b2x_len = (b2x_ba == 2'b11) ? i2x_len3 :
297 (b2x_ba == 2'b10) ? i2x_len2 :
298 (b2x_ba == 2'b01) ? i2x_len1 : i2x_len0;
300 assign b2x_cmd = (b2x_ba == 2'b11) ? i2x_cmd3 :
301 (b2x_ba == 2'b10) ? i2x_cmd2 :
302 (b2x_ba == 2'b01) ? i2x_cmd1 : i2x_cmd0;
304 assign b2x_id = (b2x_ba == 2'b11) ? i2x_id3 :
305 (b2x_ba == 2'b10) ? i2x_id2 :
306 (b2x_ba == 2'b01) ? i2x_id1 : i2x_id0;
308 assign x2i_ack[0] = (b2x_ba == 2'b00) ? x2b_ack : 1'b0;
309 assign x2i_ack[1] = (b2x_ba == 2'b01) ? x2b_ack : 1'b0;
310 assign x2i_ack[2] = (b2x_ba == 2'b10) ? x2b_ack : 1'b0;
311 assign x2i_ack[3] = (b2x_ba == 2'b11) ? x2b_ack : 1'b0;
314 // On a write write to selected rank and increment rank_cnt
315 // On a read shift rank_ba right 2 bits and decrement rank_cnt
317 assign rank_fifo_wr = b2r_ack;
319 assign rank_fifo_rd = b2x_req & b2x_cmd[1] & x2b_ack;
321 assign rank_wr_sel[0] = (rank_cnt == 3'h0) ? rank_fifo_wr :
322 (rank_cnt == 3'h1) ? rank_fifo_wr & rank_fifo_rd :
325 assign rank_wr_sel[1] = (rank_cnt == 3'h1) ? rank_fifo_wr & ~rank_fifo_rd :
326 (rank_cnt == 3'h2) ? rank_fifo_wr & rank_fifo_rd :
329 assign rank_wr_sel[2] = (rank_cnt == 3'h2) ? rank_fifo_wr & ~rank_fifo_rd :
330 (rank_cnt == 3'h3) ? rank_fifo_wr & rank_fifo_rd :
333 assign rank_wr_sel[3] = (rank_cnt == 3'h3) ? rank_fifo_wr & ~rank_fifo_rd :
334 (rank_cnt == 3'h4) ? rank_fifo_wr & rank_fifo_rd :
337 assign rank_fifo_mt = (rank_cnt == 3'b0) ? 1'b1 : 1'b0;
339 assign rank_fifo_full = (rank_cnt[2]) ? 1'b1 :
340 (rank_cnt[1:0] == a2b_req_depth) ? 1'b1 : 1'b0;
344 // synopsys translate_off
346 always @ (posedge clk) begin
348 if (~rank_fifo_wr & rank_fifo_rd && rank_cnt == 3'h0) begin
349 $display ("%t: %m: ERROR!!! Read from empty Fifo", $time);
351 end // if (rank_fifo_rd && rank_cnt == 3'h0)
353 if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4) begin
354 $display ("%t: %m: ERROR!!! Write to full Fifo", $time);
356 end // if (rank_fifo_wr && ~rank_fifo_rd && rank_cnt == 3'h4)
358 end // always @ (posedge clk)
360 // synopsys translate_on
362 always @ (posedge clk)
366 rank_ba_last <= 4'b0;
371 rank_cnt <= (rank_fifo_wr & ~rank_fifo_rd) ? rank_cnt + 3'b1 :
372 (~rank_fifo_wr & rank_fifo_rd) ? rank_cnt - 3'b1 :
375 rank_ba[1:0] <= (rank_wr_sel[0]) ? r2b_ba :
376 (rank_fifo_rd) ? rank_ba[3:2] : rank_ba[1:0];
378 rank_ba[3:2] <= (rank_wr_sel[1]) ? r2b_ba :
379 (rank_fifo_rd) ? rank_ba[5:4] : rank_ba[3:2];
381 rank_ba[5:4] <= (rank_wr_sel[2]) ? r2b_ba :
382 (rank_fifo_rd) ? rank_ba[7:6] : rank_ba[5:4];
384 rank_ba[7:6] <= (rank_wr_sel[3]) ? r2b_ba :
385 (rank_fifo_rd) ? 2'b00 : rank_ba[7:6];
387 if(`TARGET_DESIGN == `ASIC) begin // This Logic is implemented for ASIC Only
388 // Note: Currenly top-level does not generate the
389 // sdr_req_norm_dma_last signal and can be tied zero at top-level
390 rank_ba_last[0] <= (rank_wr_sel[0]) ? sdr_req_norm_dma_last :
391 (rank_fifo_rd) ? rank_ba_last[1] : rank_ba_last[0];
393 rank_ba_last[1] <= (rank_wr_sel[1]) ? sdr_req_norm_dma_last :
394 (rank_fifo_rd) ? rank_ba_last[2] : rank_ba_last[1];
396 rank_ba_last[2] <= (rank_wr_sel[2]) ? sdr_req_norm_dma_last :
397 (rank_fifo_rd) ? rank_ba_last[3] : rank_ba_last[2];
399 rank_ba_last[3] <= (rank_wr_sel[3]) ? sdr_req_norm_dma_last :
400 (rank_fifo_rd) ? 1'b0 : rank_ba_last[3];
403 end // else: !if(~reset_n)
405 assign xfr_ok[0] = (xfr_ba == 2'b00) ? 1'b1 : 1'b0;
406 assign xfr_ok[1] = (xfr_ba == 2'b01) ? 1'b1 : 1'b0;
407 assign xfr_ok[2] = (xfr_ba == 2'b10) ? 1'b1 : 1'b0;
408 assign xfr_ok[3] = (xfr_ba == 2'b11) ? 1'b1 : 1'b0;
410 /****************************************************************************/
411 // Instantiate Bank Ctl FSM 0
413 sdrc_bank_fsm bank0_fsm (.clk (clk),
416 /* Req from req_gen */
417 .r2b_req (r2i_req[0]),
418 .r2b_req_id (r2b_req_id),
419 .r2b_start (r2b_start),
420 .r2b_last (r2b_last),
421 .r2b_wrap (r2b_wrap),
422 .r2b_raddr (r2b_raddr),
423 .r2b_caddr (r2b_caddr),
425 .r2b_write (r2b_write),
426 .b2r_ack (i2r_ack[0]),
427 .sdr_dma_last(rank_ba_last[0]),
429 /* Transfer request to xfr_ctl */
430 .b2x_req (i2x_req[0]),
431 .b2x_start (i2x_start[0]),
432 .b2x_last (i2x_last[0]),
433 .b2x_wrap (i2x_wrap[0]),
435 .b2x_addr (i2x_addr0),
438 .x2b_ack (x2i_ack[0]),
440 /* Status to/from xfr_ctl */
441 .tras_ok (tras_ok[0]),
443 .x2b_refresh (x2b_refresh),
444 .x2b_pre_ok (x2b_pre_ok[0]),
445 .x2b_act_ok (x2b_act_ok),
446 .x2b_rdok (x2b_rdok),
447 .x2b_wrok (x2b_wrok),
449 .bank_row(bank0_row),
452 .tras_delay (tras_delay),
453 .trp_delay (trp_delay),
454 .trcd_delay (trcd_delay));
456 /****************************************************************************/
457 // Instantiate Bank Ctl FSM 1
459 sdrc_bank_fsm bank1_fsm (.clk (clk),
462 /* Req from req_gen */
463 .r2b_req (r2i_req[1]),
464 .r2b_req_id (r2b_req_id),
465 .r2b_start (r2b_start),
466 .r2b_last (r2b_last),
467 .r2b_wrap (r2b_wrap),
468 .r2b_raddr (r2b_raddr),
469 .r2b_caddr (r2b_caddr),
471 .r2b_write (r2b_write),
472 .b2r_ack (i2r_ack[1]),
473 .sdr_dma_last(rank_ba_last[1]),
475 /* Transfer request to xfr_ctl */
476 .b2x_req (i2x_req[1]),
477 .b2x_start (i2x_start[1]),
478 .b2x_last (i2x_last[1]),
479 .b2x_wrap (i2x_wrap[1]),
481 .b2x_addr (i2x_addr1),
484 .x2b_ack (x2i_ack[1]),
486 /* Status to/from xfr_ctl */
487 .tras_ok (tras_ok[1]),
489 .x2b_refresh (x2b_refresh),
490 .x2b_pre_ok (x2b_pre_ok[1]),
491 .x2b_act_ok (x2b_act_ok),
492 .x2b_rdok (x2b_rdok),
493 .x2b_wrok (x2b_wrok),
495 .bank_row(bank1_row),
498 .tras_delay (tras_delay),
499 .trp_delay (trp_delay),
500 .trcd_delay (trcd_delay));
502 /****************************************************************************/
503 // Instantiate Bank Ctl FSM 2
505 sdrc_bank_fsm bank2_fsm (.clk (clk),
508 /* Req from req_gen */
509 .r2b_req (r2i_req[2]),
510 .r2b_req_id (r2b_req_id),
511 .r2b_start (r2b_start),
512 .r2b_last (r2b_last),
513 .r2b_wrap (r2b_wrap),
514 .r2b_raddr (r2b_raddr),
515 .r2b_caddr (r2b_caddr),
517 .r2b_write (r2b_write),
518 .b2r_ack (i2r_ack[2]),
519 .sdr_dma_last(rank_ba_last[2]),
521 /* Transfer request to xfr_ctl */
522 .b2x_req (i2x_req[2]),
523 .b2x_start (i2x_start[2]),
524 .b2x_last (i2x_last[2]),
525 .b2x_wrap (i2x_wrap[2]),
527 .b2x_addr (i2x_addr2),
530 .x2b_ack (x2i_ack[2]),
532 /* Status to/from xfr_ctl */
533 .tras_ok (tras_ok[2]),
535 .x2b_refresh (x2b_refresh),
536 .x2b_pre_ok (x2b_pre_ok[2]),
537 .x2b_act_ok (x2b_act_ok),
538 .x2b_rdok (x2b_rdok),
539 .x2b_wrok (x2b_wrok),
541 .bank_row(bank2_row),
544 .tras_delay (tras_delay),
545 .trp_delay (trp_delay),
546 .trcd_delay (trcd_delay));
548 /****************************************************************************/
549 // Instantiate Bank Ctl FSM 3
551 sdrc_bank_fsm bank3_fsm (.clk (clk),
554 /* Req from req_gen */
555 .r2b_req (r2i_req[3]),
556 .r2b_req_id (r2b_req_id),
557 .r2b_start (r2b_start),
558 .r2b_last (r2b_last),
559 .r2b_wrap (r2b_wrap),
560 .r2b_raddr (r2b_raddr),
561 .r2b_caddr (r2b_caddr),
563 .r2b_write (r2b_write),
564 .b2r_ack (i2r_ack[3]),
565 .sdr_dma_last(rank_ba_last[3]),
567 /* Transfer request to xfr_ctl */
568 .b2x_req (i2x_req[3]),
569 .b2x_start (i2x_start[3]),
570 .b2x_last (i2x_last[3]),
571 .b2x_wrap (i2x_wrap[3]),
573 .b2x_addr (i2x_addr3),
576 .x2b_ack (x2i_ack[3]),
578 /* Status to/from xfr_ctl */
579 .tras_ok (tras_ok[3]),
581 .x2b_refresh (x2b_refresh),
582 .x2b_pre_ok (x2b_pre_ok[3]),
583 .x2b_act_ok (x2b_act_ok),
584 .x2b_rdok (x2b_rdok),
585 .x2b_wrok (x2b_wrok),
587 .bank_row(bank3_row),
590 .tras_delay (tras_delay),
591 .trp_delay (trp_delay),
592 .trcd_delay (trcd_delay));
595 /* address for current xfr, debug only */
596 wire [12:0] cur_row = (xfr_bank_sel==3) ? bank3_row:
597 (xfr_bank_sel==2) ? bank2_row:
598 (xfr_bank_sel==1) ? bank1_row: bank0_row;
602 endmodule // sdr_bank_ctl