OpenCores
URL https://opencores.org/ocsvn/usb_fpga_2_14/usb_fpga_2_14/trunk

Subversion Repositories usb_fpga_2_14

[/] [usb_fpga_2_14/] [trunk/] [examples/] [memfifo/] [fpga-2.14/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [controller/] [mig_7series_v2_3_rank_cntrl.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ZTEX
//*****************************************************************************
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
 
79
module mig_7series_v2_3_rank_cntrl #
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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.