1 //*****************************************************************************
2 // (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
4 // This file contains confidential and proprietary information
5 // of Xilinx, Inc. and is protected under U.S. and
6 // international copyright and other intellectual property
10 // This disclaimer is not a license and does not grant any
11 // rights to the materials distributed herewith. Except as
12 // otherwise provided in a valid license issued to you by
13 // Xilinx, and to the maximum extent permitted by applicable
14 // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
15 // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
16 // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
17 // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
18 // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
19 // (2) Xilinx shall not be liable (whether in contract or tort,
20 // including negligence, or under any other theory of
21 // liability) for any loss or damage of any kind or nature
22 // related to, arising under or in connection with these
23 // materials, including for any direct, or any indirect,
24 // special, incidental, or consequential loss or damage
25 // (including loss of data, profits, goodwill, or any type of
26 // loss or damage suffered as a result of any action brought
27 // by a third party) even if such damage or loss was
28 // reasonably foreseeable or Xilinx had been advised of the
29 // possibility of the same.
31 // CRITICAL APPLICATIONS
32 // Xilinx products are not designed or intended to be fail-
33 // safe, or for use in any application requiring fail-safe
34 // performance, such as life-support or safety devices or
35 // systems, Class III medical devices, nuclear facilities,
36 // applications related to the deployment of airbags, or any
37 // other applications that could lead to death, personal
38 // injury, or severe property or environmental damage
39 // (individually and collectively, "Critical
40 // Applications"). Customer assumes the sole risk and
41 // liability of any use of Xilinx products in Critical
42 // Applications, subject only to applicable laws and
43 // regulations governing limitations on product liability.
45 // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46 // PART OF THIS FILE AT ALL TIMES.
48 //*****************************************************************************
51 // /___/ \ / Vendor : Xilinx
52 // \ \ \/ Version : %version
53 // \ \ Application : MIG
54 // / / Filename : arb_row_col.v
55 // /___/ /\ Date Last Modified : $date$
56 // \ \ / \ Date Created : Tue Jun 30 2009
60 //Design Name : DDR3 SDRAM
64 //*****************************************************************************
67 // This block receives request to send row and column commands. These requests
68 // come the individual bank machines. The arbitration winner is selected
69 // and driven back to the bank machines.
71 // The CS enables are generated. For 2:1 mode, row commands are sent
72 // in the "0" phase, and column commands are sent in the "1" phase.
74 // In 2T mode, a further arbitration is performed between the row
75 // and column commands. The winner of this arbitration inhibits
76 // arbitration by the loser. The winner is allowed to arbitrate, the loser is
77 // blocked until the next state. The winning address command
78 // is repeated on both the "0" and the "1" phases and the CS
79 // is asserted for just the "1" phase.
81 `timescale 1 ps /
1 ps
86 parameter ADDR_CMD_MODE =
"1T",
88 parameter EARLY_WR_DATA_ADDR =
"OFF",
89 parameter nBANK_MACHS =
4,
90 parameter nCK_PER_CLK =
2,
91 parameter nRAS =
37500,
// ACT->PRE cmd period (CKs)
92 parameter nRCD =
12500,
// ACT->R/W delay (CKs)
93 parameter nWR =
6 // Write recovery (CKs)
97 grant_row_r,
grant_pre_r,
sent_row,
sending_row,
sending_pre,
grant_config_r,
98 rnk_config_strobe,
rnk_config_valid_r,
grant_col_r,
99 sending_col,
sent_col,
sent_col_r,
grant_col_wr,
send_cmd0_row,
send_cmd0_col,
100 send_cmd1_row,
send_cmd1_col,
send_cmd2_row,
send_cmd2_col,
send_cmd2_pre,
101 send_cmd3_col,
col_channel_offset,
cs_en0,
cs_en1,
cs_en2,
cs_en3,
102 insert_maint_r1,
rnk_config_kill_rts_col,
104 clk,
rst,
rts_row,
rts_pre,
insert_maint_r,
rts_col,
rtc,
col_rdy_wr
107 // Create a delay when switching ranks
108 localparam RNK2RNK_DLY =
12;
109 localparam RNK2RNK_DLY_CLKS =
110 (
RNK2RNK_DLY /
nCK_PER_CLK) + (
RNK2RNK_DLY %
nCK_PER_CLK ?
1 :
0);
115 input [
nBANK_MACHS-
1:
0]
rts_row;
116 input insert_maint_r;
117 input [
nBANK_MACHS-
1:
0]
rts_col;
118 reg [
RNK2RNK_DLY_CLKS-
1:
0]
rnk_config_strobe_r;
119 wire block_grant_row;
120 wire block_grant_col;
121 wire rnk_config_kill_rts_col_lcl =
122 RNK2RNK_DLY_CLKS >
0 ? |
rnk_config_strobe_r :
1'b0;
124 output rnk_config_kill_rts_col;
125 assign rnk_config_kill_rts_col =
rnk_config_kill_rts_col_lcl;
127 wire [
nBANK_MACHS-
1:
0]
col_request;
128 wire granted_col_ns = |
col_request;
129 wire [
nBANK_MACHS-
1:
0]
row_request =
130 rts_row & {
nBANK_MACHS{~
insert_maint_r}};
131 wire granted_row_ns = |
row_request;
133 if (
ADDR_CMD_MODE ==
"2T" &&
nCK_PER_CLK !=
4)
begin :
row_col_2T_arb
135 rts_col & {
nBANK_MACHS{~(
rnk_config_kill_rts_col_lcl ||
insert_maint_r)}};
136 // Give column command priority whenever previous state has no row request.
137 wire [
1:
0]
row_col_grant;
138 wire [
1:
0]
current_master = ~
granted_row_ns ?
2'b10 :
row_col_grant;
139 wire upd_last_master = ~
granted_row_ns || |
row_col_grant;
144 .
grant_r (
row_col_grant),
145 .
upd_last_master (
upd_last_master),
146 .
current_master (
current_master),
149 .
req ({
granted_row_ns,
granted_col_ns}),
150 .
disable_grant (
1'b0));
151 assign {
block_grant_col,
block_grant_row} =
row_col_grant;
153 else begin :
row_col_1T_arb
154 assign col_request =
rts_col & {
nBANK_MACHS{~
rnk_config_kill_rts_col_lcl}};
155 assign block_grant_row =
1'b0;
156 assign block_grant_col =
1'b0;
160 // Row address/command arbitration.
161 wire[
nBANK_MACHS-
1:
0]
grant_row_r_lcl;
162 output wire[
nBANK_MACHS-
1:
0]
grant_row_r;
163 assign grant_row_r =
grant_row_r_lcl;
165 always @(
posedge clk)
granted_row_r <= #TCQ
granted_row_ns;
166 wire sent_row_lcl =
granted_row_r && ~
block_grant_row;
167 output wire sent_row;
168 assign sent_row =
sent_row_lcl;
170 (.
WIDTH (
nBANK_MACHS))
173 .
grant_r (
grant_row_r_lcl[
nBANK_MACHS-
1:
0]),
174 .
upd_last_master (
sent_row_lcl),
175 .
current_master (
grant_row_r_lcl[
nBANK_MACHS-
1:
0]),
179 .
disable_grant (
1'b0));
181 output wire [
nBANK_MACHS-
1:
0]
sending_row;
182 assign sending_row =
grant_row_r_lcl & {
nBANK_MACHS{~
block_grant_row}};
184 // Precharge arbitration for 4:1 mode
185 input [
nBANK_MACHS-
1:
0]
rts_pre;
186 output wire[
nBANK_MACHS-
1:
0]
grant_pre_r;
187 output wire [
nBANK_MACHS-
1:
0]
sending_pre;
192 if((
nCK_PER_CLK ==
4) && (
ADDR_CMD_MODE !=
"2T"))
begin :
pre_4_1_1T_arb
195 wire[
nBANK_MACHS-
1:
0]
grant_pre_r_lcl;
197 wire granted_pre_ns = |
rts_pre;
198 assign grant_pre_r =
grant_pre_r_lcl;
199 always @(
posedge clk)
granted_pre_r <= #TCQ
granted_pre_ns;
200 assign sent_pre_lcl =
granted_pre_r;
201 assign sending_pre =
grant_pre_r_lcl;
204 (.
WIDTH (
nBANK_MACHS))
207 .
grant_r (
grant_pre_r_lcl[
nBANK_MACHS-
1:
0]),
208 .
upd_last_master (
sent_pre_lcl),
209 .
current_master (
grant_pre_r_lcl[
nBANK_MACHS-
1:
0]),
213 .
disable_grant (
1'b0));
220 all_bank_machines_row_arb:
221 cover property (@(
posedge clk) (~rst && &rts_row));
224 // Rank config arbitration.
225 input [
nBANK_MACHS-
1:
0] rtc;
226 wire [nBANK_MACHS-
1:
0]
grant_config_r_lcl;
227 output wire [
nBANK_MACHS-
1:
0]
grant_config_r;
228 assign grant_config_r =
grant_config_r_lcl;
229 wire upd_rnk_config_last_master;
231 (.
WIDTH (
nBANK_MACHS))
234 .
grant_r (
grant_config_r_lcl[
nBANK_MACHS-
1:
0]),
235 .
upd_last_master (
upd_rnk_config_last_master),
236 .
current_master (
grant_config_r_lcl[
nBANK_MACHS-
1:
0]),
239 .
req (
rtc[
nBANK_MACHS-
1:
0]),
240 .
disable_grant (
1'b0));
243 all_bank_machines_config_arb: cover property (@(
posedge clk) (~rst && &rtc));
246 wire rnk_config_strobe_ns = ~rnk_config_strobe_r[
0] && |rtc && ~granted_col_ns;
247 always @(
posedge clk)
rnk_config_strobe_r[
0] <= #TCQ
rnk_config_strobe_ns;
251 for(
i =
1;
i <
RNK2RNK_DLY_CLKS;
i =
i +
1)
252 always @(
posedge clk)
253 rnk_config_strobe_r[i] <= #TCQ rnk_config_strobe_r[i-
1];
256 output wire rnk_config_strobe;
257 assign rnk_config_strobe =
rnk_config_strobe_r[
0];
259 assign upd_rnk_config_last_master =
rnk_config_strobe_r[
0];
261 // Generate rnk_config_valid.
262 reg rnk_config_valid_r_lcl;
263 wire rnk_config_valid_ns;
264 assign rnk_config_valid_ns =
265 ~
rst && (
rnk_config_valid_r_lcl ||
rnk_config_strobe_ns);
266 always @(
posedge clk)
rnk_config_valid_r_lcl <= #TCQ
rnk_config_valid_ns;
267 output wire rnk_config_valid_r;
268 assign rnk_config_valid_r =
rnk_config_valid_r_lcl;
270 // Column address/command arbitration.
271 wire [
nBANK_MACHS-
1:
0]
grant_col_r_lcl;
272 output wire [
nBANK_MACHS-
1:
0]
grant_col_r;
273 assign grant_col_r =
grant_col_r_lcl;
275 always @(
posedge clk)
granted_col_r <= #TCQ
granted_col_ns;
278 (.
WIDTH (
nBANK_MACHS))
281 .
grant_r (
grant_col_r_lcl[
nBANK_MACHS-
1:
0]),
282 .
upd_last_master (
sent_col_lcl),
283 .
current_master (
grant_col_r_lcl[
nBANK_MACHS-
1:
0]),
287 .
disable_grant (
1'b0));
290 all_bank_machines_col_arb:
291 cover property (@(
posedge clk) (~rst && &rts_col));
294 output wire [nBANK_MACHS-
1:
0]
sending_col;
295 assign sending_col =
grant_col_r_lcl & {
nBANK_MACHS{~
block_grant_col}};
296 assign sent_col_lcl =
granted_col_r && ~
block_grant_col;
297 reg sent_col_lcl_r =
1'b0;
298 always @(
posedge clk)
sent_col_lcl_r <= #TCQ
sent_col_lcl;
299 output wire sent_col;
300 assign sent_col =
sent_col_lcl;
301 output wire sent_col_r;
302 assign sent_col_r =
sent_col_lcl_r;
304 // If we need early wr_data_addr because ECC is on, arbitrate
305 // to see which bank machine might sent the next wr_data_addr;
306 input [
nBANK_MACHS-
1:
0]
col_rdy_wr;
307 output wire [
nBANK_MACHS-
1:
0]
grant_col_wr;
309 if (
EARLY_WR_DATA_ADDR ==
"OFF")
begin :
early_wr_addr_arb_off
310 assign grant_col_wr = {
nBANK_MACHS{
1'b0}};
312 else begin :
early_wr_addr_arb_on
313 wire [
nBANK_MACHS-
1:
0]
grant_col_wr_raw;
315 (.
WIDTH (
nBANK_MACHS))
317 (.
grant_ns (
grant_col_wr_raw),
319 .
upd_last_master (
sent_col_lcl),
320 .
current_master (
grant_col_r_lcl[
nBANK_MACHS-
1:
0]),
324 .
disable_grant (
1'b0));
325 reg [
nBANK_MACHS-
1:
0]
grant_col_wr_r;
326 wire [
nBANK_MACHS-
1:
0]
grant_col_wr_ns =
granted_col_ns
329 always @(
posedge clk)
grant_col_wr_r <= #TCQ
grant_col_wr_ns;
330 assign grant_col_wr =
grant_col_wr_ns;
331 end // block: early_wr_addr_arb_on
334 output reg send_cmd0_row =
1'b0;
335 output reg send_cmd0_col =
1'b0;
336 output reg send_cmd1_row =
1'b0;
337 output reg send_cmd1_col =
1'b0;
338 output reg send_cmd2_row =
1'b0;
339 output reg send_cmd2_col =
1'b0;
340 output reg send_cmd2_pre =
1'b0;
341 output reg send_cmd3_col =
1'b0;
343 output reg cs_en0 =
1'b0;
344 output reg cs_en1 =
1'b0;
345 output reg cs_en2 =
1'b0;
346 output reg cs_en3 =
1'b0;
348 output wire [
5:
0]
col_channel_offset;
350 reg insert_maint_r1_lcl;
351 always @(
posedge clk)
insert_maint_r1_lcl <= #TCQ
insert_maint_r;
352 output wire insert_maint_r1;
353 assign insert_maint_r1 =
insert_maint_r1_lcl;
355 wire sent_row_or_maint =
sent_row_lcl ||
insert_maint_r1_lcl;
356 reg sent_row_or_maint_r =
1'b0;
357 always @(
posedge clk)
sent_row_or_maint_r <= #TCQ
sent_row_or_maint;
359 case ({(
nCK_PER_CLK ==
4), (
nCK_PER_CLK ==
2), (
ADDR_CMD_MODE ==
"2T")})
360 3'b000 :
begin :
one_one_not2T
362 3'b001 :
begin :
one_one_2T
364 3'b010 :
begin :
two_one_not2T
366 if(!(
CWL %
2))
begin // Place column commands on slot 0 for even CWL
368 always @(
sent_col_lcl)
begin
369 cs_en0 =
sent_col_lcl;
370 send_cmd0_col =
sent_col_lcl;
373 always @(
sent_row_or_maint)
begin
374 cs_en1 =
sent_row_or_maint;
375 send_cmd1_row =
sent_row_or_maint;
378 assign col_channel_offset =
0;
382 else begin // Place column commands on slot 1 for odd CWL
384 always @(
sent_row_or_maint)
begin
385 cs_en0 =
sent_row_or_maint;
386 send_cmd0_row =
sent_row_or_maint;
389 always @(
sent_col_lcl)
begin
390 cs_en1 =
sent_col_lcl;
391 send_cmd1_col =
sent_col_lcl;
394 assign col_channel_offset =
1;
399 3'b011 :
begin :
two_one_2T
401 if(!(
CWL %
2))
begin // Place column commands on slot 1->0 for even CWL
403 always @(
sent_row_or_maint_r or sent_col_lcl_r)
404 cs_en0 =
sent_row_or_maint_r ||
sent_col_lcl_r;
406 always @(
sent_row_or_maint or sent_row_or_maint_r)
begin
407 send_cmd0_row =
sent_row_or_maint_r;
408 send_cmd1_row =
sent_row_or_maint;
411 always @(
sent_col_lcl or sent_col_lcl_r)
begin
412 send_cmd0_col =
sent_col_lcl_r;
413 send_cmd1_col =
sent_col_lcl;
416 assign col_channel_offset =
0;
420 else begin // Place column commands on slot 0->1 for odd CWL
422 always @(
sent_col_lcl or sent_row_or_maint)
423 cs_en1 =
sent_row_or_maint ||
sent_col_lcl;
425 always @(
sent_row_or_maint)
begin
426 send_cmd0_row =
sent_row_or_maint;
427 send_cmd1_row =
sent_row_or_maint;
430 always @(
sent_col_lcl)
begin
431 send_cmd0_col =
sent_col_lcl;
432 send_cmd1_col =
sent_col_lcl;
435 assign col_channel_offset =
1;
440 3'b100 :
begin :
four_one_not2T
442 if(!(
CWL %
2))
begin // Place column commands on slot 0 for even CWL
444 always @(
sent_col_lcl)
begin
445 cs_en0 =
sent_col_lcl;
446 send_cmd0_col =
sent_col_lcl;
449 always @(
sent_row_or_maint)
begin
450 cs_en1 =
sent_row_or_maint;
451 send_cmd1_row =
sent_row_or_maint;
454 assign col_channel_offset =
0;
458 else begin // Place column commands on slot 1 for odd CWL
460 always @(
sent_row_or_maint)
begin
461 cs_en0 =
sent_row_or_maint;
462 send_cmd0_row =
sent_row_or_maint;
465 always @(
sent_col_lcl)
begin
466 cs_en1 =
sent_col_lcl;
467 send_cmd1_col =
sent_col_lcl;
470 assign col_channel_offset =
1;
474 always @(
sent_pre_lcl)
begin
475 cs_en2 =
sent_pre_lcl;
476 send_cmd2_pre =
sent_pre_lcl;
480 3'b101 :
begin :
four_one_2T
482 if(!(
CWL %
2))
begin // Place column commands on slot 3->0 for even CWL
484 always @(
sent_col_lcl or sent_col_lcl_r)
begin
485 cs_en0 =
sent_col_lcl_r;
486 send_cmd0_col =
sent_col_lcl_r;
487 send_cmd3_col =
sent_col_lcl;
490 always @(
sent_row_or_maint)
begin
491 cs_en2 =
sent_row_or_maint;
492 send_cmd1_row =
sent_row_or_maint;
493 send_cmd2_row =
sent_row_or_maint;
496 assign col_channel_offset =
0;
500 else begin // Place column commands on slot 2->3 for odd CWL
502 always @(
sent_row_or_maint)
begin
503 cs_en1 =
sent_row_or_maint;
504 send_cmd0_row =
sent_row_or_maint;
505 send_cmd1_row =
sent_row_or_maint;
508 always @(
sent_col_lcl)
begin
509 cs_en3 =
sent_col_lcl;
510 send_cmd2_col =
sent_col_lcl;
511 send_cmd3_col =
sent_col_lcl;
514 assign col_channel_offset =
3;