AMC13
Firmwares for the different applications of the AMC13 uTCA board made at Boston University
 All Classes Variables
mig_7series_v1_9_bank_queue.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 : 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 
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