AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
mig_7series_v1_9_rank_cntrl.v
1  //*****************************************************************************
2 // (c) Copyright 2008 - 2013 Xilinx, Inc. All rights reserved.
3 //
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
7 // laws.
8 //
9 // DISCLAIMER
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.
30 //
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.
44 //
45 // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
46 // PART OF THIS FILE AT ALL TIMES.
47 //
48 //*****************************************************************************
49 // ____ ____
50 // / /\/ /
51 // /___/ \ / Vendor : Xilinx
52 // \ \ \/ Version : %version
53 // \ \ Application : MIG
54 // / / Filename : rank_cntrl.v
55 // /___/ /\ Date Last Modified : $date$
56 // \ \ / \ Date Created : Tue Jun 30 2009
57 // \___\/\___\
58 //
59 //Device : 7-Series
60 //Design Name : DDR3 SDRAM
61 //Purpose :
62 //Reference :
63 //Revision History :
64 //*****************************************************************************
65 
66 //*****************************************************************************
67 // This block is responsible for managing various rank level timing
68 // parameters. For now, only Four Activate Window (FAW) and Write
69 // To Read delay are implemented here.
70 //
71 // Each rank machine generates its own inhbt_act_faw_r and inhbt_rd.
72 // These per rank machines are driven into the bank machines. Each
73 // bank machines selects the correct inhibits based on the rank
74 // of its current request.
75 //*****************************************************************************
76 
77 `timescale 1 ps / 1 ps
78 
80  (
81  parameter TCQ = 100, // clk->out delay (sim only)
82  parameter BURST_MODE = "8", // Burst length
83  parameter DQRD2DQWR_DLY = 2, // RD->WR DQ Bus Delay
84  parameter CL = 5, // Read CAS latency
85  parameter CWL = 5, // Write CAS latency
86  parameter ID = 0, // Unique ID for each instance
87  parameter nBANK_MACHS = 4, // # bank machines in MC
88  parameter nCK_PER_CLK = 2, // DRAM clock : MC clock
89  parameter nFAW = 30, // four activate window (CKs)
90  parameter nREFRESH_BANK = 8, // # REF commands to pull-in
91  parameter nRRD = 4, // ACT->ACT period (CKs)
92  parameter nWTR = 4, // Internal write->read
93  // delay (CKs)
94  parameter PERIODIC_RD_TIMER_DIV = 20, // Maintenance prescaler divisor
95  // for periodic read timer
96  parameter RANK_BM_BV_WIDTH = 16, // Width required to broadcast a
97  // single bit rank signal among
98  // all the bank machines
99  parameter RANK_WIDTH = 2, // # of bits to count ranks
100  parameter RANKS = 4, // # of ranks of DRAM
101  parameter REFRESH_TIMER_DIV = 39 // Maintenance prescaler divivor
102  // for refresh timer
103  )
104  (
105 
106  // Maintenance requests
107 
108  output periodic_rd_request,
109  output wire refresh_request,
110 
111  // Inhibit signals
112 
113  output reg inhbt_act_faw_r,
114  output reg inhbt_rd,
115  output reg inhbt_wr,
116 
117  // System Inputs
118 
119  input clk,
120  input rst,
121 
122  // User maintenance requests
123 
124  input app_periodic_rd_req,
125  input app_ref_req,
126 
127  // Inputs
128 
129  input [RANK_BM_BV_WIDTH-1:0] act_this_rank_r,
130  input clear_periodic_rd_request,
131  input col_rd_wr,
132  input init_calib_complete,
133  input insert_maint_r1,
134  input maint_prescaler_tick_r,
135  input [RANK_WIDTH-1:0] maint_rank_r,
136  input maint_zq_r,
137  input maint_sre_r,
138  input maint_srx_r,
139  input [(RANKS*nBANK_MACHS)-1:0] rank_busy_r,
140  input refresh_tick,
141  input [nBANK_MACHS-1:0] sending_col,
142  input [nBANK_MACHS-1:0] sending_row,
143  input [RANK_BM_BV_WIDTH-1:0] rd_this_rank_r,
144  input [RANK_BM_BV_WIDTH-1:0] wr_this_rank_r
145 
146  );
147 
148  //***************************************************************************
149  // RRD configuration. The bank machines have a mechanism to prevent RAS to
150  // RAS on adjacent fabric CLK states to the same rank. When
151  // nCK_PER_CLK == 1, this translates to a minimum of 2 for nRRD, 4 for nRRD
152  // when nCK_PER_CLK == 2 and 8 for nRRD when nCK_PER_CLK == 4. Some of the
153  // higher clock rate DDR3 DRAMs have nRRD > 4. The additional RRD inhibit
154  // is worked into the inhbt_faw signal.
155  //***************************************************************************
156 
157  localparam nADD_RRD = nRRD -
158  (
159  (nCK_PER_CLK == 1) ? 2 :
160  (nCK_PER_CLK == 2) ? 4 :
161  /*(nCK_PER_CLK == 4)**/ 8
162  );
163 
164  // divide by nCK_PER_CLK and add a cycle if there's a remainder
165  localparam nRRD_CLKS =
166  (nCK_PER_CLK == 1) ? nADD_RRD :
167  (nCK_PER_CLK == 2) ? ((nADD_RRD/2)+(nADD_RRD%2)) :
168  /*(nCK_PER_CLK == 4)**/ ((nADD_RRD/4)+((nADD_RRD%4) ? 1 : 0));
169 
170  // take binary log to obtain counter width and add a tick for the idle cycle
171  localparam ADD_RRD_CNTR_WIDTH = clogb2(nRRD_CLKS + /* idle state **/ 1);
172 
173  //***************************************************************************
174  // Internal signals
175  //***************************************************************************
176  reg act_this_rank;
177  integer i; // loop invariant
178 
179  //***************************************************************************
180  // Function clogb2
181  // Description:
182  // This function performs binary logarithm and rounds up
183  // Inputs:
184  // size: integer to perform binary log upon
185  // Outputs:
186  // clogb2: result of binary logarithm, rounded up
187  //***************************************************************************
188 
189  function integer clogb2 (input integer size);
190  begin
191 
192  size = size - 1;
193 
194  // increment clogb2 from 1 for each bit in size
195  for (clogb2 = 1; size > 1; clogb2 = clogb2 + 1)
196  size = size >> 1;
197 
198  end
199  endfunction // clogb2
200 
201  //***************************************************************************
202  // Determine if this rank has been activated. act_this_rank_r is a
203  // registered bit vector from individual bank machines indicating the
204  // corresponding bank machine is sending
205  // an activate. Timing is improved with this method.
206  //***************************************************************************
207 
208  always @(/*AS**/act_this_rank_r or sending_row) begin
209 
210  act_this_rank = 1'b0;
211 
212  for (i = 0; i < nBANK_MACHS; i = i + 1)
213  act_this_rank =
214  act_this_rank || (sending_row[i] && act_this_rank_r[(i*RANKS)+ID]);
215 
216  end
217 
218 
219 
220  reg add_rrd_inhbt = 1'b0;
221  generate
222  if (nADD_RRD > 0 && ADD_RRD_CNTR_WIDTH > 1) begin :add_rdd1
223  reg[ADD_RRD_CNTR_WIDTH-1:0] add_rrd_ns;
224  reg[ADD_RRD_CNTR_WIDTH-1:0] add_rrd_r;
225  always @(/*AS**/act_this_rank or add_rrd_r or rst) begin
226  add_rrd_ns = add_rrd_r;
227  if (rst) add_rrd_ns = {ADD_RRD_CNTR_WIDTH{1'b0}};
228  else
229  if (act_this_rank)
230  add_rrd_ns = nRRD_CLKS[0+:ADD_RRD_CNTR_WIDTH];
231  else if (|add_rrd_r) add_rrd_ns =
232  add_rrd_r - {{ADD_RRD_CNTR_WIDTH-1{1'b0}}, 1'b1};
233  end
234  always @(posedge clk) add_rrd_r <= #TCQ add_rrd_ns;
235  always @(/*AS**/add_rrd_ns) add_rrd_inhbt = |add_rrd_ns;
236  end // add_rdd1
237  else if (nADD_RRD > 0) begin :add_rdd0
238  reg[ADD_RRD_CNTR_WIDTH-1:0] add_rrd_ns;
239  reg[ADD_RRD_CNTR_WIDTH-1:0] add_rrd_r;
240  always @(/*AS**/act_this_rank or add_rrd_r or rst) begin
241  add_rrd_ns = add_rrd_r;
242  if (rst) add_rrd_ns = {ADD_RRD_CNTR_WIDTH{1'b0}};
243  else
244  if (act_this_rank)
245  add_rrd_ns = nRRD_CLKS[0+:ADD_RRD_CNTR_WIDTH];
246  else if (|add_rrd_r) add_rrd_ns =
247  add_rrd_r - {1'b1};
248  end
249  always @(posedge clk) add_rrd_r <= #TCQ add_rrd_ns;
250  always @(/*AS**/add_rrd_ns) add_rrd_inhbt = |add_rrd_ns;
251  end // add_rdd0
252  endgenerate
253 
254 
255 // Compute inhbt_act_faw_r. Only allow a limited number of activates
256 // in a window. Both the number of activates and the window are
257 // configurable. This depends on the RRD mechanism to prevent
258 // two consecutive activates to the same rank.
259 //
260 // Subtract three from the specified nFAW. Subtract three because:
261 // -Zero for the delay into the SRL is really one state.
262 // -Sending_row is used to trigger the delay. Sending_row is one
263 // state delayed from the arb.
264 // -inhbt_act_faw_r is registered to make timing work, hence the
265 // generation needs to be one state early.
266 
267  localparam nFAW_CLKS = (nCK_PER_CLK == 1)
268  ? nFAW
269  : (nCK_PER_CLK == 2) ? ((nFAW/2) + (nFAW%2)) :
270  ((nFAW/4) + ((nFAW%4) ? 1 : 0));
271 
272  generate
273  begin : inhbt_act_faw
274  wire act_delayed;
275  wire [4:0] shift_depth = nFAW_CLKS[4:0] - 5'd3;
276 
277  SRLC32E #(.INIT(32'h00000000) ) SRLC32E0
278  (.Q(act_delayed), // SRL data output
279  .Q31(), // SRL cascade output pin
280  .A(shift_depth), // 5-bit shift depth select input
281  .CE(1'b1), // Clock enable input
282  .CLK(clk), // Clock input
283  .D(act_this_rank) // SRL data input
284  );
285 
286  reg [2:0] faw_cnt_ns;
287  reg [2:0] faw_cnt_r;
288  reg inhbt_act_faw_ns;
289  always @(/*AS**/act_delayed or act_this_rank or add_rrd_inhbt
290  or faw_cnt_r or rst) begin
291  if (rst) faw_cnt_ns = 3'b0;
292  else begin
293  faw_cnt_ns = faw_cnt_r;
294  if (act_this_rank) faw_cnt_ns = faw_cnt_r + 3'b1;
295  if (act_delayed) faw_cnt_ns = faw_cnt_ns - 3'b1;
296  end
297  inhbt_act_faw_ns = (faw_cnt_ns == 3'h4) || add_rrd_inhbt;
298  end
299  always @(posedge clk) faw_cnt_r <= #TCQ faw_cnt_ns;
300  always @(posedge clk) inhbt_act_faw_r <= #TCQ inhbt_act_faw_ns;
301  end // block: inhbt_act_faw
302  endgenerate
303 
304 
305 // In the DRAM spec, tWTR starts from CK following the end of the data
306 // burst. Since we don't directly have that spec, the wtr timer is
307 // based on when the CAS write command is sent to the DRAM.
308 //
309 // To compute the wtr timer value, first compute the time from the write command
310 // to the read command. This is CWL + data_time + nWTR.
311 //
312 // Two is subtracted from the required wtr time since the timer
313 // starts two states after the arbitration cycle.
314 
315  localparam ONE = 1;
316  localparam TWO = 2;
317 
318  localparam CASWR2CASRD = CWL + (BURST_MODE == "4" ? 2 : 4) + nWTR;
319  localparam CASWR2CASRD_CLKS = (nCK_PER_CLK == 1)
320  ? CASWR2CASRD :
321  (nCK_PER_CLK == 2)
322  ? ((CASWR2CASRD / 2) + (CASWR2CASRD % 2)) :
323  ((CASWR2CASRD / 4) + ((CASWR2CASRD % 4) ? 1 :0));
324  localparam WTR_CNT_WIDTH = clogb2(CASWR2CASRD_CLKS);
325 
326  generate
327  begin : wtr_timer
328 
329  reg write_this_rank;
330  always @(/*AS**/sending_col or wr_this_rank_r) begin
331  write_this_rank = 1'b0;
332  for (i = 0; i < nBANK_MACHS; i = i + 1)
333  write_this_rank =
334  write_this_rank || (sending_col[i] && wr_this_rank_r[(i*RANKS)+ID]);
335  end
336 
337  reg [WTR_CNT_WIDTH-1:0] wtr_cnt_r;
338  reg [WTR_CNT_WIDTH-1:0] wtr_cnt_ns;
339 
340  always @(/*AS**/rst or write_this_rank or wtr_cnt_r)
341  if (rst) wtr_cnt_ns = {WTR_CNT_WIDTH{1'b0}};
342  else begin
343  wtr_cnt_ns = wtr_cnt_r;
344  if (write_this_rank) wtr_cnt_ns =
345  CASWR2CASRD_CLKS[WTR_CNT_WIDTH-1:0] - ONE[WTR_CNT_WIDTH-1:0];
346  else if (|wtr_cnt_r) wtr_cnt_ns = wtr_cnt_r - ONE[WTR_CNT_WIDTH-1:0];
347  end
348 
349  wire inhbt_rd_ns = |wtr_cnt_ns;
350 
351  always @(posedge clk) wtr_cnt_r <= #TCQ wtr_cnt_ns;
352  always @(inhbt_rd_ns) inhbt_rd = inhbt_rd_ns;
353 
354  end
355  endgenerate
356 
357 // In the DRAM spec (with AL = 0), the read-to-write command delay is implied to
358 // be CL + data_time + 2 tCK - CWL. The CL + data_time - CWL terms ensure the
359 // read and write data do not collide on the DQ bus. The 2 tCK ensures a gap
360 // between them. Here, we allow the user to tune this fixed term via the
361 // DQRD2DQWR_DLY parameter. There's a potential for optimization by relocating
362 // this to the rank_common module, since this is a DQ/DQS bus-level requirement,
363 // not a per-rank requirement.
364 
365  localparam CASRD2CASWR = CL + (BURST_MODE == "4" ? 2 : 4) + DQRD2DQWR_DLY - CWL;
366  localparam CASRD2CASWR_CLKS = (nCK_PER_CLK == 1)
367  ? CASRD2CASWR :
368  (nCK_PER_CLK == 2)
369  ? ((CASRD2CASWR / 2) + (CASRD2CASWR % 2)) :
370  ((CASRD2CASWR / 4) + ((CASRD2CASWR % 4) ? 1 :0));
371  localparam RTW_CNT_WIDTH = clogb2(CASRD2CASWR_CLKS);
372 
373  generate
374  begin : rtw_timer
375 
376  reg read_this_rank;
377  always @(/*AS**/sending_col or rd_this_rank_r) begin
378  read_this_rank = 1'b0;
379  for (i = 0; i < nBANK_MACHS; i = i + 1)
380  read_this_rank =
381  read_this_rank || (sending_col[i] && rd_this_rank_r[(i*RANKS)+ID]);
382  end
383 
384  reg [RTW_CNT_WIDTH-1:0] rtw_cnt_r;
385  reg [RTW_CNT_WIDTH-1:0] rtw_cnt_ns;
386 
387  always @(/*AS**/rst or col_rd_wr or sending_col or rtw_cnt_r)
388  if (rst) rtw_cnt_ns = {RTW_CNT_WIDTH{1'b0}};
389  else begin
390  rtw_cnt_ns = rtw_cnt_r;
391  if (col_rd_wr && |sending_col) rtw_cnt_ns =
392  CASRD2CASWR_CLKS[RTW_CNT_WIDTH-1:0] - ONE[RTW_CNT_WIDTH-1:0];
393  else if (|rtw_cnt_r) rtw_cnt_ns = rtw_cnt_r - ONE[RTW_CNT_WIDTH-1:0];
394  end
395 
396  wire inhbt_wr_ns = |rtw_cnt_ns;
397 
398  always @(posedge clk) rtw_cnt_r <= #TCQ rtw_cnt_ns;
399  always @(inhbt_wr_ns) inhbt_wr = inhbt_wr_ns;
400 
401  end
402  endgenerate
403 
404 // Refresh request generation. Implement a "refresh bank". Referred
405 // to as pullin-in refresh in the JEDEC spec.
406 // The refresh_rank_r counter increments when a refresh to this
407 // rank has been decoded. In the up direction, the count saturates
408 // at nREFRESH_BANK. As specified in the JEDEC spec, nREFRESH_BANK
409 // is normally eight. The counter decrements with each refresh_tick,
410 // saturating at zero. A refresh will be requests when the rank is
411 // not busy and refresh_rank_r != nREFRESH_BANK, or refresh_rank_r
412 // equals zero.
413 
414  localparam REFRESH_BANK_WIDTH = clogb2(nREFRESH_BANK + 1);
415 
416 
417  generate begin : refresh_generation
418  reg my_rank_busy;
419  always @(/*AS**/rank_busy_r) begin
420  my_rank_busy = 1'b0;
421  for (i=0; i < nBANK_MACHS; i=i+1)
422  my_rank_busy = my_rank_busy || rank_busy_r[(i*RANKS)+ID];
423  end
424 
425  wire my_refresh =
426  insert_maint_r1 && ~maint_zq_r && ~maint_sre_r && ~maint_srx_r &&
427  (maint_rank_r == ID[RANK_WIDTH-1:0]);
428 
429  reg [REFRESH_BANK_WIDTH-1:0] refresh_bank_r;
430  reg [REFRESH_BANK_WIDTH-1:0] refresh_bank_ns;
431  always @(/*AS**/app_ref_req or init_calib_complete or my_refresh
432  or refresh_bank_r or refresh_tick)
433  if (~init_calib_complete)
434  if (REFRESH_TIMER_DIV == 0)
435  refresh_bank_ns = nREFRESH_BANK[0+:REFRESH_BANK_WIDTH];
436  else refresh_bank_ns = {REFRESH_BANK_WIDTH{1'b0}};
437  else
438  case ({my_refresh, refresh_tick, app_ref_req})
439  3'b000, 3'b110, 3'b101, 3'b111 : refresh_bank_ns = refresh_bank_r;
440  3'b010, 3'b001, 3'b011 : refresh_bank_ns =
441  (|refresh_bank_r)?
442  refresh_bank_r - ONE[0+:REFRESH_BANK_WIDTH]:
443  refresh_bank_r;
444  3'b100 : refresh_bank_ns =
445  refresh_bank_r + ONE[0+:REFRESH_BANK_WIDTH];
446  endcase // case ({my_refresh, refresh_tick})
447  always @(posedge clk) refresh_bank_r <= #TCQ refresh_bank_ns;
448 
449  `ifdef MC_SVA
450  refresh_bank_overflow: assert property (@(posedge clk)
451  (rst || (refresh_bank_r <= nREFRESH_BANK)));
452  refresh_bank_underflow: assert property (@(posedge clk)
453  (rst || ~(~|refresh_bank_r && ~my_refresh && refresh_tick)));
454  refresh_hi_priority: cover property (@(posedge clk)
455  (rst && ~|refresh_bank_ns && (refresh_bank_r ==
456  ONE[0+:REFRESH_BANK_WIDTH])));
457  refresh_bank_full: cover property (@(posedge clk)
458  (rst && (refresh_bank_r ==
459  nREFRESH_BANK[0+:REFRESH_BANK_WIDTH])));
460  `endif
461 
462  assign refresh_request = init_calib_complete &&
463  (~|refresh_bank_r ||
464  ((refresh_bank_r != nREFRESH_BANK[0+:REFRESH_BANK_WIDTH]) && ~my_rank_busy));
465 
466  end
467  endgenerate
468 
469 // Periodic read request generation.
470 
471  localparam PERIODIC_RD_TIMER_WIDTH = clogb2(PERIODIC_RD_TIMER_DIV + /*idle state**/ 1);
472 
473 
474  generate begin : periodic_rd_generation
475  if ( PERIODIC_RD_TIMER_DIV != 0 ) begin // enable periodic reads
476  reg read_this_rank;
477  always @(/*AS**/rd_this_rank_r or sending_col) begin
478  read_this_rank = 1'b0;
479  for (i = 0; i < nBANK_MACHS; i = i + 1)
480  read_this_rank =
481  read_this_rank || (sending_col[i] && rd_this_rank_r[(i*RANKS)+ID]);
482  end
483 
484  reg read_this_rank_r;
485  reg read_this_rank_r1;
486  always @(posedge clk) read_this_rank_r <= #TCQ read_this_rank;
487  always @(posedge clk) read_this_rank_r1 <= #TCQ read_this_rank_r;
488  wire int_read_this_rank = read_this_rank &&
489  (((nCK_PER_CLK == 4) && read_this_rank_r) ||
490  ((nCK_PER_CLK != 4) && read_this_rank_r1));
491 
492  reg periodic_rd_cntr1_ns;
493  reg periodic_rd_cntr1_r;
494  always @(/*AS**/clear_periodic_rd_request or periodic_rd_cntr1_r) begin
495  periodic_rd_cntr1_ns = periodic_rd_cntr1_r;
496  if (clear_periodic_rd_request)
497  periodic_rd_cntr1_ns = periodic_rd_cntr1_r + 1'b1;
498  end
499  always @(posedge clk) begin
500  if (rst) periodic_rd_cntr1_r <= #TCQ 1'b0;
501  else periodic_rd_cntr1_r <= #TCQ periodic_rd_cntr1_ns;
502  end
503 
504  reg [PERIODIC_RD_TIMER_WIDTH-1:0] periodic_rd_timer_r;
505  reg [PERIODIC_RD_TIMER_WIDTH-1:0] periodic_rd_timer_ns;
506  always @(/*AS**/init_calib_complete or maint_prescaler_tick_r
507  or periodic_rd_timer_r or int_read_this_rank) begin
508  periodic_rd_timer_ns = periodic_rd_timer_r;
509  if (~init_calib_complete)
510  periodic_rd_timer_ns = {PERIODIC_RD_TIMER_WIDTH{1'b0}};
511  else if (int_read_this_rank)
512  periodic_rd_timer_ns =
513  PERIODIC_RD_TIMER_DIV[0+:PERIODIC_RD_TIMER_WIDTH];
514  else if (|periodic_rd_timer_r && maint_prescaler_tick_r)
515  periodic_rd_timer_ns =
516  periodic_rd_timer_r - ONE[0+:PERIODIC_RD_TIMER_WIDTH];
517  end
518  always @(posedge clk) periodic_rd_timer_r <= #TCQ periodic_rd_timer_ns;
519 
520  wire periodic_rd_timer_one = maint_prescaler_tick_r &&
521  (periodic_rd_timer_r == ONE[0+:PERIODIC_RD_TIMER_WIDTH]);
522 
523  reg periodic_rd_request_r;
524  wire periodic_rd_request_ns = ~rst &&
525  ((app_periodic_rd_req && init_calib_complete) ||
526  ((PERIODIC_RD_TIMER_DIV != 0) && ~init_calib_complete) ||
527  // (~(read_this_rank || clear_periodic_rd_request) &&
528  (~((int_read_this_rank) || (clear_periodic_rd_request && periodic_rd_cntr1_r)) &&
529  (periodic_rd_request_r || periodic_rd_timer_one)));
530  always @(posedge clk) periodic_rd_request_r <=
531  #TCQ periodic_rd_request_ns;
532 
533  `ifdef MC_SVA
534  read_clears_periodic_rd_request: cover property (@(posedge clk)
535  (rst && (periodic_rd_request_r && read_this_rank)));
536  `endif
537 
538  assign periodic_rd_request = init_calib_complete && periodic_rd_request_r;
539  end else
540  assign periodic_rd_request = 1'b0; //to disable periodic reads
541 
542  end
543  endgenerate
544 
545 
546 endmodule