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.13/] [memfifo.srcs/] [sources_1/] [ip/] [mig_7series_0/] [mig_7series_0/] [user_design/] [rtl/] [controller/] [mig_7series_v2_3_bank_queue.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              : bank_queue.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
// Bank machine queue controller.
67
//
68
// Bank machines are always associated with a queue.  When the system is
69
// idle, all bank machines are in the idle queue.  As requests are
70
// received, the bank machine at the head of the idle queue accepts
71
// the request, removes itself from the idle queue and places itself
72
// in a queue associated with the rank-bank of the new request.
73
//
74
// If the new request is to an idle rank-bank, a new queue is created
75
// for that rank-bank.  If the rank-bank is not idle, then the new
76
// request is added to the end of the existing rank-bank queue.
77
//
78
// When the head of the idle queue accepts a new request, all other
79
// bank machines move down one in the idle queue.  When the idle queue
80
// is empty, the memory interface deasserts its accept signal.
81
//
82
// When new requests are received, the first step is to classify them
83
// as to whether the request targets an already open rank-bank, and if
84
// so, does the new request also hit on the already open page?  As mentioned
85
// above, a new request places itself in the existing queue for a
86
// rank-bank hit.  If it is also detected that the last entry in the
87
// existing rank-bank queue has the same page, then the current tail
88
// sets a bit telling itself to pass the open row when the column
89
// command is issued.  The "passee" knows its in the head minus one
90
// position and hence takes control of the rank-bank.
91
//
92
// Requests are retired out of order to optimize DRAM array resources.
93
// However it is required that the user cannot "observe" this out of
94
// order processing as a data corruption.  An ordering queue is
95
// used to enforce some ordering rules.  As controlled by a paramter,
96
// there can be no ordering (RELAXED), ordering of writes only (NORM), and
97
// strict (STRICT) ordering whereby input request ordering is
98
// strictly adhered to.
99
//
100
// Note that ordering applies only to column commands.  Row commands
101
// such as activate and precharge are allowed to proceed in any order
102
// with the proviso that within a rank-bank row commands are processed in
103
// the request order.
104
//
105
// When a bank machine accepts a new request, it looks at the ordering
106
// mode.  If no ordering, nothing is done.  If strict ordering, then
107
// it always places itself at the end of the ordering queue.  If "normal"
108
// or write ordering, the row machine places itself in the ordering
109
// queue only if the new request is a write.  The bank state machine
110
// looks at the ordering queue, and will only issue a column
111
// command when it sees itself at the head of the ordering queue.
112
//
113
// When a bank machine has completed its request, it must re-enter the
114
// idle queue.  This is done by setting the idle_r bit, and setting q_entry_r
115
// to the idle count.
116
//
117
// There are several situations where more than one bank machine
118
// will enter the idle queue simultaneously.  If two or more
119
// simply use the idle count to place themselves in the idle queue, multiple
120
// bank machines will end up at the same location in the idle queue, which
121
// is illegal.
122
//
123
// Based on the bank machine instance numbers, a count is made of
124
// the number of bank machines entering idle "below" this instance.  This
125
// number is added to the idle count to compute the location in
126
// idle queue.
127
//
128
// There is also a single bit computed that says there were bank machines
129
// entering the idle queue "above" this instance.  This is used to
130
// compute the tail bit.
131
//
132
// The word "queue" is used frequently to describe the behavior of the
133
// bank_queue block.  In reality, there are no queues in the ordinary sense.
134
// As instantiated in this block, each bank machine has a q_entry_r number.
135
// This number represents the position of the bank machine in its current
136
// queue.  At any given time, a bank machine may be in the idle queue,
137
// one of the dynamic rank-bank queues, or a single entry manitenance queue.
138
// A complete description of which queue a bank machine is currently in is
139
// given by idle_r, its rank-bank, mainteance status and its q_entry_r number.
140
//
141
// DRAM refresh and ZQ have a private single entry queue/channel.  However,
142
// when a refresh request is made, it must be injected into the main queue
143
// properly.  At the time of injection, the refresh rank is compared against
144
// all entryies in the queue.  For those that match, if timing allows, and
145
// they are the tail of the rank-bank queue, then the auto_pre bit is set.
146
// Otherwise precharge is in progress.  This results in a fully precharged
147
// rank.
148
//
149
//  At the time of injection, the refresh channel builds a bit
150
// vector of queue entries that hit on the refresh rank.  Once all
151
// of these entries finish, the refresh is forced in at the row arbiter.
152
//
153
// New requests that come after the refresh request will notice that
154
// a refresh is in progress for their rank and wait for the refresh
155
// to finish before attempting to arbitrate to send an activate.
156
//
157
// Injection of a refresh sets the q_has_rd bit for all queues hitting
158
// on the refresh rank.  This insures a starved write request will not
159
// indefinitely hold off a refresh.
160
//
161
// Periodic reads are required to compare themselves against requests
162
// that are in progress.  Adding a unique compare channel for this
163
// is not worthwhile.  Periodic read requests inhibit the accept
164
// signal and override any new request that might be trying to
165
// enter the queue.
166
//
167
// Once a periodic read has entered the queue it is nearly indistinguishable
168
// from a normal read request.  The req_periodic_rd_r bit is set for
169
// queue entry.  This signal is used to inhibit the rd_data_en signal.
170
 
171
`timescale 1ps/1ps
172
`define BM_SHARED_BV (ID+nBANK_MACHS-1):(ID+1)
173
 
174
module mig_7series_v2_3_bank_queue #
175
  (
176
   parameter TCQ = 100,
177
   parameter BM_CNT_WIDTH             = 2,
178
   parameter nBANK_MACHS              = 4,
179
   parameter ORDERING                 = "NORM",
180
   parameter ID                       = 0
181
  )
182
  (/*AUTOARG*/
183
  // Outputs
184
  head_r, tail_r, idle_ns, idle_r, pass_open_bank_ns,
185
  pass_open_bank_r, auto_pre_r, bm_end, passing_open_bank,
186
  ordered_issued, ordered_r, order_q_zero, rcv_open_bank,
187
  rb_hit_busies_r, q_has_rd, q_has_priority, wait_for_maint_r,
188
  // Inputs
189
  clk, rst, accept_internal_r, use_addr, periodic_rd_ack_r, bm_end_in,
190
  idle_cnt, rb_hit_busy_cnt, accept_req, rb_hit_busy_r, maint_idle,
191
  maint_hit, row_hit_r, pre_wait_r, allow_auto_pre, sending_col,
192
  bank_wait_in_progress, precharge_bm_end, req_wr_r, rd_wr_r,
193
  adv_order_q, order_cnt, rb_hit_busy_ns_in, passing_open_bank_in,
194
  was_wr, maint_req_r, was_priority
195
  );
196
 
197
  localparam ZERO = 0;
198
  localparam ONE = 1;
199
  localparam [BM_CNT_WIDTH-1:0] BM_CNT_ZERO = ZERO[0+:BM_CNT_WIDTH];
200
  localparam [BM_CNT_WIDTH-1:0] BM_CNT_ONE = ONE[0+:BM_CNT_WIDTH];
201
 
202
  input clk;
203
  input rst;
204
 
205
// Decide if this bank machine should accept a new request.
206
  reg idle_r_lcl;
207
  reg head_r_lcl;
208
  input accept_internal_r;
209
  wire bm_ready = idle_r_lcl && head_r_lcl && accept_internal_r;
210
 
211
// Accept request in this bank machine.  Could be maintenance or
212
// regular request.
213
  input use_addr;
214
  input periodic_rd_ack_r;
215
  wire accept_this_bm = bm_ready && (use_addr || periodic_rd_ack_r);
216
 
217
// Multiple machines may enter the idle queue in a single state.
218
// Based on bank machine instance number, compute how many
219
// bank machines with lower instance numbers are entering
220
// the idle queue.
221
 
222
  input [(nBANK_MACHS*2)-1:0] bm_end_in;
223
 
224
  reg [BM_CNT_WIDTH-1:0] idlers_below;
225
  integer i;
226
  always @(/*AS*/bm_end_in) begin
227
    idlers_below = BM_CNT_ZERO;
228
    for (i=0; i<ID; i=i+1)
229
      idlers_below = idlers_below + bm_end_in[i];
230
   end
231
 
232
  reg idlers_above;
233
  always @(/*AS*/bm_end_in) begin
234
    idlers_above = 1'b0;
235
    for (i=ID+1; i<ID+nBANK_MACHS; i=i+1)
236
      idlers_above = idlers_above || bm_end_in[i];
237
  end
238
 
239
`ifdef MC_SVA
240
  bm_end_and_idlers_above: cover property (@(posedge clk)
241
         (~rst && bm_end && idlers_above));
242
  bm_end_and_idlers_below: cover property (@(posedge clk)
243
         (~rst && bm_end && |idlers_below));
244
`endif
245
 
246
// Compute the q_entry number.
247
  input [BM_CNT_WIDTH-1:0] idle_cnt;
248
  input [BM_CNT_WIDTH-1:0] rb_hit_busy_cnt;
249
  input accept_req;
250
  wire bm_end_lcl;
251
  reg adv_queue = 1'b0;
252
 
253
  reg [BM_CNT_WIDTH-1:0] q_entry_r;
254
  reg [BM_CNT_WIDTH-1:0] q_entry_ns;
255
  wire [BM_CNT_WIDTH-1:0] temp;
256
//  always @(/*AS*/accept_req or accept_this_bm or adv_queue
257
//           or bm_end_lcl or idle_cnt or idle_r_lcl or idlers_below
258
//           or q_entry_r or rb_hit_busy_cnt /*or rst*/) begin
259
////    if (rst) q_entry_ns = ID[BM_CNT_WIDTH-1:0];
260
////    else begin
261
//      q_entry_ns = q_entry_r;
262
//      if ((~idle_r_lcl && adv_queue) ||
263
//          (idle_r_lcl && accept_req && ~accept_this_bm))
264
//        q_entry_ns = q_entry_r - BM_CNT_ONE;
265
//      if (accept_this_bm)
266
////        q_entry_ns = rb_hit_busy_cnt - (adv_queue ? BM_CNT_ONE : BM_CNT_ZERO);
267
//        q_entry_ns = adv_queue ? (rb_hit_busy_cnt - BM_CNT_ONE) :  (rb_hit_busy_cnt -BM_CNT_ZERO);
268
//      if (bm_end_lcl) begin
269
//        q_entry_ns = idle_cnt + idlers_below;
270
//        if (accept_req) q_entry_ns = q_entry_ns - BM_CNT_ONE;
271
////      end
272
//    end
273
//  end
274
assign temp = idle_cnt + idlers_below;
275
always @ (*)
276
begin
277
  if (accept_req & bm_end_lcl)
278
    q_entry_ns  = temp - BM_CNT_ONE;
279
  else if (bm_end_lcl)
280
    q_entry_ns = temp;
281
  else if (accept_this_bm)
282
    q_entry_ns = adv_queue ? (rb_hit_busy_cnt - BM_CNT_ONE) :  (rb_hit_busy_cnt -BM_CNT_ZERO);
283
  else if ((!idle_r_lcl & adv_queue) |
284
          (idle_r_lcl & accept_req & !accept_this_bm))
285
    q_entry_ns = q_entry_r - BM_CNT_ONE;
286
  else
287
  q_entry_ns = q_entry_r;
288
end
289
 
290
 
291
  always @(posedge clk)
292
  if (rst)
293
    q_entry_r <= #TCQ ID[BM_CNT_WIDTH-1:0];
294
  else
295
    q_entry_r <= #TCQ q_entry_ns;
296
 
297
// Determine if this entry is the head of its queue.
298
  reg head_ns;
299
  always @(/*AS*/accept_req or accept_this_bm or adv_queue
300
           or bm_end_lcl or head_r_lcl or idle_cnt or idle_r_lcl
301
           or idlers_below or q_entry_r or rb_hit_busy_cnt or rst) begin
302
    if (rst) head_ns = ~|ID[BM_CNT_WIDTH-1:0];
303
    else begin
304
      head_ns = head_r_lcl;
305
      if (accept_this_bm)
306
        head_ns = ~|(rb_hit_busy_cnt - (adv_queue ? BM_CNT_ONE : BM_CNT_ZERO));
307
      if ((~idle_r_lcl && adv_queue) ||
308
           (idle_r_lcl && accept_req && ~accept_this_bm))
309
        head_ns = ~|(q_entry_r - BM_CNT_ONE);
310
      if (bm_end_lcl) begin
311
        head_ns = ~|(idle_cnt - (accept_req ? BM_CNT_ONE : BM_CNT_ZERO)) &&
312
                   ~|idlers_below;
313
      end
314
    end
315
  end
316
  always @(posedge clk) head_r_lcl <= #TCQ head_ns;
317
  output wire head_r;
318
  assign head_r = head_r_lcl;
319
 
320
// Determine if this entry is the tail of its queue.  Note that
321
// an entry can be both head and tail.
322
  input rb_hit_busy_r;
323
  reg tail_r_lcl = 1'b1;
324
  generate
325
    if (nBANK_MACHS > 1) begin : compute_tail
326
      reg tail_ns;
327
      always @(accept_req or accept_this_bm
328
               or bm_end_in or bm_end_lcl or idle_r_lcl
329
               or idlers_above or rb_hit_busy_r or rst or tail_r_lcl) begin
330
        if (rst) tail_ns = (ID == nBANK_MACHS);
331
// The order of the statements below is important in the case where
332
// another bank machine is retiring and this bank machine is accepting.
333
        else begin
334
          tail_ns = tail_r_lcl;
335
          if ((accept_req && rb_hit_busy_r) ||
336
               (|bm_end_in[`BM_SHARED_BV] && idle_r_lcl))
337
            tail_ns = 1'b0;
338
          if (accept_this_bm || (bm_end_lcl && ~idlers_above)) tail_ns = 1'b1;
339
         end
340
       end
341
       always @(posedge clk) tail_r_lcl <= #TCQ tail_ns;
342
    end // if (nBANK_MACHS > 1)
343
  endgenerate
344
  output wire tail_r;
345
  assign tail_r = tail_r_lcl;
346
 
347
  wire clear_req = bm_end_lcl || rst;
348
 
349
// Is this entry in the idle queue?
350
  reg idle_ns_lcl;
351
  always @(/*AS*/accept_this_bm or clear_req or idle_r_lcl) begin
352
    idle_ns_lcl = idle_r_lcl;
353
    if (accept_this_bm) idle_ns_lcl = 1'b0;
354
    if (clear_req) idle_ns_lcl = 1'b1;
355
  end
356
  always @(posedge clk) idle_r_lcl <= #TCQ idle_ns_lcl;
357
  output wire idle_ns;
358
  assign idle_ns = idle_ns_lcl;
359
  output wire idle_r;
360
  assign idle_r = idle_r_lcl;
361
 
362
// Maintenance hitting on this active bank machine is in progress.
363
  input maint_idle;
364
  input maint_hit;
365
  wire maint_hit_this_bm = ~maint_idle && maint_hit;
366
 
367
// Does new request hit on this bank machine while it is able to pass the
368
// open bank?
369
  input row_hit_r;
370
  input pre_wait_r;
371
  wire pass_open_bank_eligible =
372
         tail_r_lcl && rb_hit_busy_r && row_hit_r && ~pre_wait_r;
373
 
374
// Set pass open bank bit, but not if request preceded active maintenance.
375
  reg wait_for_maint_r_lcl;
376
  reg pass_open_bank_r_lcl;
377
  wire pass_open_bank_ns_lcl = ~clear_req &&
378
          (pass_open_bank_r_lcl ||
379
           (accept_req && pass_open_bank_eligible &&
380
             (~maint_hit_this_bm || wait_for_maint_r_lcl)));
381
  always @(posedge clk) pass_open_bank_r_lcl <= #TCQ pass_open_bank_ns_lcl;
382
  output wire pass_open_bank_ns;
383
  assign pass_open_bank_ns = pass_open_bank_ns_lcl;
384
  output wire pass_open_bank_r;
385
  assign pass_open_bank_r = pass_open_bank_r_lcl;
386
 
387
`ifdef MC_SVA
388
  pass_open_bank: cover property (@(posedge clk) (~rst && pass_open_bank_ns));
389
  pass_open_bank_killed_by_maint: cover property (@(posedge clk)
390
     (~rst && accept_req && pass_open_bank_eligible &&
391
       maint_hit_this_bm && ~wait_for_maint_r_lcl));
392
  pass_open_bank_following_maint: cover property (@(posedge clk)
393
     (~rst && accept_req && pass_open_bank_eligible &&
394
        maint_hit_this_bm && wait_for_maint_r_lcl));
395
`endif
396
 
397
// Should the column command be sent with the auto precharge bit set?  This
398
// will happen when it is detected that next request is to a different row,
399
// or the next reqest is the next request is refresh to this rank.
400
  reg auto_pre_r_lcl;
401
  reg auto_pre_ns;
402
  input allow_auto_pre;
403
  always @(/*AS*/accept_req or allow_auto_pre or auto_pre_r_lcl
404
           or clear_req or maint_hit_this_bm or rb_hit_busy_r
405
           or row_hit_r or tail_r_lcl or wait_for_maint_r_lcl) begin
406
    auto_pre_ns = auto_pre_r_lcl;
407
    if (clear_req) auto_pre_ns = 1'b0;
408
    else
409
      if (accept_req && tail_r_lcl && allow_auto_pre && rb_hit_busy_r &&
410
          (~row_hit_r || (maint_hit_this_bm && ~wait_for_maint_r_lcl)))
411
        auto_pre_ns = 1'b1;
412
  end
413
  always @(posedge clk) auto_pre_r_lcl <= #TCQ auto_pre_ns;
414
  output wire auto_pre_r;
415
  assign auto_pre_r = auto_pre_r_lcl;
416
 
417
`ifdef MC_SVA
418
  auto_precharge: cover property (@(posedge clk) (~rst && auto_pre_ns));
419
  maint_triggers_auto_precharge: cover property (@(posedge clk)
420
    (~rst && auto_pre_ns && ~auto_pre_r && row_hit_r));
421
`endif
422
 
423
// Determine when the current request is finished.
424
  input sending_col;
425
  input req_wr_r;
426
  input rd_wr_r;
427
  wire sending_col_not_rmw_rd = sending_col && !(req_wr_r && rd_wr_r);
428
  input bank_wait_in_progress;
429
  input precharge_bm_end;
430
  reg pre_bm_end_r;
431
  wire pre_bm_end_ns = precharge_bm_end ||
432
                       (bank_wait_in_progress && pass_open_bank_ns_lcl);
433
  always @(posedge clk) pre_bm_end_r <= #TCQ pre_bm_end_ns;
434
  assign bm_end_lcl =
435
          pre_bm_end_r || (sending_col_not_rmw_rd && pass_open_bank_r_lcl);
436
  output wire bm_end;
437
  assign bm_end = bm_end_lcl;
438
 
439
// Determine that the open bank should be passed to the successor bank machine.
440
  reg pre_passing_open_bank_r;
441
  wire pre_passing_open_bank_ns =
442
            bank_wait_in_progress && pass_open_bank_ns_lcl;
443
  always @(posedge clk) pre_passing_open_bank_r <= #TCQ
444
                         pre_passing_open_bank_ns;
445
  output wire passing_open_bank;
446
  assign passing_open_bank =
447
  pre_passing_open_bank_r || (sending_col_not_rmw_rd && pass_open_bank_r_lcl);
448
 
449
  reg ordered_ns;
450
  wire set_order_q = ((ORDERING == "STRICT") || ((ORDERING == "NORM") &&
451
                       req_wr_r)) && accept_this_bm;
452
 
453
  wire ordered_issued_lcl =
454
            sending_col_not_rmw_rd && !(req_wr_r && rd_wr_r) &&
455
            ((ORDERING == "STRICT") || ((ORDERING == "NORM") && req_wr_r));
456
  output wire ordered_issued;
457
  assign ordered_issued = ordered_issued_lcl;
458
 
459
  reg ordered_r_lcl;
460
  always @(/*AS*/ordered_issued_lcl or ordered_r_lcl or rst
461
           or set_order_q) begin
462
    if (rst) ordered_ns = 1'b0;
463
    else begin
464
      ordered_ns = ordered_r_lcl;
465
// Should never see accept_this_bm and adv_order_q at the same time.
466
      if (set_order_q) ordered_ns = 1'b1;
467
      if (ordered_issued_lcl) ordered_ns = 1'b0;
468
    end
469
  end
470
  always @(posedge clk) ordered_r_lcl <= #TCQ ordered_ns;
471
  output wire ordered_r;
472
  assign ordered_r = ordered_r_lcl;
473
 
474
// Figure out when to advance the ordering queue.
475
  input adv_order_q;
476
  input [BM_CNT_WIDTH-1:0] order_cnt;
477
  reg [BM_CNT_WIDTH-1:0] order_q_r;
478
  reg [BM_CNT_WIDTH-1:0] order_q_ns;
479
  always @(/*AS*/adv_order_q or order_cnt or order_q_r or rst
480
           or set_order_q) begin
481
    order_q_ns = order_q_r;
482
    if (rst) order_q_ns = BM_CNT_ZERO;
483
    if (set_order_q)
484
      if (adv_order_q) order_q_ns = order_cnt - BM_CNT_ONE;
485
      else order_q_ns = order_cnt;
486
    if (adv_order_q && |order_q_r) order_q_ns = order_q_r - BM_CNT_ONE;
487
  end
488
  always @(posedge clk) order_q_r <= #TCQ order_q_ns;
489
 
490
  output wire order_q_zero;
491
  assign order_q_zero = ~|order_q_r ||
492
                        (adv_order_q && (order_q_r == BM_CNT_ONE)) ||
493
                        ((ORDERING == "NORM") && rd_wr_r);
494
 
495
// Keep track of which other bank machine are ahead of this one in a
496
// rank-bank queue.  This is necessary to know when to advance this bank
497
// machine in the queue, and when to update bank state machine counter upon
498
// passing a bank.
499
  input [(nBANK_MACHS*2)-1:0] rb_hit_busy_ns_in;
500
  reg [(nBANK_MACHS*2)-1:0] rb_hit_busies_r_lcl = {nBANK_MACHS*2{1'b0}};
501
  input [(nBANK_MACHS*2)-1:0] passing_open_bank_in;
502
  output reg rcv_open_bank = 1'b0;
503
 
504
  generate
505
    if (nBANK_MACHS > 1) begin : rb_hit_busies
506
 
507
// The clear_vector resets bits in the rb_hit_busies vector as bank machines
508
// completes requests.  rst also resets all the bits.
509
      wire [nBANK_MACHS-2:0] clear_vector =
510
                ({nBANK_MACHS-1{rst}} | bm_end_in[`BM_SHARED_BV]);
511
 
512
// As this bank machine takes on a new request, capture the vector of
513
// which other bank machines are in the same queue.
514
      wire [`BM_SHARED_BV] rb_hit_busies_ns =
515
                ~clear_vector &
516
                (idle_ns_lcl
517
                   ? rb_hit_busy_ns_in[`BM_SHARED_BV]
518
                   : rb_hit_busies_r_lcl[`BM_SHARED_BV]);
519
      always @(posedge clk) rb_hit_busies_r_lcl[`BM_SHARED_BV] <=
520
                             #TCQ rb_hit_busies_ns;
521
 
522
// Compute when to advance this queue entry based on seeing other bank machines
523
// in the same queue finish.
524
      always @(bm_end_in or rb_hit_busies_r_lcl)
525
        adv_queue =
526
            |(bm_end_in[`BM_SHARED_BV] & rb_hit_busies_r_lcl[`BM_SHARED_BV]);
527
 
528
// Decide when to receive an open bank based on knowing this bank machine is
529
// one entry from the head, and a passing_open_bank hits on the
530
// rb_hit_busies vector.
531
      always @(idle_r_lcl
532
               or passing_open_bank_in or q_entry_r
533
               or rb_hit_busies_r_lcl) rcv_open_bank =
534
    |(rb_hit_busies_r_lcl[`BM_SHARED_BV] & passing_open_bank_in[`BM_SHARED_BV])
535
      && (q_entry_r == BM_CNT_ONE) && ~idle_r_lcl;
536
    end
537
  endgenerate
538
  output wire [nBANK_MACHS*2-1:0] rb_hit_busies_r;
539
  assign rb_hit_busies_r = rb_hit_busies_r_lcl;
540
 
541
 
542
// Keep track if the queue this entry is in has priority content.
543
  input was_wr;
544
  input maint_req_r;
545
  reg q_has_rd_r;
546
  wire q_has_rd_ns = ~clear_req &&
547
              (q_has_rd_r || (accept_req && rb_hit_busy_r && ~was_wr) ||
548
               (maint_req_r && maint_hit && ~idle_r_lcl));
549
  always @(posedge clk) q_has_rd_r <= #TCQ q_has_rd_ns;
550
  output wire q_has_rd;
551
  assign q_has_rd = q_has_rd_r;
552
 
553
  input was_priority;
554
  reg q_has_priority_r;
555
  wire q_has_priority_ns = ~clear_req &&
556
          (q_has_priority_r || (accept_req && rb_hit_busy_r && was_priority));
557
  always @(posedge clk) q_has_priority_r <= #TCQ q_has_priority_ns;
558
  output wire q_has_priority;
559
  assign q_has_priority = q_has_priority_r;
560
 
561
// Figure out if this entry should wait for maintenance to end.
562
  wire wait_for_maint_ns = ~rst && ~maint_idle &&
563
                      (wait_for_maint_r_lcl || (maint_hit && accept_this_bm));
564
  always @(posedge clk) wait_for_maint_r_lcl <= #TCQ wait_for_maint_ns;
565
  output wire wait_for_maint_r;
566
  assign wait_for_maint_r = wait_for_maint_r_lcl;
567
 
568
endmodule // bank_queue

powered by: WebSVN 2.1.0

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