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_tx.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_tx.v
53
//--------------------------------------------------------------------------------
54
//--------------------------------------------------------------------------------
55
/*****************************************************************************
56
 *  Description : PCIe Block LocalLink Tx Bridge - adds a LocalLink interface
57
 *                compatible with the PCIe soft core to the V-5 PCIe Hard
58
 *                Block
59
 *
60
 *  NOTE:  Search for "FIXME" tags for high-priority changes to be made
61
 ****************************************************************************/
62
 
63
`timescale 1ns/1ns
64
`ifndef TCQ
65
 `define TCQ 1
66
`endif
67
 
68
module pcie_blk_ll_tx
69
  //{{{ Module Port declarations
70
  #( parameter TX_CPL_STALL_THRESHOLD   = 6,
71
     parameter TX_DATACREDIT_FIX_EN     = 1,
72
     parameter TX_DATACREDIT_FIX_1DWONLY= 1,
73
     parameter TX_DATACREDIT_FIX_MARGIN = 6,
74
     parameter MPS                      = 0,
75
     parameter LEGACY_EP                = 0
76
  )
77
  (
78
   // Clock and reset
79
   input  wire        clk,
80
   input  wire        rst_n,
81
   // Transaction Link Up
82
   input  wire        trn_lnk_up_n,
83
   // PCIe Block Tx Ports
84
   output wire [63:0] llk_tx_data,
85
   output reg         llk_tx_src_rdy_n = 1'b1,
86
   output wire        llk_tx_src_dsc_n,
87
   output wire        llk_tx_sof_n,
88
   output wire        llk_tx_eof_n,
89
   output wire        llk_tx_sop_n,
90
   output wire        llk_tx_eop_n,
91
   output wire  [1:0] llk_tx_enable_n,
92
   output reg   [2:0] llk_tx_ch_tc = 0,
93
   output reg   [1:0] llk_tx_ch_fifo = 2'b11,
94
   input  wire        llk_tx_dst_rdy_n,
95
   input  wire  [9:0] llk_tx_chan_space,
96
   input  wire  [7:0] llk_tx_ch_posted_ready_n,     // ignored input
97
   input  wire  [7:0] llk_tx_ch_non_posted_ready_n, // ignored input
98
   input  wire  [7:0] llk_tx_ch_completion_ready_n, // ignored input
99
   // LocalLink Tx Ports
100
   input  wire [63:0] trn_td,
101
   input  wire  [7:0] trn_trem_n,
102
   input  wire        trn_tsof_n,
103
   input  wire        trn_teof_n,
104
   input  wire        trn_tsrc_rdy_n,
105
   input  wire        trn_tsrc_dsc_n,
106
   input  wire        trn_terrfwd_n,  // NOTE: this input is ignored
107
(* XIL_PAR_PATH = "pcie_ep.LLKTXDSTRDYN->D", XIL_PAR_IP_NAME = "PCIE", syn_keep = "1", keep = "TRUE" *)
108
   output reg         trn_tdst_rdy_n = 1'b0,
109
   output wire        trn_tdst_dsc_n,
110
   output wire        trn_tbuf_av_cpl,
111
   input  wire  [7:0] tx_ch_credits_consumed,
112
   input  wire [11:0] tx_pd_credits_available,
113
   input  wire [11:0] tx_pd_credits_consumed,
114
   input  wire [11:0] tx_npd_credits_available,
115
   input  wire [11:0] tx_npd_credits_consumed,
116
   input  wire [11:0] tx_cd_credits_available,
117
   input  wire [11:0] tx_cd_credits_consumed,
118
   output wire        clear_cpl_count,
119
   input  wire        pd_credit_limited,
120
   input  wire        npd_credit_limited,
121
   input  wire        cd_credit_limited,
122
   input  wire        trn_pfc_cplh_cl_upd,   //used to cause initialization of CPLD fix Margin
123
   input  wire  [7:0] trn_pfc_cplh_cl,       //CPLD fix Margin value
124
   input  wire        l0_stats_cfg_transmitted
125
   );
126
  //}}}
127
  //{{{ Parameters, regs, wires
128
 
129
  // FIFO encodings
130
  localparam POSTED_CAT     = 2'b00;
131
  localparam NONPOSTED_CAT  = 2'b01;
132
  localparam COMPLETION_CAT = 2'b10;
133
  // Format/Type encoding for message types
134
  localparam MRD            = 7'b0X_00000; // Memory Read
135
  localparam MRDLK          = 7'b0X_00001; // Memory Read Lock
136
  localparam MWR            = 7'b1X_00000; // Memory Write
137
  localparam MSG            = 7'bX1_10XXX; // Message
138
  localparam IORD           = 7'b00_00010; // I/O Read
139
  localparam IOWR           = 7'b10_00010; // I/O Write
140
  localparam CFGRD          = 7'b00_0010X; // Config Read
141
  localparam CFGWR          = 7'b10_0010X; // Config Write
142
  localparam CPL            = 7'bX0_0101X; // Completion
143
 
144
  localparam CHANSPACE_CPLEMPTY = (MPS==0)? 8'h48 : (MPS==1)? 8'h80 : 8'h80;
145
 
146
  // Static outputs
147
  assign trn_tdst_dsc_n    = 1'b1;
148
 
149
  // Signals for pipeline storage. Note that all signals are active-high,
150
  // even though some inputs & outputs are active-low. Also, signals are
151
  // added to the pipeline in later stages (sof_gap for example) that are
152
  // not present in earlier stages.
153
  reg [63:0]       td_q1 = 0;       // Data
154
  reg              sof_q1 = 0;      // Start of frame
155
  reg              eof_q1 = 0;      // End of frame
156
  reg              rem_q1 = 0;      // 1-bit encoding of remainder/enable
157
  reg              dsc_q1 = 0;      // Discontinue
158
  reg              vld_q1 = 0;      // Valid
159
(* XIL_PAR_PATH = "pcie_ep.LLKTXDSTRDYN->D", XIL_PAR_IP_NAME = "PCIE", syn_keep = "1", keep = "TRUE" *)
160
  reg [63:0]       td_q2 = 0;
161
(* XIL_PAR_PATH = "pcie_ep.LLKTXDSTRDYN->CE", XIL_PAR_IP_NAME = "PCIE", syn_keep = "1", keep = "TRUE" *)
162
  reg [5:0]        td_q2_credits = 0; //assume 512byte MPS; 512by*(1dw/4by)*(1cr/4dw)=32 (6 bits needed)
163
  reg              td_q2_credits_prev = 0;
164
  reg              td_q2_posted  = 0;
165
  reg              td_q2_iowr    = 0;
166
  reg              td_q2_cpl     = 0;
167
  reg              sof_q2_reg    = 0;
168
  wire             sofpd_q2_rose;
169
  wire             sofnpd_q2_rose;
170
  wire             sofcpl_q2_rose;
171
  reg              pd_q1_reg     = 0;
172
  reg              npd_q1_reg    = 0;
173
  reg              cpl_q1_reg    = 0;
174
  reg              sof_q2 = 0;
175
  reg              eof_q2 = 0;
176
  reg              rem_q2 = 0;
177
  reg              dsc_q2 = 0;
178
  reg              vld_q2 = 0;
179
  reg              sof_gap_q2 = 0;  // Insert gap before SOF
180
                                    //   (due to change of tc and/or fifo)
181
  reg [1:0]        fifo_q2 = 0;     // FIFO (Posted, Non-posted, or Completion)
182
  reg [2:0]        tc_q2 = 0;       // Traffic class
183
  reg [63:0]       td_q3 = 0;
184
  reg              sof_q3 = 0;
185
  reg              eof_q3 = 0;
186
  reg              rem_q3 = 0;
187
  reg              dsc_q3 = 0;
188
  reg              vld_q3 = 0;
189
  reg              sof_gap_q3 = 0;
190
(* XIL_PAR_PATH = "pcie_ep.LLKTXDSTRDYN->CE", XIL_PAR_IP_NAME = "PCIE", syn_keep = "1", keep = "TRUE" *)
191
  reg [1:0]        fifo_q3 = 0;
192
  reg [2:0]        tc_q3 = 0;
193
  // FIFO and TC of previous packet - used to determine whether to insert a
194
  // gap between EOF and SOF
195
  reg [1:0]        fifo_last = 0;
196
  reg [2:0]        tc_last = 0;
197
 
198
  //(* keep = "true" *) reg              shift_pipe;      // Move data through pipeline
199
  wire             shift_pipe;
200
  wire             only_eof;        // Asserted to flush pipeline at EOF
201
 
202
  reg              sof_gap_q3_and_block = 1;
203
  reg              block_sof = 1;   // Asserted to indicate when an SOF with
204
                                    // a new TC or FIFO should be held off
205
  reg [2:0]        block_cnt = 0;   // Control changing of TC/FIFO outputs
206
 
207
  // Signals comprising the shunt buffer used to decouple the trn_tdst_rdy_n
208
  // output from the llk_tx_dst_rdy_n input
209
  reg [63:0]       td_buf;
210
  reg              sof_buf;
211
  reg              eof_buf;
212
  reg              rem_buf;
213
  reg              dsc_buf;
214
  reg              vld_buf = 1'b0;  // Shunt buffer contents valid
215
  wire             buf_divert;      // Current cycle to be stored in shunt buf
216
  wire             buf_rd;          // Xfer shunt buffer to pipeline this cycle
217
  reg  [ 4:0]      cpl_in_count;
218
  wire  [4:0]      cpls_buffered;
219
  reg              llk_tlp_halt;
220
  reg              llk_tx_src_rdy_n_int;
221
  reg  [11:0]      user_pd_data_credits_in    = 0;
222
  reg  [11:0]      user_npd_data_credits_in   = 0;
223
  reg  [11:0]      user_cd_data_credits_in    = 0;
224
  reg  [11:0]      all_cd_data_credits_in    = 0;
225
  reg  [11:0]      l0_stats_cfg_transmitted_cnt=0;
226
 
227
  reg  [11:0]      user_cd_data_credits_in_minus_trn_pfc_cplh_cl_plus1    = 0;
228
 
229
  reg              pd_credits_near_gte_far    = 0;
230
  reg              npd_credits_near_gte_far   = 0;
231
  reg              llk_cpl_second_cycle       = 0;
232
  reg              llk_tx_ch_fifo_d           = 2'b11;
233
  reg              q2_cpl_second_cycle        = 0;
234
  wire [11:0]      near_end_pd_credits_buffered;
235
  wire [11:0]      near_end_npd_credits_buffered;
236
  wire [11:0]      near_end_cd_credits_buffered;
237
  reg              near_end_cd_credits_buffered_11_d;
238
  wire             packet_in_progress;
239
  reg              packet_in_progress_reg     = 0;
240
  reg              len_eq1_q2                 = 0;
241
  reg              llk_tx_chan_space_cpl_empty= 0;
242
  reg              eof_q3_only = 0;
243
  reg              eof_q2_only = 0;
244
  reg              eof_q1_or_eof_q2_only = 0;
245
  reg              tc_fifo_change = 1'b0;
246
  reg              block_fifo     = 1'b1;
247
 
248
  reg  [11:0]      cd_space_remaining_int     = 0;
249
  reg              cd_space_remaining_int_zero= 0;
250
  reg   [8:0]      trn_pfc_cplh_cl_plus1      = 9;
251
  reg              trn_pfc_cplh_cl_upd_d1     = 0;
252
  reg              trn_pfc_cplh_cl_upd_d2     = 0;
253
  //}}}
254
 
255
  //{{{ Shunt Buffer
256
  // Input shunt buffer - absorb one cycle of data to decouple
257
  // trn_tdst_rdy_n from other signals (and therefore make it a
258
  // registered output)
259
 
260
  // vld_buf has to be set and cleared every cycle something changes
261
  always @(posedge clk) begin
262
    if (!rst_n) begin
263
      vld_buf         <= #`TCQ 1'b0;
264
    end else begin
265
      if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && buf_divert) begin
266
        vld_buf       <= #`TCQ 1'b1;
267
      end else if (buf_rd) begin
268
        vld_buf       <= #`TCQ 1'b0;
269
      end
270
    end
271
  end
272
 
273
  // All the rest of the data & control signals only need to be changed
274
  // when new data is available since they're masked with vld_buf
275
  always @(posedge clk) begin
276
    if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n) begin
277
      td_buf        <= #`TCQ trn_td;
278
      sof_buf       <= #`TCQ !trn_tsof_n;
279
      eof_buf       <= #`TCQ !trn_teof_n;
280
      rem_buf       <= #`TCQ !trn_trem_n[0];
281
      dsc_buf       <= #`TCQ !trn_tsrc_dsc_n;
282
    end
283
  end
284
 
285
  // Control when the shunt buffer is written and read
286
  //   Writes go to the shunt buffer when the first pipeline stage is full
287
  //   and not emptying
288
  // attribute fast of vld_q1 is "true";
289
  assign buf_divert = vld_q1 && !shift_pipe;
290
  //   The shunt buffer gets read when the pipeline is first shifted after
291
  //   the shuny buffer is filled
292
  // attribute fast of vld_buf is "true";
293
  assign buf_rd     = vld_buf && shift_pipe;
294
 
295
  // Generate trn_tdst_rdy output. It is always asserted unless the shunt
296
  // buffer is full or going full. When the shunt buffer goes full, input
297
  // is cut off until it goes empty, since the buffer can only absorb a
298
  // single cycle of data.
299
  always @(posedge clk) begin
300
    if (!rst_n) begin
301
      trn_tdst_rdy_n  <= #`TCQ 1'b0;
302
    end else begin
303
      trn_tdst_rdy_n  <= #`TCQ !((!vld_buf &&
304
      //                             !(buf_divert && !trn_tdst_rdy_n)) ||
305
      // fix for CR472508-add additional qualifier
306
                  !(buf_divert && !trn_tdst_rdy_n && !trn_tsrc_rdy_n)) ||
307
                                 buf_rd);
308
    end
309
  end
310
  //}}}
311
 
312
  //{{{ Stage 1
313
  // Data & control pipeline, first stage. First stage can receive data
314
  // from either the user or the shunt buffer.
315
 
316
  always @(posedge clk) begin
317
    // Only SOF, and vld are reset - to allow inferring of SRL16s
318
    if (!rst_n) begin
319
      vld_q1       <= #`TCQ 1'b0;
320
    end else begin
321
      vld_q1   <= #`TCQ (((!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert) || buf_rd) ||
322
                       (vld_q1 && !shift_pipe));
323
    end
324
    if (!rst_n) begin
325
      sof_q1  <= #`TCQ 1'b0;
326
    end else if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert) begin
327
      sof_q1  <= #`TCQ !trn_tsof_n;
328
    end else if (buf_rd) begin
329
      sof_q1  <= #`TCQ sof_buf;
330
    //end else if (shift_pipe) begin
331
    //  sof_q1  <= #`TCQ 1'b0; // SOF implies vld
332
    end else begin
333
      sof_q1  <= #`TCQ (!shift_pipe && sof_q1);
334
    end
335
    if (!rst_n) begin
336
      eof_q1  <= #`TCQ 0;
337
      dsc_q1  <= #`TCQ 0;
338
    end else if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert) begin
339
      eof_q1  <= #`TCQ !trn_teof_n;
340
      dsc_q1  <= #`TCQ !trn_tsrc_dsc_n;
341
    end else if (buf_rd) begin
342
      eof_q1  <= #`TCQ eof_buf;
343
      dsc_q1  <= #`TCQ dsc_buf;
344
    end
345
  end
346
 
347
  always @(posedge clk) begin
348
    //If user data available, buffer empty, and either pipe isn't stalled OR stage 1 isn't valid,
349
    // grab user data  (note: tdst_rdy won't assert if buffer is full)
350
    if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert) begin // !buf_divert = shift_pipe || !vld_q1
351
      td_q1   <= #`TCQ trn_td;
352
      rem_q1  <= #`TCQ !trn_trem_n[0];
353
    //If pipe isn't stalled and buffer is valid, pull from buffer
354
    //end else if (buf_rd) begin       // buf_rd = shift_pipe && vld_buf
355
    end else if (shift_pipe) begin       // buf_rd = shift_pipe && vld_buf
356
      td_q1   <= #`TCQ td_buf;
357
      rem_q1  <= #`TCQ rem_buf;
358
    end
359
  end
360
  //}}}
361
 
362
  //{{{ Stages 2 and 3
363
  // 2nd & 3rd pipeline stages - note that each stage must remain full
364
  // in order to correctly generate EOP. Once an EOF is received, the
365
  // pipeline can be flushed unless an SOF is received. This allows a
366
  // single packet to pass all the way through the pipeline without being
367
  // "pushed" by another packet.
368
 
369
  always @(posedge clk) begin
370
    // Only SOF and vld are reset - to allow inferring of SRL16s on other
371
    // signals
372
    if (!rst_n) begin
373
      sof_q2     <= #`TCQ 1'b0;
374
      vld_q2     <= #`TCQ 1'b0;
375
      len_eq1_q2 <= #`TCQ 1'b0;
376
      sof_q3     <= #`TCQ 1'b0;
377
      eof_q3     <= #`TCQ 1'b0;
378
      vld_q3     <= #`TCQ 1'b0;
379
    end else begin
380
      if (shift_pipe) begin
381
        // Second stage
382
        sof_q2     <= #`TCQ sof_q1;
383
        vld_q2     <= #`TCQ vld_q1;
384
        if (sof_q1) len_eq1_q2 <= #`TCQ (td_q1[41:32] == 10'h001) && !(!td_q1[62] && td_q1[60:57] != 4'b0000);
385
        // Third stage - this stage is also the output data
386
        sof_q3     <= #`TCQ sof_q2;
387
        eof_q3     <= #`TCQ eof_q2 && vld_q2; // Need EOF to be gated with vld
388
                                              // for gapping below
389
        vld_q3     <= #`TCQ vld_q2;
390
      end
391
    end
392
  end
393
 
394
  always @(posedge clk) begin
395
    if (!rst_n) begin
396
      td_q2      <= #`TCQ 0;
397
      td_q2_credits <= #`TCQ 'h0;
398
      td_q2_posted  <= #`TCQ 0;
399
      td_q2_iowr    <= #`TCQ 0;
400
      td_q2_cpl     <= #`TCQ 0;
401
      pd_q1_reg     <= #`TCQ 0;
402
      npd_q1_reg    <= #`TCQ 0;
403
      cpl_q1_reg    <= #`TCQ 0;
404
      eof_q2     <= #`TCQ 0;
405
      rem_q2     <= #`TCQ 0;
406
      dsc_q2     <= #`TCQ 0;
407
    end else if (shift_pipe) begin
408
      // Second stage
409
      td_q2      <= #`TCQ td_q1;
410
      if (sof_q1)
411
        td_q2_credits <= #`TCQ (td_q1[39:34] + (|td_q1[33:32])); //assume MPS<=512
412
      td_q2_posted  <= #`TCQ (td_q1[62:57] == 'b10_0000) || (td_q1[62:57] == 'b11_0000) || (td_q1[62:59] == 'b11_10);
413
      td_q2_iowr    <= #`TCQ (td_q1[62:57] == 'b10_0001);
414
      td_q2_cpl     <= #`TCQ (td_q1[62:57] == 'b10_0101);
415
      pd_q1_reg     <= #`TCQ (td_q1[62:57] == 'b100_000) || (td_q1[62:57] == 'b110_000) || (td_q1[62:59] == 'b111_0);
416
      npd_q1_reg    <= #`TCQ (td_q1[62:57] == 'b10_0001);
417
      cpl_q1_reg    <= #`TCQ (td_q1[62:57] == 'b10_0101);
418
      eof_q2     <= #`TCQ eof_q1;
419
      rem_q2     <= #`TCQ rem_q1 || !eof_q1; // Mask off REM when not EOF
420
      dsc_q2     <= #`TCQ dsc_q1;
421
    end
422
  end
423
 
424
  always @(posedge clk) begin
425
    if (!rst_n) begin
426
      sof_q2_reg    <= #`TCQ 0;
427
    end else begin
428
      sof_q2_reg    <= #`TCQ sof_q2;
429
    end
430
  end
431
 
432
  assign sofpd_q2_rose  = (sof_q2 && !sof_q2_reg && pd_q1_reg);
433
  assign sofnpd_q2_rose = (sof_q2 && !sof_q2_reg && npd_q1_reg);
434
  assign sofcpl_q2_rose = (sof_q2 && !sof_q2_reg && cpl_q1_reg);
435
 
436
  always @(posedge clk) begin
437
    if (!rst_n) begin
438
      td_q3      <= #`TCQ 0;
439
      rem_q3     <= #`TCQ 0;
440
      dsc_q3     <= #`TCQ 0;
441
      tc_q3      <= #`TCQ 0;
442
      fifo_q3    <= #`TCQ 0;
443
    end else if (shift_pipe) begin
444
      // Third stage - this stage is also the output data
445
      td_q3      <= #`TCQ td_q2;
446
      rem_q3     <= #`TCQ rem_q2;
447
      dsc_q3     <= #`TCQ dsc_q2;
448
      // TC and FIFO only change at SOF
449
      if (sof_q2) begin
450
        tc_q3    <= #`TCQ tc_q2;
451
        fifo_q3  <= #`TCQ fifo_q2;
452
      end
453
    end
454
  end
455
 
456
  // Calculate and latch "FIFO" (Posted, Non-posted, or Completion) and TC
457
  // Calculated from first stage and valid in parallel with sof_q2
458
  always @(posedge clk) begin
459
    // No reset neccesary
460
 
461
    if (sof_q1 && shift_pipe) begin
462
      casex (td_q1[62:56])
463
        // Posted
464
        MWR,    // Memory Write
465
        MSG:    // Message
466
          fifo_q2 <= #`TCQ POSTED_CAT;
467
        // Non-Posted
468
        MRD,    // Memory Read
469
        MRDLK,  // Memory Read Lock
470
        IORD,   // I/O Read
471
        IOWR,   // I/O Write
472
        CFGRD,  // Config Read
473
        CFGWR:  // Config Write
474
          fifo_q2 <= #`TCQ NONPOSTED_CAT;
475
        // Completion
476
        CPL:    // Completion
477
          fifo_q2 <= #`TCQ COMPLETION_CAT;
478
        // Frame should _always_ be one of the above, so this is just
479
        // here to ensure the synthesizer doesn't do anything weird
480
        default:
481
          fifo_q2 <= #`TCQ POSTED_CAT;
482
      endcase
483
      tc_q2  <= #`TCQ td_q1[54:52];
484
    end
485
  end
486
  //}}}
487
 
488
  // {{{ TC/FIFO Outputs; Enforce 2-cycle FIFO Change
489
  // Generate TC and FIFO output, as well as the block_sof signal. This
490
  // prevents changing of TC/FIFO for 2 cycles after EOF and asserting of
491
  // a valid SOF beat for one cycle after changing of TC/FIFO.
492
  // This does not affect SOF when TC/FIFO doesn't change.
493
  //
494
  // FIXME comment better
495
  // Requirements:
496
  //   1) Hold TC/FIFO steady for two cycles WITH DST_RDY ASSERTED after EOF.
497
  //   2) Don't assert SOF for one cycle after changing TC/FIFO.
498
  //
499
  //   #1 means asserting block_sof for (at least) two cycles after valid
500
  //   EOF output.
501
  //   #2 means continuing to assert block_sof until
502
  //      a) a valid (non tc/fifo change) sof is transmitted
503
  //      b) one cycle after tc/fifo changes
504
 
505
  // synthesis attribute use_clock_enable of block_cnt is no;
506
  // attribute fast of eof_q3 is "true";
507
 
508
  // Generate sof_gap signal. sof_gap directs the output logic to delay
509
  // changing TC/FIFO outputs and starting a new packet when either TC or
510
  // FIFO changes.
511
  always @(posedge clk) begin
512
    if (!rst_n) begin
513
      sof_gap_q3    <= #`TCQ 1'b0;
514
      fifo_last     <= #`TCQ 2'b00;
515
      tc_last       <= #`TCQ 0;
516
    end else if (sof_q2 && shift_pipe) begin // sof_q2 implies vld_q2
517
      // If FIFO or TC has changed, assert sof_gap
518
      if ((tc_q2 != tc_last) || (fifo_q2 != fifo_last)) begin
519
        sof_gap_q3  <= #`TCQ 1'b1;
520
      end else begin
521
        sof_gap_q3  <= #`TCQ 1'b0;
522
      end
523
      // Latch current TC & FIFO at SOF
524
      fifo_last     <= #`TCQ fifo_q2;
525
      tc_last       <= #`TCQ tc_q2;
526
    end else if (vld_q2 && shift_pipe) begin
527
      // Sof_gap is only asserted with SOF
528
      sof_gap_q3    <= #`TCQ 1'b0;
529
    end
530
  end
531
 
532
  always @(posedge clk) begin
533
    if (!rst_n) begin
534
      block_sof          <= #`TCQ 1'b1;
535
    end else begin
536
      if (tc_fifo_change) begin
537
        block_sof        <= #`TCQ 1'b0;
538
      end else if (sof_q2) begin
539
        block_sof        <= #`TCQ 1'b1;
540
      end
541
    end
542
  end
543
 
544
  always @(posedge clk) begin
545
    if (!rst_n)
546
      sof_gap_q3_and_block  <= #`TCQ 1'b0;
547
    else begin
548
      if      (tc_fifo_change)
549
        sof_gap_q3_and_block  <= #`TCQ 1'b0;
550
      else if (  sof_q2 && shift_pipe )
551
        sof_gap_q3_and_block  <= #`TCQ ((tc_q2 != tc_last) || (fifo_q2 != fifo_last)) && (block_sof || sof_q2);
552
      else if (  vld_q2 && shift_pipe )
553
        sof_gap_q3_and_block  <= #`TCQ 1'b0;
554
      else
555
        sof_gap_q3_and_block  <= #`TCQ sof_gap_q3 && (block_sof || sof_q2);
556
    end
557
  end
558
 
559
  always @(posedge clk) begin
560
    if (!rst_n) begin
561
      block_cnt          <= #`TCQ 0;
562
      block_fifo         <= #`TCQ 1'b0;
563
      tc_fifo_change     <= #`TCQ 1'b0;
564
      llk_tx_ch_tc       <= #`TCQ 0;
565
      llk_tx_ch_fifo     <= #`TCQ 2'b11;
566
      llk_tx_ch_fifo_d   <= #`TCQ 2'b11;
567
    end else begin
568
      if (!llk_tx_dst_rdy_n && !llk_tlp_halt) begin
569
        block_cnt[0]     <= #`TCQ !llk_tx_eof_n && !llk_tx_src_rdy_n_int;
570
      end
571
      if (!llk_tx_dst_rdy_n && !llk_tlp_halt) begin
572
        block_cnt[2:1]   <= #`TCQ block_cnt[1:0];
573
      end
574
      if (eof_q3) begin
575
        block_fifo       <= #`TCQ 1'b1;
576
      end else if (block_cnt[1] && !llk_tx_dst_rdy_n && !llk_tlp_halt) begin
577
        block_fifo       <= #`TCQ 1'b0;
578
      end
579
      if (!block_fifo &&
580
           (llk_tx_ch_tc != tc_q3 || llk_tx_ch_fifo != fifo_q3)) begin
581
        llk_tx_ch_tc     <= #`TCQ tc_q3;
582
        llk_tx_ch_fifo   <= #`TCQ fifo_q3;
583
        tc_fifo_change   <= #`TCQ 1'b1;
584
      end else begin
585
        tc_fifo_change   <= #`TCQ 1'b0;
586
      end
587
      llk_tx_ch_fifo_d   <= #`TCQ llk_tx_ch_fifo;
588
    end
589
  end
590
  //}}}
591
 
592
  //{{{ LLK TX SRC RDY Logic
593
  // Generate src_rdy to the PCIe block
594
  always @* begin
595
      llk_tx_src_rdy_n_int <= sof_gap_q3_and_block || !(vld_q3 && (only_eof || !trn_tsrc_rdy_n || vld_buf));
596
  end
597
  always @* begin
598
      llk_tx_src_rdy_n <= sof_gap_q3_and_block || llk_tlp_halt || !(vld_q3 && (only_eof || !trn_tsrc_rdy_n || vld_buf));
599
  end
600
 
601
  // only_eof indicates when the end of a packet is in the pipeline and
602
  // can be flushed. Flushing is allowed when no SOF follows the EOF.
603
  // NOTE: It would be a -very- good idea to make this the output of a
604
  //        register, to improve timing, if practical.
605
  assign   only_eof = eof_q1_or_eof_q2_only   ||   eof_q3_only;
606
  //}}}
607
 
608
  //{{{ Shift Pipe Logic
609
  // Shift pipeline when:
610
  // 1) Data is read out. This can only happen if:
611
  //    A) There is new data available to be shifted into the pipeline -or-
612
  //    B) There is an EOF at the beginning of the pipeline (*)
613
  // -or-
614
  // 2) There's an EOF at the beginning of the pipeline and the end of the
615
  //    pipeline doesn't contain valid data (*)
616
  // -or-
617
  // 3) New data is available to be written into the pipeline and the
618
  //    end of the pipeline doesn't contain valid data
619
  //
620
  // (*) NOTE - this is to ensure that a single packet (or the end of a
621
  //            packet) can make it all the way to the output even if there
622
  //            isn't new data "pushing" it through.
623
  //
624
 
625
 
626
  //{{{ Old shift pipe logic
627
  //synthesis translate_off
628
  // Keep this around for Assertion comparison
629
 
630
  wire shift_pipe_old = (!llk_tx_src_rdy_n_int && !llk_tx_dst_rdy_n && !llk_tlp_halt) ||
631
                        ((!trn_tsrc_rdy_n || vld_buf) && !vld_q3) ||
632
                        (!vld_q3 && (eof_q1   ||   (eof_q2 && !sof_q1)   ||   (eof_q3 && !sof_q2 && !sof_q1)));
633
  //synthesis translate_on
634
  //}}}
635
 
636
 
637
 
638
  wire   shift_pipe_input0 = (vld_buf || eof_q1 || eof_q2_only || eof_q3_only);
639
 
640
  LUT6 #(.INIT(64'b00100011_00100011_00100011_00100011_00100011_00100011_00100011_11111111))
641
  shift_pipe1                 (.O (shift_pipe),
642
                               .I5(llk_tx_dst_rdy_n),
643
                               .I4(llk_tlp_halt),
644
                               .I3(llk_tx_src_rdy_n_int),
645
                               .I2(trn_tsrc_rdy_n),
646
                               .I1(vld_q3),
647
                               .I0(shift_pipe_input0));
648
 
649
 
650
  always @(posedge clk) begin
651
    if (!rst_n) begin
652
      eof_q3_only           <= #`TCQ 0;
653
      eof_q2_only           <= #`TCQ 0;
654
      eof_q1_or_eof_q2_only <= #`TCQ 0;
655
    end else begin
656
      if      (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert &&  shift_pipe)
657
        eof_q3_only <= #`TCQ (eof_q2 && vld_q2) && !sof_q1  && trn_tsof_n;
658
      else if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert && !shift_pipe)
659
        eof_q3_only <= #`TCQ (eof_q3)           && !sof_q2  && trn_tsof_n;
660
      else if (buf_rd &&  shift_pipe)
661
        eof_q3_only <= #`TCQ (eof_q2 && vld_q2) && !sof_q1  && !sof_buf;
662
      else if (buf_rd && !shift_pipe)
663
        eof_q3_only <= #`TCQ (eof_q3)           && !sof_q2  && !sof_buf;
664
      else if (shift_pipe)
665
        eof_q3_only <= #`TCQ (eof_q2 && vld_q2) && !sof_q1;
666
      if      (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert &&  shift_pipe)
667
        eof_q2_only <= #`TCQ eof_q1 && trn_tsof_n;
668
      else if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert && !shift_pipe)
669
        eof_q2_only <= #`TCQ eof_q2 && trn_tsof_n;
670
      else if (buf_rd &&  shift_pipe)
671
        eof_q2_only <= #`TCQ eof_q1 && !sof_buf;
672
      else if (buf_rd && !shift_pipe)
673
        eof_q2_only <= #`TCQ eof_q2 && !sof_buf;
674
      else if (shift_pipe)
675
        eof_q2_only <= #`TCQ eof_q1;
676
      //eof_q2  <= #`TCQ eof_q1;
677
 
678
      if      (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert &&  shift_pipe)
679
        eof_q1_or_eof_q2_only <= #`TCQ (eof_q1 && trn_tsof_n) || !trn_teof_n;
680
      else if (!trn_tdst_rdy_n && !trn_tsrc_rdy_n && !buf_divert && !shift_pipe)
681
        eof_q1_or_eof_q2_only <= #`TCQ (eof_q2 && trn_tsof_n) || !trn_teof_n;
682
      else if (buf_rd &&  shift_pipe)
683
        eof_q1_or_eof_q2_only <= #`TCQ (eof_q1 && !sof_buf) || eof_buf;
684
      else if (buf_rd && !shift_pipe)
685
        eof_q1_or_eof_q2_only <= #`TCQ (eof_q2 && !sof_buf) || eof_buf;
686
      else if (shift_pipe)
687
        eof_q1_or_eof_q2_only <= #`TCQ eof_q1;
688
      else
689
        eof_q1_or_eof_q2_only <= #`TCQ eof_q2_only || eof_q1;
690
    end
691
  end
692
  //}}}
693
 
694
  //{{{ LLK Output assignments
695
  // Outputs to the PCIe block are just polarity-fixed versions of the last
696
  // pipeline stage (except for TC/FIFO, which change at different times than
697
  // the data)
698
  assign llk_tx_data      = td_q3;
699
  assign llk_tx_enable_n  = {1'b0, !rem_q3};
700
  assign llk_tx_sof_n     = !(sof_q3);// || (!packet_in_progress && cd_credits_near_gte_far));
701
  assign llk_tx_eof_n     = !(eof_q3);// || (!packet_in_progress && cd_credits_near_gte_far));
702
  assign llk_tx_sop_n     = 1'b1; //not needed
703
  assign llk_tx_eop_n     = 1'b1; //not needed
704
  assign llk_tx_src_dsc_n = !(dsc_q3);// || (!packet_in_progress && cd_credits_near_gte_far));
705
  //}}}
706
 
707
  //{{{ Completion Fix and Datacredit Fix Logic
708
  always @(posedge clk) begin
709
    if (!rst_n) begin
710
      cpl_in_count <= #`TCQ 'b0;
711
      llk_tlp_halt <= #`TCQ 'b0;
712
    end else begin
713
      //Counts number of valid (not-discontinued) Completions put into the TRN interface
714
      cpl_in_count <= #`TCQ cpl_in_count + l0_stats_cfg_transmitted +
715
                            (!llk_tx_sof_n && !llk_tx_src_rdy_n_int && !llk_tx_dst_rdy_n && !llk_tlp_halt &&
716
                            (llk_tx_data[61:57] == 5'b0_0101));
717
      //Halt the LLK interface if:
718
      // 1: There are 8 (or close to 8) CPLs buffered, and the next CPL is
719
      //    being presented, or is about to.
720
      //    --or --
721
      // 2: The number of data credits is about to run out, if the link
722
      //    parter advertised credits such that it is data-credit limited
723
      llk_tlp_halt <= #`TCQ
724
          ((cpls_buffered >= TX_CPL_STALL_THRESHOLD) && fifo_q2[1] && (llk_tlp_halt || (sof_q2 && shift_pipe)))
725
                                                      ||
726
//          (TX_DATACREDIT_FIX_EN &&        
727
//           (({6'b000000,td_q2_credits} > cd_space_remaining_int)||cd_space_remaining_int_zero)
728
//                                                 &&   fifo_q2[1]   && (llk_tlp_halt || (sof_q2 && shift_pipe)))
729
//                                                      ||
730
          (TX_DATACREDIT_FIX_EN && (len_eq1_q2 || !TX_DATACREDIT_FIX_1DWONLY) && (
731
           (pd_credits_near_gte_far              && ~|fifo_q2[1:0] && (llk_tlp_halt || (sof_q2 && shift_pipe))) ||
732
           (npd_credits_near_gte_far             &&   fifo_q2[0]   && (llk_tlp_halt || (sof_q2 && shift_pipe)) && LEGACY_EP))
733
                            );
734
 
735
    end
736
  end
737
 
738
  //synthesis translate_off
739
  reg llk_tlp_halt_cpl8buf;
740
  reg llk_tlp_halt_cpldatacredit;
741
  reg llk_tlp_halt_pdatacredit;
742
  reg llk_tlp_halt_npdatacredit;
743
 
744
  always @(posedge clk) begin
745
    if (!rst_n) begin
746
      llk_tlp_halt_cpl8buf       <= #`TCQ 1'b0;
747
      llk_tlp_halt_cpldatacredit <= #`TCQ 1'b0;
748
      llk_tlp_halt_pdatacredit   <= #`TCQ 1'b0;
749
      llk_tlp_halt_npdatacredit  <= #`TCQ 1'b0;
750
    end else begin
751
      llk_tlp_halt_cpl8buf       <= #`TCQ ((cpls_buffered >= TX_CPL_STALL_THRESHOLD) && fifo_q2[1] &&
752
                                           (llk_tlp_halt || (sof_q2 && shift_pipe)));
753
      llk_tlp_halt_cpldatacredit <= #`TCQ (TX_DATACREDIT_FIX_EN && ({6'b0,td_q2_credits} > cd_space_remaining_int));
754
      llk_tlp_halt_pdatacredit   <= #`TCQ (TX_DATACREDIT_FIX_EN && (len_eq1_q2 || !TX_DATACREDIT_FIX_1DWONLY) &&
755
                                           (pd_credits_near_gte_far && ~|fifo_q2[1:0] &&
756
                                           (llk_tlp_halt || (sof_q2 && shift_pipe))));
757
      llk_tlp_halt_npdatacredit  <= #`TCQ (TX_DATACREDIT_FIX_EN && (len_eq1_q2 || !TX_DATACREDIT_FIX_1DWONLY) &&
758
                                           (npd_credits_near_gte_far &&  fifo_q2[0]   &&
759
                                           (llk_tlp_halt || (sof_q2 && shift_pipe)) && LEGACY_EP));
760
    end
761
  end
762
  //synthesis translate_on
763
 
764
  assign cpls_buffered   = cpl_in_count - tx_ch_credits_consumed[4:0];
765
  assign trn_tbuf_av_cpl = (cpls_buffered < (TX_CPL_STALL_THRESHOLD - 2));
766
 
767
  assign near_end_pd_credits_buffered  = (user_pd_data_credits_in  - tx_pd_credits_consumed);
768
  assign near_end_npd_credits_buffered = (user_npd_data_credits_in - tx_npd_credits_consumed);
769
  //This is an estimate of the number of Cpls buffered in the TLM's Tx buffer.
770
  //It makes a conservate estimate of Cfg Cpls.
771
  //#Cpls presented on TRN - # Cpls sent (subtract conservate estimate for internal Cfg Cpls)
772
  assign near_end_cd_credits_buffered  = (all_cd_data_credits_in  - tx_cd_credits_consumed);
773
 
774
  assign clear_cpl_count = llk_tx_chan_space_cpl_empty;
775
 
776
  assign packet_in_progress = packet_in_progress_reg || (sof_q3 && !llk_tx_src_rdy_n);
777
 
778
  always @(posedge clk) begin
779
    if (!rst_n) begin
780
       packet_in_progress_reg <= #`TCQ 0;
781
    end else if (sof_q3 && !llk_tx_src_rdy_n) begin
782
       packet_in_progress_reg <= #`TCQ 1;
783
    end else if (eof_q3 && !llk_tx_src_rdy_n) begin
784
       packet_in_progress_reg <= #`TCQ 0;
785
    end
786
  end
787
 
788
  always @(posedge clk) begin
789
    if (!rst_n) begin
790
      user_pd_data_credits_in     <= #`TCQ TX_DATACREDIT_FIX_MARGIN;
791
      user_npd_data_credits_in    <= #`TCQ 'h1; //NPD is different; must account for itself only
792
      user_cd_data_credits_in     <= #`TCQ TX_DATACREDIT_FIX_MARGIN;
793
      all_cd_data_credits_in      <= #`TCQ TX_DATACREDIT_FIX_MARGIN;
794
      l0_stats_cfg_transmitted_cnt<= #`TCQ 0;
795
      near_end_cd_credits_buffered_11_d<= #`TCQ 0;
796
    end else begin
797
      near_end_cd_credits_buffered_11_d<= #`TCQ near_end_cd_credits_buffered[11];
798
      // POSTED FIX
799
      if (sofpd_q2_rose)
800
        user_pd_data_credits_in    <= #`TCQ user_pd_data_credits_in + td_q2_credits;
801
      // NON-POSTED FIX
802
      if (sofnpd_q2_rose)
803
        user_npd_data_credits_in   <= #`TCQ user_npd_data_credits_in + 1;
804
      // COMPLETION FIX
805
      if (sofcpl_q2_rose) begin
806
        user_cd_data_credits_in    <= #`TCQ user_cd_data_credits_in + td_q2_credits;
807
        user_cd_data_credits_in_minus_trn_pfc_cplh_cl_plus1 <= #`TCQ user_cd_data_credits_in + td_q2_credits -
808
                                                              trn_pfc_cplh_cl_plus1;
809
      end
810
      //If Cpl queue goes empty, then near_end_cd_credits_buffered s/b 0 (or MARGIN). The
811
      //Cfg Cpl estimate (possibly high)  s/b adjusted to reflect the delta
812
      //between total consumed and user to return "near_end.." to MARGIN (trn_pfc_cplh_cl_plus1)
813
//      if (llk_tx_chan_space_cpl_empty || near_end_cd_credits_buffered[11])
814
      if (llk_tx_chan_space_cpl_empty || near_end_cd_credits_buffered_11_d)
815
        l0_stats_cfg_transmitted_cnt <= #`TCQ tx_cd_credits_consumed - user_cd_data_credits_in_minus_trn_pfc_cplh_cl_plus1;
816
      else
817
        l0_stats_cfg_transmitted_cnt <= #`TCQ l0_stats_cfg_transmitted_cnt + l0_stats_cfg_transmitted;
818
 
819
      if (sofcpl_q2_rose)
820
        all_cd_data_credits_in     <= #`TCQ user_cd_data_credits_in + l0_stats_cfg_transmitted_cnt + td_q2_credits;
821
      else
822
        all_cd_data_credits_in     <= #`TCQ user_cd_data_credits_in + l0_stats_cfg_transmitted_cnt;
823
    end
824
  end
825
 
826
 
827
  always @(posedge clk) begin
828
    if (!rst_n) begin
829
      td_q2_credits_prev           <= #`TCQ 'h0;
830
      llk_tx_chan_space_cpl_empty  <= #`TCQ 1'b0;
831
      llk_cpl_second_cycle         <= #`TCQ 1'b0;
832
      q2_cpl_second_cycle          <= #`TCQ 1'b0;
833
      trn_pfc_cplh_cl_upd_d1       <= #`TCQ 1'b0;
834
      trn_pfc_cplh_cl_upd_d2       <= #`TCQ 1'b0;
835
      trn_pfc_cplh_cl_plus1        <= #`TCQ 'd9; //default of 8 headers + 1
836
    end else begin
837
      if (sofcpl_q2_rose)
838
        td_q2_credits_prev           <= #`TCQ td_q2_credits[0];
839
      //llk_tx_chan_space_cpl_empty  <= #`TCQ (llk_tx_chan_space[7:0] == 8'hb1) && llk_cpl_second_cycle;
840
      llk_tx_chan_space_cpl_empty  <= #`TCQ (llk_tx_chan_space[7:0] == CHANSPACE_CPLEMPTY) && (llk_tx_ch_fifo==2'b10);
841
      llk_cpl_second_cycle         <= #`TCQ !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n && llk_tx_ch_fifo[1];
842
      q2_cpl_second_cycle          <= #`TCQ sof_q2 && vld_q2 && shift_pipe && td_q2_cpl;
843
      trn_pfc_cplh_cl_upd_d1       <= #`TCQ trn_pfc_cplh_cl_upd;
844
      trn_pfc_cplh_cl_upd_d2       <= #`TCQ trn_pfc_cplh_cl_upd_d1;
845
      if (trn_pfc_cplh_cl_upd && !trn_pfc_cplh_cl_upd_d1)
846
        trn_pfc_cplh_cl_plus1        <= #`TCQ {1'b0,trn_pfc_cplh_cl} + 1;
847
    end
848
  end
849
 
850
  always @(posedge clk) begin
851
    //SOFq2___|A|_|B|_____ assume "A" is final good packet (first pkt to violate inequality)
852
    //EOFq2_____|A|_|B|___
853
    //userpd____(+A (+B
854
    //gte  _______|^^^^^^^
855
    //halt _________|^^^^^
856
    //SOFq3_____|A|_|B|___  
857
    //EOFq3_______|A|_|B|_  
858
    if (!pd_credit_limited)
859
      pd_credits_near_gte_far     <= #`TCQ 1'b0;
860
    else
861
      pd_credits_near_gte_far     <= #`TCQ (near_end_pd_credits_buffered  >= tx_pd_credits_available);
862
    if (!npd_credit_limited)
863
      npd_credits_near_gte_far    <= #`TCQ 1'b0;
864
    else
865
      npd_credits_near_gte_far    <= #`TCQ (near_end_npd_credits_buffered >  tx_npd_credits_available);
866
 
867
    //SOFq2___|A|_|B|_____ assume "A" is final good packet (does NOT to violate inequality)
868
    //EOFq2_____|A|_|B|___
869
    //usercd____(+A (+B
870
    //cdrema______(+A (+B
871
    //gte  _______|^^^^^^^
872
    //halt _________|^^^^^
873
    //SOFq3_____|A|_|B|___
874
    //EOFq3_______|A|_|B|_
875
  end
876
 
877
  always @(posedge clk) begin
878
    if (!cd_credit_limited) begin
879
      cd_space_remaining_int      <= #`TCQ 12'hFFF;
880
      cd_space_remaining_int_zero <= #`TCQ 1'b0;
881
//  else if (tx_cd_credits_available < near_end_cd_credits_buffered) //underflow protection
882
//    cd_space_remaining_int      <= #`TCQ 0;
883
    end else begin
884
      //tx_cd_credits_available is how many credits the link partner can
885
      // accept, and no more than that should exist in the Tx buffer (otherwise
886
      // data credit bug c/b triggered, and TLPs c/b sent). It is CPL DATA LIMIT-CONSUMED 
887
      cd_space_remaining_int      <= #`TCQ (tx_cd_credits_available  - near_end_cd_credits_buffered);
888
      cd_space_remaining_int_zero <= #`TCQ (tx_cd_credits_available <= near_end_cd_credits_buffered);
889
    end
890
  end
891
 
892
  //}}}
893
 
894
  //{{{ Debug
895
  //synthesis translate_off
896
 reg [11:0] llk_pd_credit_count;
897
 reg [11:0] llk_pd_credit_count_reg;
898
 
899
 reg [11:0] llk_npd_credit_count;
900
 reg [11:0] llk_npd_credit_count_reg;
901
 
902
 reg [11:0] llk_cpl_credit_count;
903
 reg [11:0] llk_cpl_credit_count_reg;
904
 
905
  always @(posedge clk) begin
906
     if (!rst_n)
907
        llk_pd_credit_count_reg <= #`TCQ TX_DATACREDIT_FIX_MARGIN;
908
     else if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n &&
909
              ((llk_tx_data[62] && (llk_tx_data[60:56]==5'b00000)) || (llk_tx_data[62:59] == 4'b11_10)))
910
        if (llk_tx_data[41:32]==10'h0)
911
          llk_pd_credit_count_reg <= #`TCQ llk_pd_credit_count_reg + {1'b1,llk_tx_data[41:34]};
912
        else
913
          llk_pd_credit_count_reg <= #`TCQ llk_pd_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
914
  end
915
  always @* begin
916
     if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n &&
917
         ((llk_tx_data[62] && (llk_tx_data[60:56]==5'b00000)) || (llk_tx_data[62:59] == 4'b11_10)))
918
        if (llk_tx_data[41:32]==10'h0)
919
          llk_pd_credit_count = llk_pd_credit_count_reg + {1'b1,llk_tx_data[41:34]};
920
        else
921
          llk_pd_credit_count = llk_pd_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
922
     else
923
       llk_pd_credit_count = llk_pd_credit_count_reg;
924
  end
925
 
926
 
927
  always @(posedge clk) begin
928
     if (!rst_n)
929
        llk_npd_credit_count_reg <= #`TCQ 'h1;
930
     else if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n && (llk_tx_data[62:56]==7'b100_0010))
931
        llk_npd_credit_count_reg <= #`TCQ llk_npd_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
932
  end
933
  always @* begin
934
     if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n && (llk_tx_data[62:56]==7'b100_0010))
935
        llk_npd_credit_count = llk_npd_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
936
     else
937
        llk_npd_credit_count = llk_npd_credit_count_reg;
938
  end
939
 
940
  always @(posedge clk) begin
941
     if (!trn_pfc_cplh_cl_upd_d2)
942
        llk_cpl_credit_count_reg <= #`TCQ {3'b000, trn_pfc_cplh_cl_plus1};
943
     else if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n && (llk_tx_data[62:57]==6'b100_101))
944
        llk_cpl_credit_count_reg <= #`TCQ llk_cpl_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
945
  end
946
  always @* begin
947
     if (!llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n && (llk_tx_data[62:57]==6'b100_101))
948
        llk_cpl_credit_count = llk_cpl_credit_count_reg + llk_tx_data[41:34] + |llk_tx_data[33:32];
949
     else
950
        llk_cpl_credit_count = llk_cpl_credit_count_reg;
951
  end
952
 
953
  wire  [11:0] user_pd_data_credits_in_raw  = user_pd_data_credits_in  - TX_DATACREDIT_FIX_MARGIN;
954
  wire  [11:0] user_npd_data_credits_in_raw = user_npd_data_credits_in - 1;
955
  wire  [11:0] user_cd_data_credits_in_raw  = all_cd_data_credits_in  - TX_DATACREDIT_FIX_MARGIN;
956
  //synthesis translate_on
957
  //}}}
958
 
959
  //{{{ Assertions
960
  `ifdef SV
961
  //synthesis translate_off
962
     //During SOF, either LLK Tx is inactive, or active transmitting non-Cpl, or active
963
     // transmitting a Cpl and is below threshold
964
   ASSERT_LLK_TX_NOCPL_BEYOND_THRESHOLD: assert property (@(posedge clk)
965
       !llk_tx_sof_n && !llk_tx_src_rdy_n && llk_tx_ch_fifo[1] |->
966
              (cpls_buffered <= TX_CPL_STALL_THRESHOLD)
967
                                                         ) else $fatal;
968
   ASSERT_SHIFT_PIPE_LUT_EQ_EQUATION:    assert property (@(posedge clk)
969
        rst_n  |-> (shift_pipe == shift_pipe_old)
970
                                                         ) else $fatal;
971
   ASSERT_EOFQ1Q2_REPLACEMENT:           assert property (@(posedge clk)
972
        rst_n  |-> (eof_q1_or_eof_q2_only == (eof_q1 || (eof_q2 && !sof_q1)))
973
                                                         ) else $fatal;
974
   ASSERT_LLKHALT_RISES_ONLY_ON_LLKSOF:  assert property (@(posedge clk)
975
        rst_n && llk_tlp_halt |-> !llk_tx_sof_n
976
                                                         ) else $fatal;
977
   ASSERT_LLK_PD_CREDITCNT_INCONSISTENT: assert property (@(posedge clk)
978
        rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n |-> (llk_pd_credit_count != user_pd_data_credits_in)
979
                                                         ) else $fatal;
980
   ASSERT_LLK_NPD_CREDITCNT_INCONSISTENT:assert property (@(posedge clk)
981
        rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n |-> (llk_npd_credit_count!= user_npd_data_credits_in)
982
                                                         ) else $fatal;
983
   //ASSERT_LLK_CPL_CREDITCNT_INCONSISTENT:assert property (@(posedge clk)
984
   //     rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n |-> (llk_cpl_credit_count!= user_cd_data_credits_in)
985
   //                                                      ) else $fatal;
986
  //synthesis translate_on
987
  `else
988
  //synthesis translate_off
989
     always @(posedge clk) if (rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && llk_tx_ch_fifo[1] && (cpls_buffered > TX_CPL_STALL_THRESHOLD)) begin
990
        $display("ASSERT_LLK_TX_NOCPL_BEYOND_THRESHOLD");
991
        $finish;
992
     end
993
     always @(posedge clk) if (rst_n && (shift_pipe != shift_pipe_old)) begin
994
        $display("ASSERT_SHIFT_PIPE_LUT_EQ_EQUATION");
995
        $finish;
996
     end
997
     always @(posedge clk) if (rst_n && (eof_q1_or_eof_q2_only != (eof_q1 || (eof_q2 && !sof_q1)))) begin
998
        $display("ASSERT_EOFQ1Q2_REPLACEMENT");
999
        $finish;
1000
     end
1001
     always @(posedge clk) if (rst_n && llk_tlp_halt && llk_tx_sof_n) begin
1002
        $display("ASSERT_LLKHALT_RISES_ONLY_ON_LLKSOF");
1003
        $finish;
1004
     end
1005
     always @(posedge clk) if (rst_n && llk_tlp_halt && llk_tx_sof_n) begin
1006
        $display("ASSERT_LLKHALT_RISES_ONLY_ON_LLKSOF");
1007
        $finish;
1008
     end
1009
     always @(posedge clk) if (rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n &&
1010
                               (llk_pd_credit_count != user_pd_data_credits_in)) begin
1011
        $display("ASSERT_LLK_PD_CREDITCNT_INCONSISTENT");
1012
        $finish;
1013
     end
1014
     always @(posedge clk) if (rst_n && !llk_tx_sof_n && !llk_tx_src_rdy_n && !llk_tx_dst_rdy_n &&
1015
                               (llk_npd_credit_count != user_npd_data_credits_in)) begin
1016
        $display("ASSERT_LLK_NPD_CREDITCNT_INCONSISTENT");
1017
        $finish;
1018
     end
1019
     reg [9:0] initcnt = 0;
1020
     always @(posedge clk) begin
1021
       if (!rst_n)
1022
         initcnt <= #`TCQ 0;
1023
       else if (trn_pfc_cplh_cl_upd && !(&initcnt))
1024
         initcnt <= #`TCQ initcnt + 1;
1025
     end
1026
     //Check that Posteds do not go over the limit by more than MPS
1027
     always @(posedge clk) if (rst_n && pd_credit_limited &&  (near_end_pd_credits_buffered  > (tx_pd_credits_available + 512))) begin
1028
        $display("ASSERT_TX_TOOMUCH_POSTEDDATA_OUTSTANDING");
1029
        $finish;
1030
     end
1031
     always @(posedge clk) if (rst_n && npd_credit_limited && (near_end_npd_credits_buffered  > (tx_npd_credits_available + 1))) begin
1032
        $display("ASSERT_TX_TOOMUCH_NONPOSTEDDATA_OUTSTANDING");
1033
        $finish;
1034
     end
1035
  //synthesis translate_on
1036
  `endif
1037
  //}}}
1038
 
1039
 
1040
endmodule // pcie_blk_ll_tx

powered by: WebSVN 2.1.0

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