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

Subversion Repositories pcie_ds_dma

[/] [pcie_ds_dma/] [trunk/] [core/] [ds_dma64/] [pcie_src/] [pcie_core64_m1/] [source/] [pcie_blk_ll_arb.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
 
2
//-----------------------------------------------------------------------------
3
//
4
// (c) Copyright 2009-2010 Xilinx, Inc. All rights reserved.
5
//
6
// This file contains confidential and proprietary information
7
// of Xilinx, Inc. and is protected under U.S. and
8
// international copyright and other intellectual property
9
// laws.
10
//
11
// DISCLAIMER
12
// This disclaimer is not a license and does not grant any
13
// rights to the materials distributed herewith. Except as
14
// otherwise provided in a valid license issued to you by
15
// Xilinx, and to the maximum extent permitted by applicable
16
// law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
17
// WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
18
// AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
19
// BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
20
// INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
21
// (2) Xilinx shall not be liable (whether in contract or tort,
22
// including negligence, or under any other theory of
23
// liability) for any loss or damage of any kind or nature
24
// related to, arising under or in connection with these
25
// materials, including for any direct, or any indirect,
26
// special, incidental, or consequential loss or damage
27
// (including loss of data, profits, goodwill, or any type of
28
// loss or damage suffered as a result of any action brought
29
// by a third party) even if such damage or loss was
30
// reasonably foreseeable or Xilinx had been advised of the
31
// possibility of the same.
32
//
33
// CRITICAL APPLICATIONS
34
// Xilinx products are not designed or intended to be fail-
35
// safe, or for use in any application requiring fail-safe
36
// performance, such as life-support or safety devices or
37
// systems, Class III medical devices, nuclear facilities,
38
// applications related to the deployment of airbags, or any
39
// other applications that could lead to death, personal
40
// injury, or severe property or environmental damage
41
// (individually and collectively, "Critical
42
// Applications"). Customer assumes the sole risk and
43
// liability of any use of Xilinx products in Critical
44
// Applications, subject only to applicable laws and
45
// regulations governing limitations on product liability.
46
//
47
// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
48
// PART OF THIS FILE AT ALL TIMES.
49
//
50
//-----------------------------------------------------------------------------
51
// Project    : V5-Block Plus for PCI Express
52
// File       : pcie_blk_ll_arb.v
53
//--------------------------------------------------------------------------------
54
//--------------------------------------------------------------------------------
55
//--
56
//-- Description: Arbitration sub-module of PCIe LL Bridge. This module
57
//--              drives the llkrxchtc/fifo signals in a round-robin scheme.
58
//--         
59
//--
60
//--------------------------------------------------------------------------------
61
 
62
`timescale 1ns/1ns
63
`ifndef TCQ
64
 `define TCQ 1
65
`endif
66
 
67
module pcie_blk_ll_arb
68
#(
69
       parameter C_STREAMING                   = 0,
70
       parameter CPL_STREAMING_PRIORITIZE_P_NP = 0
71
 )
72
 (
73
       // Clock and reset
74
 
75
       input wire         clk,
76
       input wire         rst_n,
77
 
78
       // PCIe Block Rx Ports
79
 
80
       output reg         llk_rx_dst_req_n,
81
       output reg  [2:0]  llk_rx_ch_tc     = 0,
82
       output wire [1:0]  llk_rx_ch_fifo,
83
       output wire        fifo_np_req,
84
       output wire        fifo_pcpl_req,
85
 
86
       input  wire        fifo_np_ok,
87
       input  wire        fifo_pcpl_ok,
88
       input  wire        trn_rnp_ok_n,
89
       input  wire        llk_rx_src_last_req_n,
90
       input  wire [7:0]  llk_rx_ch_posted_available_n,
91
       input  wire [7:0]  llk_rx_ch_non_posted_available_n,
92
       input  wire [7:0]  llk_rx_ch_completion_available_n,
93
       input  wire [15:0] llk_rx_preferred_type,
94
 
95
       output reg         llk_rx_dst_cont_req_n,
96
       input  wire        trn_rcpl_streaming_n,
97
 
98
       input  wire [7:0]  cpl_tlp_cntr,
99
       input  wire        cpl_tlp_cntr_inc
100
);
101
 
102
reg  [7:0] any_queue_available       = 8'b0;
103
reg  [7:0] any_queue_available_int;
104
reg  [7:0] high_mask                 = 8'b0;
105
reg        any_available             = 0;
106
reg        any_available_d           = 0;
107
reg  [2:0] next_tc                   = 3'b0;
108
reg  [2:0] next_tc_high              = 3'b0;
109
reg  [2:0] next_tc_low               = 3'b0;
110
reg  [2:0] next_tc_high_pre          = 3'b0;
111
reg  [2:0] next_tc_low_pre           = 3'b0;
112
reg        next_tc_avail_high        = 0;
113
reg        next_tc_avail_low         = 0;
114
reg        next_tc_avail_high_pre    = 0;
115
reg        next_tc_avail_low_pre     = 0;
116
reg        transaction               = 0;
117
reg        llk_rx_dst_req_n_q1       = 1;
118
reg        llk_rx_dst_req_n_q2       = 1;
119
reg        final_xfer_d              = 0;
120
reg        fifo_pcpl_ok_final        = 1;
121
reg        transaction_first         = 0;
122
reg        transaction_stream        = 0;
123
(* XIL_PAR_PATH = "pcie_ep.LLKRXSRCLASTREQN->SR", XIL_PAR_IP_NAME = "PCIE", syn_keep = "1", keep = "TRUE" *)
124
reg        completion_available      = 0;
125
reg        last_completion           = 1;
126
reg  [7:0] cpl_tlp_rcntr             = 8'h00;
127
reg  [7:0] cpl_tlp_rcntr_p1          = 8'h01;
128
reg  [7:0] cpl_tlp_rcntr_p2          = 8'h02;
129
reg        llk_rx_src_last_req_n_dly = 1;
130
reg        llk_rx_src_last_req_n_q   = 1;
131
reg        current_posted_available_n_d     = 1;
132
reg        current_non_posted_available_n_d = 1;
133
reg        current_completion_available_n_d = 1;
134
reg        trn_rcpl_streaming_n_reg  = 1;
135
reg        next_tc_is_same_rdy       = 0;
136
reg        next_tc_is_same_lock      = 0;
137
reg        transaction_second        = 0;
138
reg        transaction_third         = 0;
139
reg  [1:0] preferred_timer           = 'd3;
140
reg        preferred_vld             = 1;
141
reg  [7:0] preferred_avail_tc;
142
reg        preferred_avail           = 0;
143
reg        posted_avail              = 0;
144
reg  [1:0] llk_rx_ch_fifo_int        = 0;
145
reg        force_streaming           = 0;
146
reg        preferred_avail_chosen    = 0;
147
reg [47:0] transaction_status        = "RESET";
148
reg        pnp_waiting               = 0;
149
reg        force_service_pnp_queues  = 0;
150
 
151
reg  [1:0] preferred_alt             = 2'd0;
152
reg        rnp_rob                   = 0;
153
reg        rnp_rr                    = 0;
154
reg  [1:0] llk_rx_preferred_type_d             = 0;
155
reg        llk_rx_ch_posted_available_n_d      = 0;
156
reg        llk_rx_ch_non_posted_available_n_d  = 0;
157
reg        llk_rx_ch_completion_available_n_d  = 0;
158
 
159
 
160
 
161
 
162
 
163
reg        cpl_avail                 = 0;
164
reg        np_rnp_stall              = 0;
165
 
166
wire       final_xfer;
167
wire       trigger_xfer;
168
wire       transaction_init_cpl;
169
wire       llk_rx_src_last_req_fell = llk_rx_src_last_req_n_q &&
170
                                     !llk_rx_src_last_req_n_dly;
171
wire       fifo_np_ok_1hdr;
172
 
173
integer    i,j,k,m;
174
 
175
 
176
////////////////////////////////////////////////////////////////////////////////
177
// CONTREQ and DSTREQ signaling
178
////////////////////////////////////////////////////////////////////////////////
179
 
180
  always @* begin
181
 
182
    if (!trn_rcpl_streaming_n_reg) begin : dst_stream
183
 
184
    //DSTREQ (request) data so long as:
185
    //1) there is either a new packet available, or a current packet in progress
186
    // -and-
187
    // 2a)for Completions:
188
    //    * this is not the LAST cycle of the final Completion packet
189
    // 2b)for Posted/Non-Posted:
190
    //    * this is not the LAST cycle of the packet
191
    llk_rx_dst_req_n =
192
      !(transaction && (llk_rx_ch_fifo[1]?
193
                        (!last_completion || llk_rx_src_last_req_n_dly):  //Cpl
194
                        (llk_rx_src_last_req_n_dly &&                     //P,NP
195
                         (preferred_avail || posted_avail))));
196
 
197
    //CONTREQ data so long as:
198
    // 1) there is either a new Completion packet available, 
199
    //     or a current Completion packet in progress
200
    // -and-
201
    // 2) this is not the final (or only) packet
202
 
203
    llk_rx_dst_cont_req_n = !(transaction &&
204
                              (llk_rx_ch_fifo[1]?  !last_completion: 1'b0));
205
    /***********/
206
 
207
    end else begin:dst_normal
208
 
209
    //DSTREQ (request) data so long as:
210
    //1) there is either a new packet available, or a current packet in progress
211
    // -and-
212
    // 2) this is not the LAST cycle of the packet
213
    llk_rx_dst_req_n = !(transaction && llk_rx_src_last_req_n_dly &&
214
                         (preferred_avail || posted_avail || cpl_avail));
215
 
216
    //CONTREQ of data not supported in non-streaming mode
217
    llk_rx_dst_cont_req_n = 1'b1;
218
 
219
    end
220
 
221
  end
222
/******************************************************************************/
223
 
224
 
225
// If next_tc is the same as the current one:
226
//---------------------------------------------
227
// preferred_vld        __________|^^^^^^^^ 
228
// next_tc_is_same_lock ^^^^^^^^^^^^^|_____
229
//
230
// AVAILABLE            ^^^^^^^^^^^^^^^^^^^
231
// preferred_avail      ________XXXXXX^^^^^
232
// trigger_xfer         ____|^^^^^^^^|_____
233
// transaction          _____________|^^^^^
234
 
235
////////////////////////////////////////////////////////////////////////////////
236
// Load the output Traffic Class and Fifo registers
237
////////////////////////////////////////////////////////////////////////////////
238
always @(posedge clk) begin
239
  if (!rst_n) begin
240
    llk_rx_ch_tc       <= #`TCQ 0;
241
    llk_rx_ch_fifo_int <= #`TCQ 0;
242
  end else begin
243
    // In Streaming mode; give priority to Completions
244
    if (transaction_init_cpl) begin
245
      llk_rx_ch_tc       <= #`TCQ 0;
246
      llk_rx_ch_fifo_int <= #`TCQ 2'd2;
247
    // Otherwise, let round-robin logic load registers when current
248
    //  xfer ends, or new one is beginning
249
    end else if (trigger_xfer) begin
250
      llk_rx_ch_tc   <= #`TCQ next_tc;
251
      // use preferred_type to select the fifo (P,NP,Cpl) of the next TC
252
      case (next_tc)
253
      3'd0: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[1:0];
254
      3'd1: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[3:2];
255
      3'd2: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[5:4];
256
      3'd3: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[7:6];
257
      3'd4: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[9:8];
258
      3'd5: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[11:10];
259
      3'd6: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[13:12];
260
      3'd7: llk_rx_ch_fifo_int <= #`TCQ llk_rx_preferred_type[15:14];
261
      endcase
262
    end
263
  end
264
end
265
 
266
always @(posedge clk) begin
267
  if (!rst_n) begin
268
    preferred_avail_chosen <= #`TCQ 0;
269
    force_streaming        <= #`TCQ 0;
270
  end else begin
271
    if (transaction_init_cpl)
272
      force_streaming      <= #`TCQ 1;
273
    else if (trigger_xfer)
274
      force_streaming      <= #`TCQ 0;
275
    if (transaction_first && preferred_avail)
276
      preferred_avail_chosen <= #`TCQ 1;
277
    else if (final_xfer)
278
      preferred_avail_chosen <= #`TCQ 0;
279
  end
280
end
281
 
282
assign llk_rx_ch_fifo = (force_streaming ||
283
                         preferred_avail ||
284
                         preferred_avail_chosen) ?
285
                         llk_rx_ch_fifo_int : np_rnp_stall ? preferred_alt : 2'd0;
286
 
287
 
288
 
289
always @* begin
290
    // For each TC, record if there are *any* packets available for reading
291
        // Streaming mode uses different logic for Completions
292
        // It will be assumed that only TC0 will get completions
293
  any_queue_available_int[0] =
294
     (!llk_rx_ch_non_posted_available_n[0] && fifo_np_ok) ||
295
     ((!llk_rx_ch_posted_available_n[0] ||
296
      (!llk_rx_ch_completion_available_n[0] && trn_rcpl_streaming_n_reg)) &&
297
        fifo_pcpl_ok);
298
  for (i=1; i<=7; i=i+1) begin
299
    any_queue_available_int[i] =
300
       (!llk_rx_ch_non_posted_available_n[i] && fifo_np_ok) ||
301
       (!llk_rx_ch_posted_available_n[i]     && fifo_pcpl_ok);
302
  end
303
end
304
 
305
////////////////////////////////////////////////////////////////////////////////
306
// Round-Robin Arbitration logic
307
//   This block will poll for available Posted (P), Non-Posted (NP), and, if in
308
//   non-streaming mode, Completions (C). It will arbitrate, starting with TC=0.
309
//   The logic will take 1 packet if available, then the arb will look at TC=1,
310
//   and so forth for all further TCs. The logic can jump to the next available
311
//   packet in just a few cycles, even if it is a distant TC.
312
////////////////////////////////////////////////////////////////////////////////
313
// synthesis attribute use_clock_enable of next_tc is no;
314
always @(posedge clk) begin
315
  if (!rst_n) begin
316
    next_tc_high                       <= #`TCQ 3'b000;
317
    next_tc_low                        <= #`TCQ 3'b000;
318
    next_tc_avail_high                 <= #`TCQ 0;
319
    next_tc_avail_low                  <= #`TCQ 0;
320
    any_queue_available                <= #`TCQ 8'b00000000;
321
    any_available                      <= #`TCQ 0;
322
    any_available_d                    <= #`TCQ 0;
323
    next_tc                            <= #`TCQ 0;
324
  end else begin
325
    // For each TC, record if there are *any* packets available for reading
326
        // Streaming mode uses different logic for Completions
327
        // It will be assumed that only TC0 will get completions
328
    for (i=0; i<=7; i=i+1) begin
329
      any_queue_available[i]             <= #`TCQ any_queue_available_int[i];
330
    end
331
    // Indicate that a packet exists to be read
332
    any_available                      <= #`TCQ |any_queue_available;
333
    any_available_d                    <= #`TCQ any_available;
334
    // If available, pick the next candidate TC numerically above
335
    //  the current one, and flag that it exists
336
    next_tc_avail_high                 <= #`TCQ next_tc_avail_high_pre;
337
    next_tc_high                       <= #`TCQ next_tc_high_pre;
338
    // If available, pick the next candidate TC numerically below (or equal to)
339
    //  the current one, and flag that it exists
340
    next_tc_avail_low                  <= #`TCQ next_tc_avail_low_pre;
341
    next_tc_low                        <= #`TCQ next_tc_low_pre;
342
    // Indicate if the current packet TC/type has another packet available
343
    current_posted_available_n_d       <= #`TCQ
344
                                          llk_rx_ch_posted_available_n[llk_rx_ch_tc];
345
    current_non_posted_available_n_d   <= #`TCQ
346
                                          llk_rx_ch_non_posted_available_n[llk_rx_ch_tc];
347
    if (!trn_rcpl_streaming_n_reg)
348
      current_completion_available_n_d   <= #`TCQ 0;
349
    else
350
      current_completion_available_n_d   <= #`TCQ
351
                                            llk_rx_ch_completion_available_n[llk_rx_ch_tc];
352
    /////////////////////////////////////////////////////////////////////////
353
    // Determine the next (if any) Traffic Class
354
    /////////////////////////////////////////////////////////////////////////
355
    if (next_tc_avail_high) begin
356
      next_tc              <= #`TCQ next_tc_high;
357
    end else begin
358
      next_tc              <= #`TCQ next_tc_low;
359
    end
360
  end
361
end
362
 
363
 
364
////////////////////////////////////////////////////////////////////////////////
365
// Create a mask of the TCs numerically above the current one
366
////////////////////////////////////////////////////////////////////////////////
367
always @(posedge clk) begin
368
  if (!rst_n)
369
    high_mask <= #`TCQ 8'b00000000;
370
  else begin
371
    for (k=0; k<= 7; k=k+1)
372
      high_mask[k] <= #`TCQ (llk_rx_ch_tc < k);
373
  end
374
end
375
 
376
////////////////////////////////////////////////////////////////////////////////
377
// Combinatorial computation of the next potential Traffic Class
378
// based off a 1-cycle delayed availibility bus
379
////////////////////////////////////////////////////////////////////////////////
380
always @* begin
381
  next_tc_high_pre        = llk_rx_ch_tc;
382
  next_tc_low_pre         = llk_rx_ch_tc;
383
  next_tc_avail_high_pre  = 0;
384
  next_tc_avail_low_pre   = 0;
385
  for (j=7; j>=0; j=j-1)
386
  begin
387
    if (high_mask[j] && any_queue_available[j])
388
    begin
389
      next_tc_high_pre       = j;
390
      next_tc_avail_high_pre = 1;
391
    end
392
    if (any_queue_available[j])
393
    begin
394
      next_tc_low_pre       = j;
395
      next_tc_avail_low_pre = 1;
396
    end
397
  end
398
end
399
 
400
 
401
//The final xfer is when LASTREQ asserts and either REQN is asserting or
402
// it did so the cycle before
403
//assign final_xfer     = llk_rx_src_last_req_fell &&
404
//                        (!llk_rx_dst_req_n || !llk_rx_dst_req_n_q2);
405
assign final_xfer     = !llk_rx_src_last_req_n_dly;
406
// Indicate to the dualfifo that a packet is about to be xfer'd
407
assign fifo_np_req    = transaction_first &&  llk_rx_ch_fifo[0];
408
assign fifo_pcpl_req  = transaction_first && !llk_rx_ch_fifo[0];
409
 
410
assign transaction_init_cpl = (!trn_rcpl_streaming_n_reg && completion_available &&
411
                               (!transaction || (final_xfer && !last_completion)));
412
 
413
assign trigger_xfer   = ((any_available_d || next_tc_is_same_rdy) &&
414
                         (!transaction    || final_xfer));
415
 
416
////////////////////////////////////////////////////////////////////////////////
417
//Indicate a xfer is in progress. A transfer begins if a packet is reported as
418
// available. It ends on LASTREQ (unless it is a Completion in Streaming mode,
419
// in which case the next packet could begin on that cycle, back2back.
420
////////////////////////////////////////////////////////////////////////////////
421
always @(posedge clk)
422
begin
423
  if (!rst_n) begin
424
    transaction        <= #`TCQ 0;
425
    transaction_first  <= #`TCQ 0;
426
    transaction_stream <= #`TCQ 0;
427
    //synthesis translate_off
428
      transaction_status <= #`TCQ "RESET";
429
    //synthesis translate_on
430
  // Streaming mode Completion read has been triggered
431
  end else if (transaction_init_cpl) begin
432
    transaction        <= #`TCQ 1;
433
    transaction_first  <= #`TCQ 1;
434
    transaction_stream <= #`TCQ 1;
435
    //synthesis translate_off
436
      transaction_status <= #`TCQ "INCPL";
437
    //synthesis translate_on
438
  // Abort transaction if it is not actually available
439
  //  dst_req will not actually assert
440
  end else if (transaction_first &&
441
      !(preferred_avail || posted_avail || cpl_avail || transaction_stream)) begin
442
    transaction        <= #`TCQ 0;
443
    transaction_first  <= #`TCQ 0;
444
    transaction_stream <= #`TCQ 0;
445
    //synthesis translate_off
446
      transaction_status <= #`TCQ "ABORT";
447
    //synthesis translate_on
448
  //  If next packet is from the same queue/TC; must temporarily force 
449
  //  to 0 to allow *AVAILABLE/PREFERRED bus to update, to see if there
450
  //  really is another packet
451
  end else if (next_tc_is_same_lock && (final_xfer || !transaction)) begin
452
    transaction        <= #`TCQ 0;
453
    transaction_first  <= #`TCQ 0;
454
    transaction_stream <= #`TCQ 0;
455
    //synthesis translate_off
456
      transaction_status <= #`TCQ "LOCK";
457
    //synthesis translate_on
458
  // Beginning new packet
459
  end else if (trigger_xfer) begin
460
  //end else if (any_available_d && (!transaction || final_xfer)) begin
461
    transaction        <= #`TCQ 1;
462
    transaction_first  <= #`TCQ 1;
463
    transaction_stream <= #`TCQ 0;
464
    //synthesis translate_off
465
      transaction_status <= #`TCQ "TRIG";
466
    //synthesis translate_on
467
  // Ending packet, and no others available
468
  end else if (final_xfer) begin
469
    transaction        <= #`TCQ 0;
470
    transaction_first  <= #`TCQ 0;
471
    transaction_stream <= #`TCQ 0;
472
    //synthesis translate_off
473
      transaction_status <= #`TCQ "LAST";
474
    //synthesis translate_on
475
  // Deassert "first" after first DSTREQ cycle
476
  end else if (!llk_rx_dst_req_n) begin
477
    transaction        <= #`TCQ transaction;
478
    transaction_first  <= #`TCQ 0;
479
    transaction_stream <= #`TCQ transaction_stream;
480
    //synthesis translate_off
481
      transaction_status <= #`TCQ "REQ";
482
    //synthesis translate_on
483
  end
484
    //synthesis translate_off
485
    else begin
486
      transaction_status <= #`TCQ "OFF";
487
    end
488
    //synthesis translate_on
489
end
490
 
491
////////////////////////////////////////////////////////////////////////////////
492
// Set a lockout bit to indicate that the next xfer is the same fifo/tc.
493
//  This is necessary because the Available bus does not update fast enough
494
//  (to indicate it is now empty), and we have to stall a few cycle for
495
//  short packets to see if there is another packet to read.
496
////////////////////////////////////////////////////////////////////////////////
497
 
498
always @(posedge clk)
499
begin
500
  if (!rst_n) begin
501
    next_tc_is_same_rdy  <= #`TCQ 1'b0;
502
    next_tc_is_same_lock <= #`TCQ 1'b0;
503
  end else begin
504
    next_tc_is_same_rdy  <= #`TCQ (next_tc == llk_rx_ch_tc) &&
505
                                  any_queue_available_int[next_tc];
506
    next_tc_is_same_lock <= #`TCQ (next_tc == llk_rx_ch_tc) && !preferred_vld;
507
  end
508
end
509
 
510
always @(posedge clk)
511
begin
512
  if (!rst_n) begin
513
    llk_rx_dst_req_n_q1 <= #`TCQ 1;
514
    llk_rx_dst_req_n_q2 <= #`TCQ 1;
515
    final_xfer_d        <= #`TCQ 0;
516
  end else begin
517
    llk_rx_dst_req_n_q1 <= #`TCQ llk_rx_dst_req_n;
518
    llk_rx_dst_req_n_q2 <= #`TCQ llk_rx_dst_req_n_q1;
519
    final_xfer_d        <= #`TCQ final_xfer;
520
  end
521
end
522
 
523
 
524
////////////////////////////////////////////////////////////////////////////////
525
// Streaming logic only; not used in non-streaming mode
526
////////////////////////////////////////////////////////////////////////////////
527
 
528
////////////////////////////////////////////////////////////////////////////////
529
// Indicate that a Completion is available to be read
530
////////////////////////////////////////////////////////////////////////////////
531
 
532
always @(posedge clk) begin
533
  if (!rst_n) begin
534
    completion_available <= #`TCQ 0;
535
  // If we must service the P/NP queues first
536
  end else if (force_service_pnp_queues && llk_rx_dst_cont_req_n) begin
537
    completion_available <= #`TCQ 0;
538
  // No further completions available beyond the currently-requested one
539
  //    Only using lower 4 bits in comparison for timing; assuming Cpls
540
  //    couldn't be more than 8 apart
541
  end else if (!llk_rx_src_last_req_n?(cpl_tlp_cntr[3:0] == cpl_tlp_rcntr_p1[3:0]):
542
                                      (cpl_tlp_cntr[3:0] == cpl_tlp_rcntr[3:0])) begin
543
    completion_available <= #`TCQ 0;
544
  // If there is a mismatch between read cnt and cpl cnt, and there is room
545
  //  in fifo, assert
546
  //    Only using lower 4 bits in comparison for timing; assuming Cpls
547
  //    couldn't be more than 8 apart
548
  end else if (cpl_tlp_cntr[3:0] != cpl_tlp_rcntr[3:0]) begin
549
    completion_available <= #`TCQ fifo_pcpl_ok_final;
550
  end
551
end
552
 
553
//This logic compels the core to drain P/NP queues has highest priority during
554
//Cpl stream
555
 
556
always @(posedge clk) begin
557
  if (!rst_n) begin
558
    pnp_waiting              <= #`TCQ 0;
559
    force_service_pnp_queues <= #`TCQ 0;
560
  end else begin
561
    pnp_waiting              <= #`TCQ !llk_rx_ch_posted_available_n[0] ||
562
                                      !llk_rx_ch_non_posted_available_n[0];
563
    force_service_pnp_queues <= #`TCQ pnp_waiting && CPL_STREAMING_PRIORITIZE_P_NP;
564
  end
565
end
566
 
567
////////////////////////////////////////////////////////////////////////////////
568
// Indicate if the current Completion is the final one, so we know to deassert
569
//  CONTREQ and DSTREQ appropriatly
570
////////////////////////////////////////////////////////////////////////////////
571
always @(posedge clk) begin
572
  if (!rst_n) begin
573
    last_completion         <= #`TCQ 1;
574
    llk_rx_src_last_req_n_q <= #`TCQ 1;
575
  end else begin
576
    // LASTREQ cycle, to see if forthcoming xfer is the last one, compare to
577
    //  read counter + 2 (b/c read counter hasn't updated yet)
578
    //    Only using lower 4 bits in comparison for timing; assuming Cpls
579
    //    couldn't be more than 8 apart
580
    if ((llk_rx_ch_fifo == 2'd2) && !llk_rx_src_last_req_n)
581
      last_completion         <= #`TCQ (cpl_tlp_cntr[3:0] == cpl_tlp_rcntr_p2[3:0]) ||
582
                                        !fifo_pcpl_ok || force_service_pnp_queues;
583
    // First cycle, to see if forthcoming xfer is the only one, compare to
584
    //  compare to read counter + 1
585
    //    Only using lower 4 bits in comparison for timing; assuming Cpls
586
    //    couldn't be more than 8 apart
587
    else if (transaction_init_cpl)
588
      last_completion         <= #`TCQ (cpl_tlp_cntr[3:0] == cpl_tlp_rcntr_p1[3:0]) ||
589
                                        !fifo_pcpl_ok || force_service_pnp_queues;
590
    llk_rx_src_last_req_n_q <= #`TCQ llk_rx_src_last_req_n;
591
  end
592
end
593
 
594
////////////////////////////////////////////////////////////////////////////////
595
// Indicate if there will be room in the dualfifo for the next packet; dualfifo
596
//  will flag full early, to give a 1-packet warning
597
////////////////////////////////////////////////////////////////////////////////
598
always @(posedge clk) begin
599
  if (!rst_n) begin
600
    fifo_pcpl_ok_final <= #`TCQ 1;
601
  end else begin
602
    if (!fifo_pcpl_ok && !llk_rx_src_last_req_n)
603
      fifo_pcpl_ok_final <= #`TCQ 0;
604
    else if (fifo_pcpl_ok)
605
      fifo_pcpl_ok_final <= #`TCQ 1;
606
  end
607
end
608
 
609
////////////////////////////////////////////////////////////////////////////////
610
// Count how many Completions have been read out so far. A plus1 and plus2
611
//  counter is needed so other logic can anticipate what the count will be.
612
////////////////////////////////////////////////////////////////////////////////
613
always @(posedge clk) begin
614
  if (!rst_n) begin
615
    cpl_tlp_rcntr        <= #`TCQ 8'h00;
616
    cpl_tlp_rcntr_p1     <= #`TCQ 8'h01;
617
    cpl_tlp_rcntr_p2     <= #`TCQ 8'h02;
618
  end else if ((llk_rx_ch_fifo == 2'd2) && !llk_rx_src_last_req_n) begin
619
    cpl_tlp_rcntr        <= #`TCQ cpl_tlp_rcntr    + 1;
620
    cpl_tlp_rcntr_p1     <= #`TCQ cpl_tlp_rcntr_p1 + 1;
621
    cpl_tlp_rcntr_p2     <= #`TCQ cpl_tlp_rcntr_p2 + 1;
622
  end
623
end
624
 
625
always @(posedge clk) begin
626
  if (!rst_n) begin
627
    trn_rcpl_streaming_n_reg <= #`TCQ 1;
628
  //streaming is to be turned off; must wait to complete last contreq completion
629
  end else if (trn_rcpl_streaming_n && !trn_rcpl_streaming_n_reg) begin
630
    trn_rcpl_streaming_n_reg <= #`TCQ !((llk_rx_ch_fifo == 2'd2) && !llk_rx_dst_cont_req_n);
631
  end else begin
632
    trn_rcpl_streaming_n_reg <= #`TCQ trn_rcpl_streaming_n;
633
  end
634
end
635
 
636
// Trigger a timer that counts down when a transaction is detected.
637
//  When the timer reaches 0, the PREFERRED type is valid.  
638
always @(posedge clk) begin
639
  if (!rst_n) begin
640
    preferred_vld      <= #`TCQ 1;
641
    preferred_timer    <= #`TCQ 'd3;
642
    transaction_second <= #`TCQ 0;
643
    transaction_third  <= #`TCQ 0;
644
  end else begin
645
    // Trigger new packet
646
   if (transaction_first && (preferred_avail || posted_avail || cpl_avail || transaction_stream)) begin
647
      preferred_vld      <= #`TCQ 0;
648
      preferred_timer    <= #`TCQ 'd3;
649
      transaction_second <= #`TCQ 1;
650
      transaction_third  <= #`TCQ 0;
651
    end else if (transaction_second) begin
652
      preferred_vld      <= #`TCQ 0;
653
      preferred_timer    <= #`TCQ 'd3;
654
      transaction_second <= #`TCQ 0;
655
      //void this transaction if it happens during a cpl stream
656
      transaction_third  <= #`TCQ transaction && !transaction_stream; //possibly aborted
657
    // Stay in this state until packet is AVAILABLE on the
658
    //  first cycle
659
    end else if (transaction_third && transaction) begin
660
      preferred_vld      <= #`TCQ 0;
661
      transaction_second <= #`TCQ 0;
662
      casex ({llk_rx_ch_fifo,
663
              current_posted_available_n_d,
664
              current_non_posted_available_n_d,
665
              current_completion_available_n_d})
666
      5'b00_0xx: begin
667
          preferred_timer    <= #`TCQ preferred_timer - 1;
668
          transaction_third  <= #`TCQ 0;
669
        end
670
      5'b01_x0x: begin
671
          preferred_timer    <= #`TCQ preferred_timer - 1;
672
          transaction_third  <= #`TCQ 0;
673
        end
674
      5'b1x_xx0: begin
675
          preferred_timer    <= #`TCQ preferred_timer - 1;
676
          transaction_third  <= #`TCQ 0;
677
        end
678
      default: begin
679
          preferred_timer    <= #`TCQ preferred_timer;
680
          transaction_third  <= #`TCQ 1;
681
        end
682
      endcase
683
    // After first cycle, count down until 0
684
    end else if (|preferred_timer) begin
685
      preferred_vld      <= #`TCQ (preferred_timer <= 3'd1);
686
      preferred_timer    <= #`TCQ preferred_timer - 1;
687
      transaction_second <= #`TCQ 0;
688
      transaction_third  <= #`TCQ 0;
689
    end
690
  end
691
end
692
 
693
// Register that the next PREFERRED packet is available
694
always @(posedge clk) begin
695
  if (!rst_n) begin
696
    preferred_avail <= #`TCQ 0;
697
    posted_avail    <= #`TCQ 0;
698
  end else if (trigger_xfer) begin
699
    case (next_tc)
700
    3'd0: preferred_avail <= #`TCQ preferred_avail_tc[0] && preferred_vld;
701
    3'd1: preferred_avail <= #`TCQ preferred_avail_tc[1] && preferred_vld;
702
    3'd2: preferred_avail <= #`TCQ preferred_avail_tc[2] && preferred_vld;
703
    3'd3: preferred_avail <= #`TCQ preferred_avail_tc[3] && preferred_vld;
704
    3'd4: preferred_avail <= #`TCQ preferred_avail_tc[4] && preferred_vld;
705
    3'd5: preferred_avail <= #`TCQ preferred_avail_tc[5] && preferred_vld;
706
    3'd6: preferred_avail <= #`TCQ preferred_avail_tc[6] && preferred_vld;
707
    3'd7: preferred_avail <= #`TCQ preferred_avail_tc[7] && preferred_vld;
708
    endcase
709
    case (next_tc)
710
    3'd0: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[0] && fifo_np_ok_1hdr && fifo_pcpl_ok;
711
    3'd1: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[1] && fifo_np_ok_1hdr && fifo_pcpl_ok;
712
    3'd2: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[2] && fifo_np_ok_1hdr && fifo_pcpl_ok;
713
    3'd3: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[3] && fifo_np_ok_1hdr && fifo_pcpl_ok;
714
    3'd4: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[4] && fifo_np_ok_1hdr && fifo_pcpl_ok;
715
    3'd5: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[5] && fifo_np_ok_1hdr && fifo_pcpl_ok;
716
    3'd6: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[6] && fifo_np_ok_1hdr && fifo_pcpl_ok;
717
    3'd7: posted_avail <= #`TCQ !llk_rx_ch_posted_available_n[7] && fifo_np_ok_1hdr && fifo_pcpl_ok;
718
    endcase
719
 
720
 // It will be assumed that only TC0 will get completions
721
   cpl_avail <= #`TCQ  !llk_rx_ch_completion_available_n[0] && fifo_np_ok_1hdr && fifo_pcpl_ok;
722
 
723
  end
724
end
725
 
726
assign fifo_np_ok_1hdr = (CPL_STREAMING_PRIORITIZE_P_NP ? 1 : !fifo_np_ok);
727
 
728
// Indicate that the PREFERRED packet is also AVAILABLE
729
//   for a given TC
730
always @* begin
731
  casex ({llk_rx_preferred_type[1:0],
732
          llk_rx_ch_posted_available_n[0],
733
          llk_rx_ch_non_posted_available_n[0],
734
          llk_rx_ch_completion_available_n[0]})
735
  5'b00_0xx: preferred_avail_tc[0] = fifo_pcpl_ok;
736
  5'b01_x0x: preferred_avail_tc[0] = fifo_pcpl_ok && fifo_np_ok;
737
  5'b1x_xx0: preferred_avail_tc[0] = fifo_pcpl_ok;
738
  default:   preferred_avail_tc[0] = 0;
739
  endcase
740
  for (m=1; m<8; m=m+1) begin
741
    casex ({llk_rx_preferred_type[m*2],
742
            llk_rx_ch_posted_available_n[m],
743
            llk_rx_ch_non_posted_available_n[m]})
744
    3'b0_0x: preferred_avail_tc[m] = fifo_pcpl_ok;
745
    3'b1_x0: preferred_avail_tc[m] = fifo_pcpl_ok && fifo_np_ok;
746
    default: preferred_avail_tc[m] = 0;
747
    endcase
748
  end
749
end
750
 
751
 
752
// when preferred type is NP and bq full(rnp_ok_n deasserted) and there are P/CPL available 
753
//    to be drained from Hardblock
754
always @(posedge clk) begin
755
   if (!rst_n) begin
756
      llk_rx_preferred_type_d <= #`TCQ 2'b0;
757
      llk_rx_ch_posted_available_n_d            <= #`TCQ 0;
758
      llk_rx_ch_non_posted_available_n_d        <= #`TCQ 0;
759
      llk_rx_ch_completion_available_n_d        <= #`TCQ 0;
760
      preferred_alt <= #`TCQ 0;
761
   end else begin
762
 
763
      if (~llk_rx_src_last_req_n) begin
764
 
765
         case  ({llk_rx_preferred_type_d[1:0],
766
                 llk_rx_ch_posted_available_n_d,
767
                 llk_rx_ch_non_posted_available_n_d,
768
                 llk_rx_ch_completion_available_n_d,
769
         fifo_np_ok})
770
         6'b01_000_0 : preferred_alt <= #`TCQ {rnp_rob, 1'b0};
771
         6'b01_100_0 : preferred_alt <= #`TCQ 2'b10;
772
         6'b01_001_0 : preferred_alt <= #`TCQ 2'b00;
773
         default     : preferred_alt <= #`TCQ 2'd0;
774
         endcase
775
      end
776
 
777
   llk_rx_preferred_type_d            <= #`TCQ llk_rx_preferred_type[1:0];
778
   llk_rx_ch_posted_available_n_d     <= #`TCQ llk_rx_ch_posted_available_n[0];
779
   llk_rx_ch_non_posted_available_n_d <= #`TCQ llk_rx_ch_non_posted_available_n[0];
780
   llk_rx_ch_completion_available_n_d <= #`TCQ llk_rx_ch_completion_available_n[0];
781
 
782
   end
783
end
784
 
785
always @(posedge clk) begin
786
  if (!rst_n) begin
787
    rnp_rob         <= #`TCQ 0;
788
    np_rnp_stall    <= #`TCQ 0;
789
  end else begin
790
 
791
    // round robin mode
792
    if ((llk_rx_preferred_type[1:0] == 2'b01) & ~llk_rx_ch_posted_available_n[0] &
793
       ~llk_rx_ch_non_posted_available_n[0] & ~llk_rx_ch_completion_available_n[0] & ~fifo_np_ok)
794
         rnp_rr <= #`TCQ 1;
795
     else
796
         rnp_rr <= #`TCQ 0;
797
 
798
 
799
      if (rnp_rr & ~llk_rx_src_last_req_n) // round robbin and finished pulling a pkt
800
           rnp_rob <= #`TCQ rnp_rob + 1;
801
 
802
 
803
    //  if PREFERRED_TYPE = NP and bq_full and pkts avail on P or CPL queues
804
    if ((llk_rx_preferred_type[1:0] == 2'b01) &  // NP
805
         ~llk_rx_ch_non_posted_available_n[0] & ~fifo_np_ok & trn_rnp_ok_n &
806
        (~llk_rx_ch_posted_available_n[0] | ~llk_rx_ch_completion_available_n[0]))
807
        np_rnp_stall  <= #`TCQ 1'b1;
808
    else if (~transaction)
809
        np_rnp_stall <= #`TCQ 1'b0;
810
 
811
  end
812
end
813
 
814
 
815
 
816
 
817
 
818
// This is to get rid of glitches in simulation
819
always @(llk_rx_src_last_req_n)
820
  llk_rx_src_last_req_n_dly <= #`TCQ llk_rx_src_last_req_n;
821
 
822
`ifdef SV
823
  //synthesis translate_off
824
  ASSERT_STALL_NP1:        assert property (@(posedge clk)
825
    !fifo_np_ok   |-> ##2 !fifo_np_req   || fifo_np_ok
826
                                        ) else $fatal;
827
  ASSERT_STALL_PCPL1:      assert property (@(posedge clk)
828
    !fifo_pcpl_ok |-> ##2 !fifo_pcpl_req || fifo_pcpl_ok
829
                                        ) else $fatal;
830
  ASSERT_2CYCLE_LLKRXLAST: assert property (@(posedge clk)
831
    !llk_rx_src_last_req_n |-> ##1 llk_rx_src_last_req_n
832
                                        ) else $fatal;
833
  ASSERT_LLKRXREQ_ROSE_WO_LAST: assert property (@(posedge clk)
834
    !llk_rx_dst_req_n ##1 llk_rx_dst_req_n |-> !llk_rx_src_last_req_n
835
                                        ) else $fatal;
836
//synthesis translate_on
837
`else
838
//synthesis translate_off
839
  always @(posedge clk) begin
840
    if (!llk_rx_src_last_req_n_q && !llk_rx_src_last_req_n)
841
       $strobe("FAIL: 2-cycle assertion of Llk Rx Last ");
842
    if (!llk_rx_dst_req_n_q1 && llk_rx_dst_req_n && llk_rx_src_last_req_n)
843
       $strobe("FAIL: Deassertion of Llk Rx DstReq w/o Last");
844
  end
845
//synthesis translate_on
846
`endif
847
 
848
endmodule // pcie_blk_ll_arb

powered by: WebSVN 2.1.0

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