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 : tlm_rx_data_snk_mal.v
|
53 |
|
|
//--------------------------------------------------------------------------------
|
54 |
|
|
//--------------------------------------------------------------------------------
|
55 |
|
|
/****************************************************************************
|
56 |
|
|
* Description : Rx Data Sink malformed packet detection
|
57 |
|
|
*
|
58 |
|
|
* Hierarchical :
|
59 |
|
|
*
|
60 |
|
|
* Functional :
|
61 |
|
|
* Takes incoming packets, examines the packet for correct
|
62 |
|
|
* construction and drops if it malformed.
|
63 |
|
|
*
|
64 |
|
|
***************************************************************************/
|
65 |
|
|
`timescale 1ns/1ps
|
66 |
|
|
`ifndef TCQ
|
67 |
|
|
`define TCQ 1
|
68 |
|
|
`endif
|
69 |
|
|
`ifndef PCIE
|
70 |
|
|
`ifndef AS
|
71 |
|
|
`define PCIE
|
72 |
|
|
`endif
|
73 |
|
|
`endif
|
74 |
|
|
|
75 |
|
|
module tlm_rx_data_snk_mal #(parameter DW = 32,
|
76 |
|
|
parameter FCW = 6,
|
77 |
|
|
parameter LENW = 10,
|
78 |
|
|
`ifdef PCIE
|
79 |
|
|
parameter DOWNSTREAM_PORT = 0,
|
80 |
|
|
`else // `ifdef AS
|
81 |
|
|
parameter OVC = 0,
|
82 |
|
|
parameter MVC = 0,
|
83 |
|
|
`endif
|
84 |
|
|
parameter MPS = 512,
|
85 |
|
|
parameter TYPE1_UR = 0)
|
86 |
|
|
(
|
87 |
|
|
input clk_i,
|
88 |
|
|
input reset_i,
|
89 |
|
|
|
90 |
|
|
// credit output
|
91 |
|
|
output reg [FCW-1:0] data_credits_o, // data credits for the packet
|
92 |
|
|
output data_credits_vld_o,// data credits valid
|
93 |
|
|
|
94 |
|
|
// packet steering
|
95 |
|
|
output reg cfg_o, // Packet is config
|
96 |
|
|
`ifdef AS
|
97 |
|
|
input oo_i, // Packet is OVC-bound
|
98 |
|
|
input ts_i, // Packet is Bypassable in BVC
|
99 |
|
|
`endif
|
100 |
|
|
|
101 |
|
|
// errors
|
102 |
|
|
`ifdef PCIE
|
103 |
|
|
output reg malformed_o, // packet is badly constructed
|
104 |
|
|
output reg tlp_ur_o, // unsupported request
|
105 |
|
|
output reg tlp_ur_lock_o, // unsupported request due to MemRdLk
|
106 |
|
|
output reg tlp_uc_o, // unexpected completion
|
107 |
|
|
output reg tlp_filt_o, // filter this packet - not an
|
108 |
|
|
// error, but handled @same time
|
109 |
|
|
`else // `ifdef AS
|
110 |
|
|
output reg bad_header_crc_o,
|
111 |
|
|
output reg bad_pi_chain_o,
|
112 |
|
|
output reg bad_credit_length_o,
|
113 |
|
|
output reg invalid_credit_length_o,
|
114 |
|
|
output reg non_zero_turn_pointer_o,
|
115 |
|
|
output reg unsup_mvc_o,
|
116 |
|
|
output reg unsup_ovc_o,
|
117 |
|
|
`endif
|
118 |
|
|
|
119 |
|
|
// For user/config steering
|
120 |
|
|
input [3:0] aperture_i, // Config address ext. reg. number
|
121 |
|
|
input load_aperture_i,
|
122 |
|
|
|
123 |
|
|
`ifdef PCIE
|
124 |
|
|
// for format calculations
|
125 |
|
|
input eval_fulltype_i, // Latch fulltype_i
|
126 |
|
|
input [6:0] fulltype_i, // Type valid on eval_fulltype_i
|
127 |
|
|
input eval_msgcode_i, // Latch msgcode_i
|
128 |
|
|
input [7:0] msgcode_i, // Msg code valid on eval_msgcode_i
|
129 |
|
|
input tc0_i, // Are we traffic class 0?
|
130 |
|
|
|
131 |
|
|
// for UC/UR determination
|
132 |
|
|
input hit_src_rdy_i, // are the results ready
|
133 |
|
|
input hit_ack_i, // did we request a check?
|
134 |
|
|
input hit_lock_i, // was it for a locked Memrd?
|
135 |
|
|
input hit_i, // is this our address?
|
136 |
|
|
input hit_lat3_i, // is the hit latency 3 clocks?
|
137 |
|
|
input pwr_mgmt_on_i, // are we in power mgmt mode?
|
138 |
|
|
input legacy_mode_i, // core is in legacy mode
|
139 |
|
|
|
140 |
|
|
// For user/config steering
|
141 |
|
|
input legacy_cfg_access_i,//user implements legacy config
|
142 |
|
|
input ext_cfg_access_i, // user implements extended config
|
143 |
|
|
input [7:0] offset_i, // Config address offset
|
144 |
|
|
|
145 |
|
|
// for (potential) packet drop
|
146 |
|
|
output reg hp_msg_detect_o, // obsolete hot-plug msg detected
|
147 |
|
|
`else // `ifdef AS
|
148 |
|
|
// for PI calculations
|
149 |
|
|
input [6:0] pi_1st_i,
|
150 |
|
|
input [6:0] pi_2nd_i,
|
151 |
|
|
input [6:0] pi_3rd_i,
|
152 |
|
|
input [6:0] pi_4th_i,
|
153 |
|
|
|
154 |
|
|
input load_pi_1st_i,
|
155 |
|
|
input load_pi_2nd_i,
|
156 |
|
|
input load_pi_3rd_i,
|
157 |
|
|
input load_pi_4th_i,
|
158 |
|
|
|
159 |
|
|
// for format calculations
|
160 |
|
|
input [6:0] hcrc_i, // Header CRC
|
161 |
|
|
input [50:0] route_header_i, // Route header covered by HCRC
|
162 |
|
|
input [4:0] turn_pointer_i, // Pointer into the Turn Pool
|
163 |
|
|
input dir_i, // Direction (1 = back-route)
|
164 |
|
|
input switch_mode_i, // Are we in a Switch?
|
165 |
|
|
|
166 |
|
|
// For user/config steering
|
167 |
|
|
input [31:0] offset_i, // Config address offset
|
168 |
|
|
input load_offset_i,
|
169 |
|
|
|
170 |
|
|
input fabric_manager_mode_i, // Is core a Fabric Manager?
|
171 |
|
|
input [31:0] cmm_ap0_space_end_i, // End of Aperture 0 range
|
172 |
|
|
input [31:0] cmm_ap1_space_start_i, // Start of Aperture 1 range
|
173 |
|
|
input [31:0] cmm_ap1_space_end_i, // End of Aperture 1 range
|
174 |
|
|
|
175 |
|
|
// for packet drop
|
176 |
|
|
input [1:0] lnk_state_i, // link state
|
177 |
|
|
input lnk_state_src_rdy_i, // link state write enable
|
178 |
|
|
output filter_drop_o,
|
179 |
|
|
`endif
|
180 |
|
|
|
181 |
|
|
// for length calculations
|
182 |
|
|
input eval_formats_i, // latch the formatting check
|
183 |
|
|
input [9:0] length_i, // supposed length of the packet
|
184 |
|
|
`ifdef PCIE
|
185 |
|
|
input length_1dw_i, // true if length_i == 1
|
186 |
|
|
`endif
|
187 |
|
|
input sof_i, // beginning of header
|
188 |
|
|
input eof_i, // end of packet
|
189 |
|
|
`ifdef PCIE
|
190 |
|
|
input rem_i, // rem at eof
|
191 |
|
|
input td_i, // packet has digest
|
192 |
|
|
input [2:0] max_payload_i // as cfg'd by the cmm
|
193 |
|
|
`else // `ifdef AS
|
194 |
|
|
input [3:0] max_payload_i // as cfg'd by the cmm
|
195 |
|
|
`endif
|
196 |
|
|
);
|
197 |
|
|
|
198 |
|
|
`ifdef PCIE
|
199 |
|
|
//---------------------------------------------------------------------------
|
200 |
|
|
// PCI Express constants
|
201 |
|
|
//---------------------------------------------------------------------------
|
202 |
|
|
// Full Type
|
203 |
|
|
localparam MRD32 = 7'b00_00000;
|
204 |
|
|
localparam MRD64 = 7'b01_00000;
|
205 |
|
|
localparam MRD32LK = 7'b00_00001;
|
206 |
|
|
localparam MRD64LK = 7'b01_00001;
|
207 |
|
|
localparam MWR32 = 7'b10_00000;
|
208 |
|
|
localparam MWR64 = 7'b11_00000;
|
209 |
|
|
localparam IORD = 7'b00_00010;
|
210 |
|
|
localparam IOWR = 7'b10_00010;
|
211 |
|
|
localparam CFGRD0 = 7'b00_00100;
|
212 |
|
|
localparam CFGWR0 = 7'b10_00100;
|
213 |
|
|
localparam CFGRD1 = 7'b00_00101;
|
214 |
|
|
localparam CFGWR1 = 7'b10_00101;
|
215 |
|
|
localparam CFGANY = 7'bx0_0010x;
|
216 |
|
|
localparam CFGANY0 = 7'bx0_00100;
|
217 |
|
|
localparam CFGANY1 = 7'bx0_00101;
|
218 |
|
|
localparam MSG = 7'b01_10xxx;
|
219 |
|
|
localparam MSGD = 7'b11_10xxx;
|
220 |
|
|
localparam CPL = 7'b00_01010;
|
221 |
|
|
localparam CPLD = 7'b10_01010;
|
222 |
|
|
localparam CPLLK = 7'b00_01011;
|
223 |
|
|
localparam CPLDLK = 7'b10_01011;
|
224 |
|
|
|
225 |
|
|
// Message code
|
226 |
|
|
localparam UNLOCK = 8'b0000_0000;
|
227 |
|
|
localparam PM_ACTIVE_STATE_NAK = 8'b0001_0100;
|
228 |
|
|
localparam PM_PME = 8'b0001_1000;
|
229 |
|
|
localparam PME_TURN_OFF = 8'b0001_1001;
|
230 |
|
|
localparam PME_TO_ACK = 8'b0001_1011;
|
231 |
|
|
localparam ATTENTION_INDICATOR_OFF = 8'b0100_0000;
|
232 |
|
|
localparam ATTENTION_INDICATOR_ON = 8'b0100_0001;
|
233 |
|
|
localparam ATTENTION_INDICATOR_BLINK = 8'b0100_0011;
|
234 |
|
|
localparam POWER_INDICATOR_ON = 8'b0100_0101;
|
235 |
|
|
localparam POWER_INDICATOR_BLINK = 8'b0100_0111;
|
236 |
|
|
localparam POWER_INDICATOR_OFF = 8'b0100_0100;
|
237 |
|
|
localparam ATTENTION_BUTTON_PRESSED = 8'b0100_1000;
|
238 |
|
|
localparam SET_SLOT_POWER_LIMIT = 8'b0101_0000;
|
239 |
|
|
localparam ASSERT_INTA = 8'b0010_0000;
|
240 |
|
|
localparam ASSERT_INTB = 8'b0010_0001;
|
241 |
|
|
localparam ASSERT_INTC = 8'b0010_0010;
|
242 |
|
|
localparam ASSERT_INTD = 8'b0010_0011;
|
243 |
|
|
localparam DEASSERT_INTA = 8'b0010_0100;
|
244 |
|
|
localparam DEASSERT_INTB = 8'b0010_0101;
|
245 |
|
|
localparam DEASSERT_INTC = 8'b0010_0110;
|
246 |
|
|
localparam DEASSERT_INTD = 8'b0010_0111;
|
247 |
|
|
localparam ERR_COR = 8'b0011_0000;
|
248 |
|
|
localparam ERR_NONFATAL = 8'b0011_0001;
|
249 |
|
|
localparam ERR_FATAL = 8'b0011_0011;
|
250 |
|
|
localparam VENDOR_DEFINED_TYPE_0 = 8'b0111_1110;
|
251 |
|
|
localparam VENDOR_DEFINED_TYPE_1 = 8'b0111_1111;
|
252 |
|
|
|
253 |
|
|
// Route
|
254 |
|
|
localparam ROUTE_TO_RC = 3'b000;
|
255 |
|
|
localparam ROUTE_BY_AD = 3'b001;
|
256 |
|
|
localparam ROUTE_BY_ID = 3'b010;
|
257 |
|
|
localparam ROUTE_BROAD = 3'b011;
|
258 |
|
|
localparam ROUTE_LOCAL = 3'b100;
|
259 |
|
|
localparam ROUTE_GATHR = 3'b101;
|
260 |
|
|
localparam ROUTE_RSRV0 = 3'b110;
|
261 |
|
|
localparam ROUTE_RSRV1 = 3'b111;
|
262 |
|
|
`endif // `ifdef PCIE
|
263 |
|
|
|
264 |
|
|
//---------------------------------------------------------------------------
|
265 |
|
|
// Other constants
|
266 |
|
|
//---------------------------------------------------------------------------
|
267 |
|
|
// Bus widths
|
268 |
|
|
`ifdef PCIE
|
269 |
|
|
localparam DCW = FCW + ((DW == 64) ? 1 : 2); // Data-count width
|
270 |
|
|
localparam PLW = (FCW == 9) ? 10 : (FCW + 2);
|
271 |
|
|
// Pertinent portion of the Length field
|
272 |
|
|
`else // `ifdef AS
|
273 |
|
|
localparam DCW = FCW + ((DW == 64) ? 3 : 4); // Data-count width
|
274 |
|
|
localparam PLW = (FCW == 6) ? 5 : FCW;
|
275 |
|
|
// Pertinent portion of the Credits Required field
|
276 |
|
|
`endif
|
277 |
|
|
|
278 |
|
|
// Port direction
|
279 |
|
|
localparam UPSTREAM_PORT = !DOWNSTREAM_PORT;
|
280 |
|
|
|
281 |
|
|
//---------------------------------------------------------------------------
|
282 |
|
|
// Internal signals
|
283 |
|
|
//---------------------------------------------------------------------------
|
284 |
|
|
// delayed versions of signals
|
285 |
|
|
reg eof_q1;
|
286 |
|
|
`ifdef PCIE
|
287 |
|
|
reg sof_q1, sof_q2, sof_q3, sof_q4;
|
288 |
|
|
reg eof_q2, eof_q3;
|
289 |
|
|
reg eval_formats_q, eval_formats_q2;
|
290 |
|
|
wire eof_sync, bar_sync;
|
291 |
|
|
reg load_aperture_q;
|
292 |
|
|
`else // `ifdef AS
|
293 |
|
|
reg load_offset_q;
|
294 |
|
|
`endif
|
295 |
|
|
|
296 |
|
|
// Length check
|
297 |
|
|
reg [DCW-1:0] word_ct;
|
298 |
|
|
reg [DCW-1:0] word_ct_d;
|
299 |
|
|
reg malformed_maxsize;
|
300 |
|
|
reg malformed_over;
|
301 |
|
|
`ifdef AS
|
302 |
|
|
reg malformed_byp_not_1;
|
303 |
|
|
reg malformed_pi4_or_5_not_1;
|
304 |
|
|
`endif
|
305 |
|
|
reg [LENW-1:0] max_length;
|
306 |
|
|
|
307 |
|
|
`ifdef PCIE
|
308 |
|
|
reg [6:0] fulltype_in;
|
309 |
|
|
reg [7:0] msgcode_in;
|
310 |
|
|
|
311 |
|
|
wire has_data = fulltype_in[6];
|
312 |
|
|
wire header_4dw = fulltype_in[5];
|
313 |
|
|
wire length_odd = length_i[0] && has_data;
|
314 |
|
|
reg type_1dw;
|
315 |
|
|
|
316 |
|
|
reg malformed_eof;
|
317 |
|
|
reg malformed_rem;
|
318 |
|
|
reg malformed_len;
|
319 |
|
|
reg malformed_min;
|
320 |
|
|
wire malformed_1dw;
|
321 |
|
|
|
322 |
|
|
wire word_ct_zero;
|
323 |
|
|
wire word_ct_neg1;
|
324 |
|
|
wire expected_rem;
|
325 |
|
|
|
326 |
|
|
reg delay_ct;
|
327 |
|
|
reg delay_ct_d;
|
328 |
|
|
`endif
|
329 |
|
|
|
330 |
|
|
`ifdef PCIE
|
331 |
|
|
// URs and UCs
|
332 |
|
|
reg malformed_fulltype;
|
333 |
|
|
reg malformed_tc;
|
334 |
|
|
reg malformed_message;
|
335 |
|
|
reg malformed_fmt;
|
336 |
|
|
|
337 |
|
|
reg ismsg, ismsgd, ismsgany;
|
338 |
|
|
reg fulltype_tc0;
|
339 |
|
|
wire msgcode_tc0;
|
340 |
|
|
reg msgcode_legacy;
|
341 |
|
|
reg msgcode_hotplug;
|
342 |
|
|
reg msgcode_sigdef;
|
343 |
|
|
reg msgcode_vendef;
|
344 |
|
|
reg msgcode_dmatch;
|
345 |
|
|
reg [2:0] msgcode_routing;
|
346 |
|
|
|
347 |
|
|
wire [2:0] routing = fulltype_i[2:0];
|
348 |
|
|
wire [2:0] routing_in = fulltype_in[2:0];
|
349 |
|
|
reg routing_vendef;
|
350 |
|
|
reg cpl_ip;
|
351 |
|
|
reg filter_msgcode;
|
352 |
|
|
reg filter_msgcode_q;
|
353 |
|
|
reg ur_pwr_mgmt, uc_pwr_mgmt;
|
354 |
|
|
reg ur_type1_cfg = 0;
|
355 |
|
|
reg ur_mem_lk, uc_cpl_lk;
|
356 |
|
|
reg ur_format, uc_format;
|
357 |
|
|
reg ur_format_lock;
|
358 |
|
|
|
359 |
|
|
// Packet steering
|
360 |
|
|
reg cfg0_ip, cfg1_ip;
|
361 |
|
|
reg is_usr_leg_ap, is_usr_ext_ap;
|
362 |
|
|
`else // `ifdef AS
|
363 |
|
|
// PI chain
|
364 |
|
|
reg [7:0] pi_1st;
|
365 |
|
|
reg [7:0] pi_2nd;
|
366 |
|
|
reg [7:0] pi_3rd;
|
367 |
|
|
reg [7:0] pi_4th;
|
368 |
|
|
|
369 |
|
|
wire load_pi_1st;
|
370 |
|
|
wire load_pi_2nd;
|
371 |
|
|
wire load_pi_3rd;
|
372 |
|
|
wire load_pi_4th;
|
373 |
|
|
|
374 |
|
|
reg pi_1st_vld;
|
375 |
|
|
reg pi_2nd_vld;
|
376 |
|
|
reg pi_3rd_vld;
|
377 |
|
|
reg pi_4th_vld;
|
378 |
|
|
|
379 |
|
|
reg pi_2nd_seq_vld;
|
380 |
|
|
reg pi_3rd_seq_vld;
|
381 |
|
|
reg pi_4th_seq_vld;
|
382 |
|
|
|
383 |
|
|
reg primary_pi0;
|
384 |
|
|
reg primary_pi4;
|
385 |
|
|
reg primary_pi5;
|
386 |
|
|
|
387 |
|
|
// Config-packet detection
|
388 |
|
|
reg pi4_ap0;
|
389 |
|
|
reg pi4_ap1;
|
390 |
|
|
reg in_ap0_range;
|
391 |
|
|
reg in_ap1_range;
|
392 |
|
|
reg secondary_pi0;
|
393 |
|
|
|
394 |
|
|
// Link state and packet drop
|
395 |
|
|
reg [1:0] lnk_state_d;
|
396 |
|
|
reg [1:0] lnk_state;
|
397 |
|
|
reg packet_ip;
|
398 |
|
|
reg packet_keep;
|
399 |
|
|
|
400 |
|
|
// Header CRC
|
401 |
|
|
wire [6:0] header_crc_d;
|
402 |
|
|
wire [6:0] header_crc_pb_d;
|
403 |
|
|
reg [6:0] header_crc;
|
404 |
|
|
reg [6:0] header_crc_pb;
|
405 |
|
|
reg path_build;
|
406 |
|
|
`endif
|
407 |
|
|
|
408 |
|
|
`ifdef PCIE
|
409 |
|
|
// Synchronize checks with BAR-hit latency
|
410 |
|
|
|
411 |
|
|
assign eof_sync = hit_lat3_i ? eof_q3 : eof_q2;
|
412 |
|
|
assign bar_sync = hit_lat3_i ? eval_formats_q2 : eval_formats_q;
|
413 |
|
|
`endif
|
414 |
|
|
|
415 |
|
|
`ifdef PCIE
|
416 |
|
|
// Calculate data credits from Length field
|
417 |
|
|
//====================================================================
|
418 |
|
|
// If the Length field is not correct, we'll signal Malformed for the
|
419 |
|
|
// packet later, while freeing that same amount with unuse.
|
420 |
|
|
//-------------------------------------------------------------------
|
421 |
|
|
|
422 |
|
|
// Data credits are calculated on SOF q2 and provided to the top level
|
423 |
|
|
// at SOF q4 for pipelining purposes.
|
424 |
|
|
|
425 |
|
|
// 1 data credit = 4 dwords, round up partials
|
426 |
|
|
always @(posedge clk_i) begin
|
427 |
|
|
if (sof_q2) begin
|
428 |
|
|
data_credits_o[PLW-3:0] <= #`TCQ has_data ?
|
429 |
|
|
(length_i[PLW-1:2] + |length_i[1:0]): 0;
|
430 |
|
|
end
|
431 |
|
|
end
|
432 |
|
|
|
433 |
|
|
generate
|
434 |
|
|
if (FCW == 9) begin : max_data_credits
|
435 |
|
|
always @(posedge clk_i) begin
|
436 |
|
|
if (sof_q2) begin
|
437 |
|
|
data_credits_o[FCW-1] <= #`TCQ ~|length_i && has_data;
|
438 |
|
|
end
|
439 |
|
|
end
|
440 |
|
|
end
|
441 |
|
|
endgenerate
|
442 |
|
|
|
443 |
|
|
assign data_credits_vld_o = sof_q4;
|
444 |
|
|
`else // `ifdef AS
|
445 |
|
|
// Calculate data credits from actual length count
|
446 |
|
|
//====================================================================
|
447 |
|
|
|
448 |
|
|
localparam WPC = 512/DW; // Words/credit (64 bytes = 512 bits/credit)
|
449 |
|
|
localparam WPCW = (DW == 64) ? 3 : 4; // log2(WPC)
|
450 |
|
|
|
451 |
|
|
// We pull off the upper portion of the word count to get the number
|
452 |
|
|
// of credits. An illustration is how this works is given further
|
453 |
|
|
// along.
|
454 |
|
|
|
455 |
|
|
always @* data_credits_o = word_ct[DCW-1:WPCW];
|
456 |
|
|
assign data_credits_vld_o = eof_q1;
|
457 |
|
|
`endif
|
458 |
|
|
|
459 |
|
|
// Malformed length checks
|
460 |
|
|
//====================================================================
|
461 |
|
|
|
462 |
|
|
//------------------------------------------------------------------------
|
463 |
|
|
// Convert the incoming CMM max-payload signal to a max length.
|
464 |
|
|
//------------------------------------------------------------------------
|
465 |
|
|
|
466 |
|
|
// Optimize out any unsupported MPS settings. Note: 2176/4096 checked
|
467 |
|
|
// differently.
|
468 |
|
|
|
469 |
|
|
`ifdef PCIE
|
470 |
|
|
localparam MAX_128 = 32; // 128B
|
471 |
|
|
localparam MAX_256 = (MPS >= 256) ? 64 : MAX_128; // 256B
|
472 |
|
|
localparam MAX_512 = (MPS >= 512) ? 128 : MAX_256; // 512B
|
473 |
|
|
localparam MAX_1024 = (MPS >= 1024) ? 256 : MAX_512; // 1024B
|
474 |
|
|
localparam MAX_2048 = (MPS >= 2048) ? 512 : MAX_1024; // 2048B
|
475 |
|
|
localparam MAX_4096 = (MPS >= 4096) ? 0 : MAX_2048; // 4096B*
|
476 |
|
|
|
477 |
|
|
always @(posedge clk_i) begin
|
478 |
|
|
if (reset_i) begin
|
479 |
|
|
max_length <= #`TCQ MAX_128;
|
480 |
|
|
end else begin
|
481 |
|
|
case (max_payload_i)
|
482 |
|
|
3'b000: max_length <= #`TCQ MAX_128;
|
483 |
|
|
3'b001: max_length <= #`TCQ MAX_256;
|
484 |
|
|
3'b010: max_length <= #`TCQ MAX_512;
|
485 |
|
|
3'b011: max_length <= #`TCQ MAX_1024;
|
486 |
|
|
3'b100: max_length <= #`TCQ MAX_2048;
|
487 |
|
|
default: max_length <= #`TCQ MAX_4096;
|
488 |
|
|
endcase
|
489 |
|
|
end
|
490 |
|
|
end
|
491 |
|
|
`else // `ifdef AS
|
492 |
|
|
localparam BVC = !OVC && !MVC;
|
493 |
|
|
|
494 |
|
|
localparam MAX_64 = !BVC ? 1 : 3;
|
495 |
|
|
localparam MAX_96 = (!BVC && (MPS >= 96)) ? 2 : 3;
|
496 |
|
|
localparam MAX_128 = (!BVC && (MPS >= 128)) ? 2 : 3;
|
497 |
|
|
localparam MAX_192 = (MPS >= 192) ? 3 : MAX_128;
|
498 |
|
|
localparam MAX_320 = (MPS >= 320) ? 5 : MAX_192;
|
499 |
|
|
localparam MAX_576 = (MPS >= 576) ? 9 : MAX_320;
|
500 |
|
|
localparam MAX_1088 = (MPS >= 1088) ? 17: MAX_576;
|
501 |
|
|
localparam MAX_2176 = (MPS >= 2176) ? 0 : MAX_1088;
|
502 |
|
|
|
503 |
|
|
// Max length is MPS, except for PI-0:0, PI-4, PI-5 and Bypassable
|
504 |
|
|
// packets, whose max length is 1.
|
505 |
|
|
|
506 |
|
|
always @(posedge clk_i) begin
|
507 |
|
|
if (reset_i) begin
|
508 |
|
|
max_length <= #`TCQ MAX_192;
|
509 |
|
|
end else begin
|
510 |
|
|
casex (max_payload_i)
|
511 |
|
|
4'b000x: max_length <= #`TCQ MAX_64;
|
512 |
|
|
4'b0010: max_length <= #`TCQ MAX_96;
|
513 |
|
|
4'b0011: max_length <= #`TCQ MAX_128;
|
514 |
|
|
4'b0100: max_length <= #`TCQ MAX_192;
|
515 |
|
|
4'b0101: max_length <= #`TCQ MAX_320;
|
516 |
|
|
4'b0110: max_length <= #`TCQ MAX_576;
|
517 |
|
|
4'b0111: max_length <= #`TCQ MAX_1088;
|
518 |
|
|
default: max_length <= #`TCQ MAX_2176;
|
519 |
|
|
endcase
|
520 |
|
|
end
|
521 |
|
|
end
|
522 |
|
|
`endif
|
523 |
|
|
|
524 |
|
|
//--------------------------------------------------------------------
|
525 |
|
|
// This checks if the Length field is set too large for programmed
|
526 |
|
|
// MPS. In PCIe, this only applies to packets with data; packets
|
527 |
|
|
// without data can have length fields that exceed MPS (other length
|
528 |
|
|
// requirements notwithstanding) since they don't have payloads.
|
529 |
|
|
//--------------------------------------------------------------------
|
530 |
|
|
always @(posedge clk_i) begin
|
531 |
|
|
if (reset_i) begin
|
532 |
|
|
malformed_maxsize <= #`TCQ 0;
|
533 |
|
|
end else if (eval_formats_i) begin
|
534 |
|
|
`ifdef PCIE
|
535 |
|
|
// If programmed MPS is not 4096, Length must be non-zero
|
536 |
|
|
if ((max_payload_i < 3'b101) || (MPS < 4096)) begin
|
537 |
|
|
malformed_maxsize <= #`TCQ ((length_i > max_length) || ~|length_i) &&
|
538 |
|
|
has_data;
|
539 |
|
|
// If programmed MPS is 4096, any Length setting is legal
|
540 |
|
|
end else begin
|
541 |
|
|
malformed_maxsize <= #`TCQ 0;
|
542 |
|
|
end
|
543 |
|
|
`else // `ifdef AS
|
544 |
|
|
// The Credits Required field must be 1 for Bypassable, PI-0:0,
|
545 |
|
|
// PI-4 and PI-5.
|
546 |
|
|
if ((!oo_i && ts_i) || (primary_pi0 && (pi_2nd_i == 0)) ||
|
547 |
|
|
primary_pi4 || primary_pi5) begin
|
548 |
|
|
malformed_maxsize <= #`TCQ (length_i != 1);
|
549 |
|
|
// If programmed MPS is not 2176, Credits Required must be non-zero
|
550 |
|
|
end else if ((max_payload_i < 4'b1000) || (MPS < 2176)) begin
|
551 |
|
|
malformed_maxsize <= #`TCQ (length_i > max_length) || ~|length_i;
|
552 |
|
|
// If programmed MPS is 2176, any Credits Required setting is legal
|
553 |
|
|
end else begin
|
554 |
|
|
malformed_maxsize <= #`TCQ 0;
|
555 |
|
|
end
|
556 |
|
|
`endif
|
557 |
|
|
end
|
558 |
|
|
end
|
559 |
|
|
|
560 |
|
|
//--------------------------------------------------------------------
|
561 |
|
|
// Payload count: DW count in 32-bit, QW count in 64-bit
|
562 |
|
|
//--------------------------------------------------------------------
|
563 |
|
|
|
564 |
|
|
`ifdef PCIE
|
565 |
|
|
//--------------------------------------------------------------------
|
566 |
|
|
// In PCIe, word_ct is loaded with the number of data beats following
|
567 |
|
|
// assertion of eval_formats_q (on the 4th DW or 3rd QW), rem
|
568 |
|
|
// notwithstanding. After eval_formats_i, word_ct decrements. This
|
569 |
|
|
// causes word_ct to equal zero on the same clock cycle EOF is
|
570 |
|
|
// expected.
|
571 |
|
|
//--------------------------------------------------------------------
|
572 |
|
|
|
573 |
|
|
// The load value of word_ct is one of the following:
|
574 |
|
|
// * Outside of eval_formats_i: current value of word_ct. We want to
|
575 |
|
|
// decrement word_ct by 1; this will be done separately.
|
576 |
|
|
// * If eval_formats_i is asserted, same as Length in 32-bit, or
|
577 |
|
|
// Length right-shifted by 1 in 64-bit. The count is later delayed
|
578 |
|
|
// based on header and TD.
|
579 |
|
|
|
580 |
|
|
generate
|
581 |
|
|
if (DW == 64) begin : word_ct_load_64
|
582 |
|
|
always @* begin
|
583 |
|
|
if (!eval_formats_i) begin
|
584 |
|
|
word_ct_d[PLW-2:0] = word_ct[PLW-2:0];
|
585 |
|
|
end else if (has_data) begin
|
586 |
|
|
word_ct_d[PLW-2:0] = length_i[PLW-1:1];
|
587 |
|
|
end else begin
|
588 |
|
|
word_ct_d[PLW-2:0] = 0;
|
589 |
|
|
end
|
590 |
|
|
end
|
591 |
|
|
end else begin : word_ct_load_32
|
592 |
|
|
always @* begin
|
593 |
|
|
if (!eval_formats_i) begin
|
594 |
|
|
word_ct_d[PLW-1:0] = word_ct[PLW-1:0];
|
595 |
|
|
end else if (has_data) begin
|
596 |
|
|
word_ct_d[PLW-1:0] = length_i[PLW-1:0];
|
597 |
|
|
end else begin
|
598 |
|
|
word_ct_d[PLW-1:0] = 0;
|
599 |
|
|
end
|
600 |
|
|
end
|
601 |
|
|
end
|
602 |
|
|
endgenerate
|
603 |
|
|
|
604 |
|
|
// If the data-count width supports 4096 bytes, we need to take care
|
605 |
|
|
// of the all-zero case.
|
606 |
|
|
|
607 |
|
|
generate
|
608 |
|
|
if (FCW == 9) begin : word_ct_max_load
|
609 |
|
|
always @* begin
|
610 |
|
|
if (!eval_formats_i) begin
|
611 |
|
|
word_ct_d[DCW-1] = word_ct[DCW-1];
|
612 |
|
|
end else begin
|
613 |
|
|
word_ct_d[DCW-1] = ~|length_i && has_data;
|
614 |
|
|
end
|
615 |
|
|
end
|
616 |
|
|
end
|
617 |
|
|
endgenerate
|
618 |
|
|
|
619 |
|
|
// Load or increment word_ct, using a mux-before-add strategy. This
|
620 |
|
|
// saves us a level of logic over add-before-mux.
|
621 |
|
|
|
622 |
|
|
always @(posedge clk_i) begin
|
623 |
|
|
if (reset_i) begin
|
624 |
|
|
word_ct <= #`TCQ 0;
|
625 |
|
|
end else if (!delay_ct && !delay_ct_d) begin
|
626 |
|
|
word_ct <= #`TCQ word_ct_d - 1;
|
627 |
|
|
end
|
628 |
|
|
end
|
629 |
|
|
`else // `ifdef AS
|
630 |
|
|
//--------------------------------------------------------------------
|
631 |
|
|
// In AS, word_ct is loaded upon sof_i with the number of data beats
|
632 |
|
|
// per credit (16 in 32-bit, 8 in 64-bit). Unlike PCIe, word_ct counts
|
633 |
|
|
// upward because the upper bits double as the data-credit quantity.
|
634 |
|
|
// As such, the count is valid on the clock cycle after eof_i, as can
|
635 |
|
|
// be seen in these 64-bit examples:
|
636 |
|
|
//
|
637 |
|
|
// 64 bytes => 8 words = 1 credit
|
638 |
|
|
// clock 1: sof_i => load counter
|
639 |
|
|
// clock 2: => length = 8
|
640 |
|
|
// clock 3: => length = 9
|
641 |
|
|
// clock 4: => length = 10
|
642 |
|
|
// clock 5: => length = 11
|
643 |
|
|
// clock 6: => length = 12
|
644 |
|
|
// clock 7: => length = 13
|
645 |
|
|
// clock 8: eof_i => length = 14
|
646 |
|
|
// clock 9: eof_q1 => length = 15 -> 01111b -> [01]111b -> 1 cred.
|
647 |
|
|
// 72 bytes => 9 words = 2 credits
|
648 |
|
|
// clock 1: sof_i => load counter
|
649 |
|
|
// clock 2: => length = 8
|
650 |
|
|
// clock 3: => length = 9
|
651 |
|
|
// clock 4: => length = 10
|
652 |
|
|
// clock 5: => length = 11
|
653 |
|
|
// clock 6: => length = 12
|
654 |
|
|
// clock 7: => length = 13
|
655 |
|
|
// clock 8: => length = 14
|
656 |
|
|
// clock 9: eof_i => length = 15
|
657 |
|
|
// clock 10: eof_q1 => length = 16 -> 10000b -> [10]000b -> 2 cred.
|
658 |
|
|
//
|
659 |
|
|
// Note in the second case that if the
|
660 |
|
|
//
|
661 |
|
|
// To account for built-in incrementer in word_ct, we load
|
662 |
|
|
// with the desired value minus one.
|
663 |
|
|
//-----------------------------------------------------------
|
664 |
|
|
|
665 |
|
|
always @* begin
|
666 |
|
|
if (sof_i) begin
|
667 |
|
|
word_ct_d = WPC - 1;
|
668 |
|
|
end else begin
|
669 |
|
|
word_ct_d = word_ct;
|
670 |
|
|
end
|
671 |
|
|
end
|
672 |
|
|
|
673 |
|
|
// Load or increment word_ct, using a mux-before-add strategy. This
|
674 |
|
|
// saves us a level of logic over add-before-mux.
|
675 |
|
|
|
676 |
|
|
always @(posedge clk_i) begin
|
677 |
|
|
if (reset_i) begin
|
678 |
|
|
word_ct <= #`TCQ 0;
|
679 |
|
|
end else begin
|
680 |
|
|
word_ct <= #`TCQ word_ct_d + 1;
|
681 |
|
|
end
|
682 |
|
|
end
|
683 |
|
|
`endif
|
684 |
|
|
|
685 |
|
|
`ifdef PCIE
|
686 |
|
|
// Delay the start of the word count based on header, TD and length
|
687 |
|
|
// (in 64-bit, even or odd). Delaying the start of the counter rather
|
688 |
|
|
// than adjusting the start value saves muxing logic into the word_ct
|
689 |
|
|
// arithmetic.
|
690 |
|
|
|
691 |
|
|
always @(posedge clk_i) begin
|
692 |
|
|
if (reset_i) begin
|
693 |
|
|
delay_ct <= #`TCQ 0;
|
694 |
|
|
delay_ct_d <= #`TCQ 0;
|
695 |
|
|
end else if (!eval_formats_i) begin
|
696 |
|
|
delay_ct <= #`TCQ delay_ct_d;
|
697 |
|
|
delay_ct_d <= #`TCQ 0;
|
698 |
|
|
end else if (DW == 64) begin
|
699 |
|
|
// In the 64-bit world, we want to count the number of data beats
|
700 |
|
|
// following the 3rd QW. It's easiest to enumerate the possible
|
701 |
|
|
// scenarios:
|
702 |
|
|
//
|
703 |
|
|
// 1. 3 DW header, no digest, even Length: The end of the packet
|
704 |
|
|
// would be aligned if not for the 3 DW header. Thus the EOF
|
705 |
|
|
// ends up at the same place as with a 4 DW, no-digest packet.
|
706 |
|
|
// Beats after 3rd QW: Length/2 + 2 - 3 = Length/2 - 1.
|
707 |
|
|
// 2. 3 DW header, no digest, odd Length: The odd DW at the end
|
708 |
|
|
// fills out the last beat in case #1: floor(Length/2) - 1.
|
709 |
|
|
// 3. 3 DW header, digest, even Length: Fills out the unaligned
|
710 |
|
|
// end of case #1: Length/2 - 1.
|
711 |
|
|
// 4. 3 DW header, digest, odd Length: Adds an unaligned beat to
|
712 |
|
|
// case #2: floor(Length/2).
|
713 |
|
|
// 5. 4 DW header, no digest, even Length: Additional header DW
|
714 |
|
|
// fills out the unaligned end of case #1: Length/2 - 1.
|
715 |
|
|
// 6. 4 DW header, no digest, odd Length: Adds an unaligned beat
|
716 |
|
|
// to case #2: floor(Length/2).
|
717 |
|
|
// 7. 4 DW header, digest, even Length: Adds an unaligned beat to
|
718 |
|
|
// case #3: Length/2.
|
719 |
|
|
// 8. 4 DW header, digest, odd Length: Fills out the unaligned end
|
720 |
|
|
// of case #4: floor(Length/2).
|
721 |
|
|
//
|
722 |
|
|
// The decrementer in word_ct causes the load value to be
|
723 |
|
|
// word_ct_d - 1 = (length_i >> 1) - 1 = floor(Length/2) - 1. We
|
724 |
|
|
// distill these out to get the delay needed from the start of
|
725 |
|
|
// the count:
|
726 |
|
|
//
|
727 |
|
|
// Case #1: (Length/2 - 1) - (floor(Length/2) - 1) = 0 delay
|
728 |
|
|
// ...
|
729 |
|
|
// Case #4: floor(Length/2) - (floor(Length/2) - 1) = 1 delay
|
730 |
|
|
// ...
|
731 |
|
|
|
732 |
|
|
case ({header_4dw,td_i,length_odd})
|
733 |
|
|
3'b000: delay_ct <= #`TCQ 0;
|
734 |
|
|
3'b001: delay_ct <= #`TCQ 0;
|
735 |
|
|
3'b010: delay_ct <= #`TCQ 0;
|
736 |
|
|
3'b011: delay_ct <= #`TCQ 1;
|
737 |
|
|
3'b100: delay_ct <= #`TCQ 0;
|
738 |
|
|
3'b101: delay_ct <= #`TCQ 1;
|
739 |
|
|
3'b110: delay_ct <= #`TCQ 1;
|
740 |
|
|
default: delay_ct <= #`TCQ 1;
|
741 |
|
|
endcase
|
742 |
|
|
|
743 |
|
|
delay_ct_d <= #`TCQ 0; // Only used in 32-bit, where two cycles
|
744 |
|
|
// of delay may be necessary
|
745 |
|
|
end else begin
|
746 |
|
|
// In the 32-bit world, the number of data beats following the 4th
|
747 |
|
|
// DW is equal to Length + Hdr_DW + TD - 4. The adjustment from
|
748 |
|
|
// word_ct_d is thus Hdr_DW + TD - 4. Note that (Hdr_DW - 3) is
|
749 |
|
|
// the same as header_4dw, so the delay is simply the sum of
|
750 |
|
|
// header_4dw + td_i - 1, PLUS ONE to account for the built-in
|
751 |
|
|
// word_ct decrementer.
|
752 |
|
|
|
753 |
|
|
case ({header_4dw,td_i})
|
754 |
|
|
2'b11: {delay_ct_d,delay_ct} <= #`TCQ 2'b10; // Two-cycle delay
|
755 |
|
|
2'b00: {delay_ct_d,delay_ct} <= #`TCQ 2'b00; // Zero-cycle delay
|
756 |
|
|
default: {delay_ct_d,delay_ct} <= #`TCQ 2'b01; // One-cycle delay
|
757 |
|
|
endcase
|
758 |
|
|
end
|
759 |
|
|
end
|
760 |
|
|
|
761 |
|
|
// Flag a word count of zero. There are two ways to represent zero
|
762 |
|
|
// word count:
|
763 |
|
|
//
|
764 |
|
|
// 1. If word_ct = 0 with no count delay (delay_ct = 0).
|
765 |
|
|
// 2. If word_ct = -1 with count delay (delay_ct = 1). Count delay
|
766 |
|
|
// represents a +1 adjustment to word_ct, so these two conditions
|
767 |
|
|
// indicate that the true word count is zero. (See the delay_ct
|
768 |
|
|
// comments below for more information.) This scenario occurs in
|
769 |
|
|
// 64-bit when we have a packet of 1 DW payload that ends on the
|
770 |
|
|
// 3rd QW: 3 DW header + TD, or 4 DW header w/o TD. (This case is
|
771 |
|
|
// not covered by malformed_min, which only covers EOF on the 1st
|
772 |
|
|
// or 2nd QW.)
|
773 |
|
|
//
|
774 |
|
|
// This logic also takes care of the case in 32-bit when Length = 1
|
775 |
|
|
// (causing word_ct = 0) but delay_ct/d is asserted due to a 4 DW
|
776 |
|
|
// header or a TLP Digest. In this case, true word count is non-zero
|
777 |
|
|
// even though word_ct = 0, because of the count delay.
|
778 |
|
|
//
|
779 |
|
|
// The lowest possible start value for word_ct is -1 (derived from a
|
780 |
|
|
// payload length of 0 [or 1 in 64-bit]). This means that the true
|
781 |
|
|
// word count will never be zero if delay_ct_d is asserted, because
|
782 |
|
|
// this represents a two-cycle delay.
|
783 |
|
|
|
784 |
|
|
assign word_ct_zero = (delay_ct ? &word_ct : ~|word_ct) && !delay_ct_d;
|
785 |
|
|
|
786 |
|
|
// Flag a word count of -1. This occurs when word_ct = -1 with no
|
787 |
|
|
// count delay. Needed to detect rollover.
|
788 |
|
|
|
789 |
|
|
assign word_ct_neg1 = &word_ct && !delay_ct && !delay_ct_d;
|
790 |
|
|
reg [4:0] test_temp;
|
791 |
|
|
//------------------------------------------------------------------------
|
792 |
|
|
// Check length of short packets (1-4 DW in 32-bit, 1-2 DW in 64-bit).
|
793 |
|
|
// Longer packets are checked against word_ct.
|
794 |
|
|
//------------------------------------------------------------------------
|
795 |
|
|
always @(posedge clk_i) begin
|
796 |
|
|
if (reset_i) begin
|
797 |
|
|
malformed_min <= #`TCQ 0;
|
798 |
|
|
end else begin
|
799 |
|
|
if (DW == 64) begin
|
800 |
|
|
// 2 words or less
|
801 |
|
|
if (sof_i && eof_i) begin
|
802 |
|
|
malformed_min <= #`TCQ 1;
|
803 |
|
|
|
804 |
|
|
// Header fields too small check (3 or 4 words)
|
805 |
|
|
// header words + digest <= 3 + rem
|
806 |
|
|
end else if (sof_q1 && eof_i) begin
|
807 |
|
|
casex ({header_4dw, rem_i, td_i, has_data, length_1dw_i})
|
808 |
|
|
// No-data checks
|
809 |
|
|
// 3 DW header, 3 DW packet.. but digest is set!
|
810 |
|
|
5'b0010x: malformed_min <= #`TCQ 1;
|
811 |
|
|
// 4 DW header, 3 DW packet (w/wo digest)
|
812 |
|
|
5'b10x0x: malformed_min <= #`TCQ 1;
|
813 |
|
|
// 4 DW header, 4 DW packet.. but digest is set!
|
814 |
|
|
5'b1110x: malformed_min <= #`TCQ 1;
|
815 |
|
|
// Has-data checks
|
816 |
|
|
// 3 DW header, supposed to have data but doesn't
|
817 |
|
|
5'b00x1x: malformed_min <= #`TCQ 1;
|
818 |
|
|
// 3 DW header, only 1 DW of data, but should have more
|
819 |
|
|
5'b0xx10: malformed_min <= #`TCQ 1;
|
820 |
|
|
// 3 DW header w/TD, supposed to have data but doesn't
|
821 |
|
|
5'b0x11x: malformed_min <= #`TCQ 1;
|
822 |
|
|
// 4 DW header, supposed to have data but doesn't
|
823 |
|
|
5'b1xx1x: malformed_min <= #`TCQ 1;
|
824 |
|
|
// header-only (or header + 1DW data) packet is
|
825 |
|
|
// correctly constructed
|
826 |
|
|
default: malformed_min <= #`TCQ 0;
|
827 |
|
|
endcase
|
828 |
|
|
|
829 |
|
|
// There was data.. we'll catch these cases with the
|
830 |
|
|
// word counter
|
831 |
|
|
end else begin
|
832 |
|
|
malformed_min <= #`TCQ 0;
|
833 |
|
|
end
|
834 |
|
|
|
835 |
|
|
// 32 bit checks
|
836 |
|
|
end else begin
|
837 |
|
|
// 1 or 2 dwords
|
838 |
|
|
if ((sof_i || sof_q1) && eof_i) begin
|
839 |
|
|
malformed_min <= #`TCQ 1;
|
840 |
|
|
// 3 dword pkt, but w/ digest or data or 4 dw header
|
841 |
|
|
end else if (sof_q2 && eof_i && (td_i || header_4dw || has_data)) begin
|
842 |
|
|
malformed_min <= #`TCQ 1;
|
843 |
|
|
// 4 word pkt && header, but with digest
|
844 |
|
|
end else if (sof_q3 && eof_i && td_i && header_4dw) begin
|
845 |
|
|
malformed_min <= #`TCQ 1;
|
846 |
|
|
// we must be long enough
|
847 |
|
|
end else begin
|
848 |
|
|
malformed_min <= #`TCQ 0;
|
849 |
|
|
end
|
850 |
|
|
end
|
851 |
|
|
end
|
852 |
|
|
end
|
853 |
|
|
|
854 |
|
|
//=====================================================================
|
855 |
|
|
// Malformed TLP: incorrect length (valid at eof_o)
|
856 |
|
|
// * length field != 0 while the TLP has no data
|
857 |
|
|
// * length field doesn't match number of data dwords
|
858 |
|
|
// * length field is not hardwired correctly (1 DW only for I/O & Cfg)
|
859 |
|
|
//=====================================================================
|
860 |
|
|
|
861 |
|
|
//--------------------------------------------------------------------
|
862 |
|
|
// This checks Config and I/O packets to make sure the Length field is
|
863 |
|
|
// set to 1.
|
864 |
|
|
//--------------------------------------------------------------------
|
865 |
|
|
|
866 |
|
|
always @(posedge clk_i) begin
|
867 |
|
|
if (reset_i) begin
|
868 |
|
|
type_1dw <= #`TCQ 0;
|
869 |
|
|
end else if (eval_formats_i) begin
|
870 |
|
|
casex (fulltype_in)
|
871 |
|
|
CFGRD0, CFGWR0, CFGRD1, CFGWR1, IORD, IOWR:
|
872 |
|
|
type_1dw <= #`TCQ 1;
|
873 |
|
|
default:
|
874 |
|
|
type_1dw <= #`TCQ 0;
|
875 |
|
|
endcase
|
876 |
|
|
end
|
877 |
|
|
end
|
878 |
|
|
|
879 |
|
|
assign malformed_1dw = type_1dw && !length_1dw_i;
|
880 |
|
|
|
881 |
|
|
// Determine if the length of the packet is correct. Interpreted on
|
882 |
|
|
// every clock, but only latched on eof_q1.
|
883 |
|
|
//----------------------------------------------------------
|
884 |
|
|
|
885 |
|
|
always @(posedge clk_i) begin
|
886 |
|
|
if (reset_i) begin
|
887 |
|
|
malformed_eof <= #`TCQ 0;
|
888 |
|
|
end else begin
|
889 |
|
|
malformed_eof <= #`TCQ !eval_formats_i && !word_ct_zero;
|
890 |
|
|
end
|
891 |
|
|
end
|
892 |
|
|
`endif
|
893 |
|
|
|
894 |
|
|
`ifdef PCIE
|
895 |
|
|
// Flag when the counter rolls over. This covers the case in 32-bit
|
896 |
|
|
// where a start value of -1 is loaded into word_ct on the 4th DW.
|
897 |
|
|
// A -1 on the 4th DW means EOF should've been asserted on the 3rd DW;
|
898 |
|
|
// but because word_ct cannot be valid on the 3rd DW, we can't flag a
|
899 |
|
|
// zero count on that data beat. So we must flag when the count has
|
900 |
|
|
// been allowed to load with a rollover value on or before EOF, so
|
901 |
|
|
// that eof_q1 will detect the overflow condition.
|
902 |
|
|
//
|
903 |
|
|
// The rollover flag also ensures that the TLM doesn't mark as legal a
|
904 |
|
|
// packet that overshoots Length by exactly MPS*2 (which would cause
|
905 |
|
|
// the word counter to go down to zero a SECOND time).
|
906 |
|
|
|
907 |
|
|
always @(posedge clk_i) begin
|
908 |
|
|
if (reset_i) begin
|
909 |
|
|
malformed_over <= #`TCQ 0;
|
910 |
|
|
end else begin
|
911 |
|
|
malformed_over <= #`TCQ (word_ct_neg1 || malformed_over) &&
|
912 |
|
|
!eval_formats_i;
|
913 |
|
|
end
|
914 |
|
|
end
|
915 |
|
|
|
916 |
|
|
// Determine if REM is set incorrectly. Only matters on EOF.
|
917 |
|
|
//----------------------------------------------------------
|
918 |
|
|
|
919 |
|
|
// The expected REM is determined by payload length (even vs. odd),
|
920 |
|
|
// header size and and presence of the digest. The formula is:
|
921 |
|
|
//
|
922 |
|
|
// exp_rem = (!header_4dw + length_i[0] + td_i) % 2 == 0 -OR-
|
923 |
|
|
// exp_rem = (header_4dw + length_i[0] + td_i) % 2 == 1
|
924 |
|
|
//
|
925 |
|
|
// a.k.a. XOR. Length is qualified by has_data (embodied by the
|
926 |
|
|
// length_odd signal) as it depends on the presence of the payload.
|
927 |
|
|
|
928 |
|
|
assign expected_rem = header_4dw ^ length_odd ^ td_i;
|
929 |
|
|
|
930 |
|
|
// The check for malformed REM is performed on each clock cycle but
|
931 |
|
|
// only latched on the cycle after EOF.
|
932 |
|
|
|
933 |
|
|
always @(posedge clk_i) begin
|
934 |
|
|
if (reset_i) begin
|
935 |
|
|
malformed_rem <= #`TCQ 0;
|
936 |
|
|
end else if (DW == 32) begin
|
937 |
|
|
malformed_rem <= #`TCQ 0;
|
938 |
|
|
end else begin
|
939 |
|
|
malformed_rem <= #`TCQ rem_i ^ expected_rem;
|
940 |
|
|
end
|
941 |
|
|
end
|
942 |
|
|
|
943 |
|
|
// All our counting is complete on eof_i- latch on q1
|
944 |
|
|
// Our length is bad if the payload was bad, or if a header-only
|
945 |
|
|
// packet was too short
|
946 |
|
|
//-------------------------------------------------------------
|
947 |
|
|
always @(posedge clk_i) begin
|
948 |
|
|
if (reset_i) begin
|
949 |
|
|
malformed_len <= #`TCQ 0;
|
950 |
|
|
end else if (eof_q1) begin
|
951 |
|
|
malformed_len <= #`TCQ malformed_eof || malformed_over ||
|
952 |
|
|
malformed_rem || malformed_min;
|
953 |
|
|
end
|
954 |
|
|
end
|
955 |
|
|
|
956 |
|
|
always @(posedge clk_i) begin
|
957 |
|
|
if (reset_i) begin
|
958 |
|
|
malformed_o <= #`TCQ 0;
|
959 |
|
|
end else if (eof_sync) begin
|
960 |
|
|
malformed_o <= #`TCQ malformed_len || malformed_fmt;
|
961 |
|
|
end
|
962 |
|
|
end
|
963 |
|
|
`else // `ifdef AS
|
964 |
|
|
// Flag when the counter exceeds Credits Required. We trigger when
|
965 |
|
|
// word_ct equals the maximum allowed for Credits Required. An
|
966 |
|
|
// adjustment must be made for MPS = 96, since this represents an
|
967 |
|
|
// overflow on a half-credit. Note that this is the only case where
|
968 |
|
|
// we check the RUNNING word count against MPS. The malformed_maxsize
|
969 |
|
|
// logic covers all other cases where the actual Credits Required
|
970 |
|
|
// field exceeds MPS.
|
971 |
|
|
//
|
972 |
|
|
// We must adjust the incoming CR upwards for the all-zeroes case.
|
973 |
|
|
|
974 |
|
|
reg [WPCW-1:0] word_ct_lo_limit;
|
975 |
|
|
reg [FCW-1:0] word_ct_hi_limit;
|
976 |
|
|
wire [DCW-1:0] word_ct_limit;
|
977 |
|
|
reg [FCW-1:0] true_length;
|
978 |
|
|
|
979 |
|
|
always @(posedge clk_i) begin
|
980 |
|
|
if (reset_i) begin
|
981 |
|
|
word_ct_lo_limit <= #`TCQ 0;
|
982 |
|
|
end else if ((max_payload_i == 4'b0010) && !BVC && (MPS >= 96) &&
|
983 |
|
|
(length_i == 2)) begin
|
984 |
|
|
word_ct_lo_limit <= #`TCQ WPC/2;
|
985 |
|
|
end else begin
|
986 |
|
|
word_ct_lo_limit <= #`TCQ 0;
|
987 |
|
|
end
|
988 |
|
|
end
|
989 |
|
|
|
990 |
|
|
generate
|
991 |
|
|
if (FCW == 6) begin : word_ct_limit_2176
|
992 |
|
|
always @* begin
|
993 |
|
|
if (~|length_i) begin // All zeroes
|
994 |
|
|
true_length = 34;
|
995 |
|
|
end else begin
|
996 |
|
|
true_length = {1'b0,length_i};
|
997 |
|
|
end
|
998 |
|
|
end
|
999 |
|
|
end else begin : word_ct_limit_below_2176
|
1000 |
|
|
always @* true_length = length_i[FCW-1:0];
|
1001 |
|
|
end
|
1002 |
|
|
endgenerate
|
1003 |
|
|
|
1004 |
|
|
always @(posedge clk_i) begin
|
1005 |
|
|
if (reset_i) begin
|
1006 |
|
|
word_ct_hi_limit <= #`TCQ 1;
|
1007 |
|
|
end else begin
|
1008 |
|
|
word_ct_hi_limit <= #`TCQ true_length + 1;
|
1009 |
|
|
end
|
1010 |
|
|
end
|
1011 |
|
|
|
1012 |
|
|
assign word_ct_limit = {word_ct_hi_limit,word_ct_lo_limit};
|
1013 |
|
|
|
1014 |
|
|
always @(posedge clk_i) begin
|
1015 |
|
|
if (reset_i) begin
|
1016 |
|
|
malformed_over <= #`TCQ 0;
|
1017 |
|
|
end else if (eval_formats_i) begin
|
1018 |
|
|
malformed_over <= #`TCQ 0;
|
1019 |
|
|
end else begin
|
1020 |
|
|
malformed_over <= #`TCQ (word_ct == word_ct_limit) || malformed_over;
|
1021 |
|
|
end
|
1022 |
|
|
end
|
1023 |
|
|
|
1024 |
|
|
// Flag if Credits Required is not 1 for a bypassable, PI-4 or PI-5
|
1025 |
|
|
// packet.
|
1026 |
|
|
|
1027 |
|
|
always @(posedge clk_i) begin
|
1028 |
|
|
if (reset_i) begin
|
1029 |
|
|
malformed_byp_not_1 <= #`TCQ 0;
|
1030 |
|
|
end else if (eval_formats_i) begin
|
1031 |
|
|
malformed_byp_not_1 <= #`TCQ BVC && !oo_i && ts_i && (length_i != 1);
|
1032 |
|
|
end
|
1033 |
|
|
end
|
1034 |
|
|
|
1035 |
|
|
always @(posedge clk_i) begin
|
1036 |
|
|
if (reset_i) begin
|
1037 |
|
|
malformed_pi4_or_5_not_1 <= #`TCQ 0;
|
1038 |
|
|
end else if (eval_formats_i) begin
|
1039 |
|
|
malformed_pi4_or_5_not_1 <= #`TCQ (primary_pi4 || primary_pi5) &&
|
1040 |
|
|
(length_i != 1);
|
1041 |
|
|
end
|
1042 |
|
|
end
|
1043 |
|
|
|
1044 |
|
|
// All our counting is complete on eof_i; latch on eof_q1.
|
1045 |
|
|
//-------------------------------------------------------------
|
1046 |
|
|
always @(posedge clk_i) begin
|
1047 |
|
|
if (reset_i) begin
|
1048 |
|
|
bad_credit_length_o <= #`TCQ 0;
|
1049 |
|
|
end else if (eof_q1) begin
|
1050 |
|
|
bad_credit_length_o <= #`TCQ malformed_over;
|
1051 |
|
|
end
|
1052 |
|
|
end
|
1053 |
|
|
|
1054 |
|
|
always @(posedge clk_i) begin
|
1055 |
|
|
if (reset_i) begin
|
1056 |
|
|
invalid_credit_length_o <= #`TCQ 0;
|
1057 |
|
|
end else if (eof_q1) begin
|
1058 |
|
|
invalid_credit_length_o <= #`TCQ malformed_maxsize ||
|
1059 |
|
|
malformed_byp_not_1 ||
|
1060 |
|
|
malformed_pi4_or_5_not_1;
|
1061 |
|
|
end
|
1062 |
|
|
end
|
1063 |
|
|
`endif
|
1064 |
|
|
|
1065 |
|
|
`ifdef PCIE
|
1066 |
|
|
//====================================================================
|
1067 |
|
|
// Malformed format checks
|
1068 |
|
|
//====================================================================
|
1069 |
|
|
|
1070 |
|
|
// delay this one cycle more than is strictly necessary- otherwise
|
1071 |
|
|
// we might collide with another bad back-to-back packet
|
1072 |
|
|
always @(posedge clk_i) begin
|
1073 |
|
|
if (reset_i) begin
|
1074 |
|
|
malformed_fmt <= #`TCQ 0;
|
1075 |
|
|
|
1076 |
|
|
// All type checks get triggered after we have latched
|
1077 |
|
|
// the inputs. OR together the checks afterwards.
|
1078 |
|
|
// ismsg* needs to be added into malformed_message even
|
1079 |
|
|
// though it is also included in some field checks
|
1080 |
|
|
// because completely specifying it in the case statement
|
1081 |
|
|
// absolutely kills timing
|
1082 |
|
|
end else if (bar_sync) begin
|
1083 |
|
|
malformed_fmt <= #`TCQ malformed_tc ||
|
1084 |
|
|
malformed_fulltype ||
|
1085 |
|
|
(malformed_message && ismsgany) ||
|
1086 |
|
|
malformed_maxsize ||
|
1087 |
|
|
malformed_1dw;
|
1088 |
|
|
end
|
1089 |
|
|
end
|
1090 |
|
|
|
1091 |
|
|
//--------------------------------------------------------------------
|
1092 |
|
|
// Traffic class determinations
|
1093 |
|
|
//--------------------------------------------------------------------
|
1094 |
|
|
// Bad TC received if doesn't map to any enabled VC, meaning either:
|
1095 |
|
|
// * TC not mapped to any VC
|
1096 |
|
|
// * TC mapped to a VC not enabled ** FOR THIS VERSION ONLY 0 VALID!! **
|
1097 |
|
|
// * TC other than TC0 on received:
|
1098 |
|
|
// * io and cfg
|
1099 |
|
|
// * CplDLk and I guess CplLk (MRdLk is UR and Unlock is dropped)
|
1100 |
|
|
// . Msg: power management (INT and errors are UR because routed to Root)
|
1101 |
|
|
//
|
1102 |
|
|
// Spec references on TC0 traffic restriction:
|
1103 |
|
|
// * "MRdLk, CplDLk and Unlock semantics are allowed only for (...) TC0"
|
1104 |
|
|
// * "all Assert_INTx and Deassert_INTx interrupts Requests must use TC0"
|
1105 |
|
|
// * "for legacy I/O, TC0 is used"
|
1106 |
|
|
// * "all power management system messages must use (...) TC0"
|
1107 |
|
|
// * "all Error Messages must use (...) TC0"
|
1108 |
|
|
// * "the Unlock Message must use (...) TC0"
|
1109 |
|
|
// * "MSIs are not restricted to TC0"
|
1110 |
|
|
// * cfg and io header shows a TC hardwired to 0
|
1111 |
|
|
//--------------------------------------------------------------------
|
1112 |
|
|
|
1113 |
|
|
// Latch Type and Message code, should be removed as equivalent to
|
1114 |
|
|
// cur_fulltype and cur_msgcode on the upper level
|
1115 |
|
|
|
1116 |
|
|
always @(posedge clk_i) begin
|
1117 |
|
|
if (eval_fulltype_i) begin
|
1118 |
|
|
fulltype_in <= #`TCQ fulltype_i;
|
1119 |
|
|
end
|
1120 |
|
|
end
|
1121 |
|
|
|
1122 |
|
|
always @(posedge clk_i) begin
|
1123 |
|
|
if (eval_msgcode_i) begin
|
1124 |
|
|
msgcode_in <= #`TCQ msgcode_i;
|
1125 |
|
|
end
|
1126 |
|
|
end
|
1127 |
|
|
|
1128 |
|
|
// Pre-calculate whether the Type is Msg or MsgD; ismsgany will be
|
1129 |
|
|
// removed during synthesis as equivalent to cur_fulltype_oh[MSG_BIT]
|
1130 |
|
|
// on the upper level.
|
1131 |
|
|
|
1132 |
|
|
always @(posedge clk_i) begin
|
1133 |
|
|
if (eval_fulltype_i) begin
|
1134 |
|
|
casex (fulltype_i)
|
1135 |
|
|
MSG: begin
|
1136 |
|
|
ismsg <= #`TCQ 1;
|
1137 |
|
|
ismsgd <= #`TCQ 0;
|
1138 |
|
|
ismsgany <= #`TCQ 1;
|
1139 |
|
|
end
|
1140 |
|
|
MSGD: begin
|
1141 |
|
|
ismsg <= #`TCQ 0;
|
1142 |
|
|
ismsgd <= #`TCQ 1;
|
1143 |
|
|
ismsgany <= #`TCQ 1;
|
1144 |
|
|
end
|
1145 |
|
|
default: begin
|
1146 |
|
|
ismsg <= #`TCQ 0;
|
1147 |
|
|
ismsgd <= #`TCQ 0;
|
1148 |
|
|
ismsgany <= #`TCQ 0;
|
1149 |
|
|
end
|
1150 |
|
|
endcase
|
1151 |
|
|
end
|
1152 |
|
|
end
|
1153 |
|
|
|
1154 |
|
|
// Pre-calculate whether the full type requires TC0
|
1155 |
|
|
|
1156 |
|
|
always @(posedge clk_i) begin
|
1157 |
|
|
if (eval_fulltype_i) begin
|
1158 |
|
|
casex (fulltype_i)
|
1159 |
|
|
// These Types require TC == 0
|
1160 |
|
|
CFGANY, IORD, IOWR, CPLLK, CPLDLK,
|
1161 |
|
|
MRD32LK, MRD64LK: begin
|
1162 |
|
|
fulltype_tc0 <= #`TCQ 1;
|
1163 |
|
|
end
|
1164 |
|
|
default: begin
|
1165 |
|
|
fulltype_tc0 <= #`TCQ 0;
|
1166 |
|
|
end
|
1167 |
|
|
endcase
|
1168 |
|
|
end
|
1169 |
|
|
end
|
1170 |
|
|
|
1171 |
|
|
// Pre-calculate whether the Message code requires TC0. All messages
|
1172 |
|
|
// other than Vendor_Defined_0/1 require TC0.
|
1173 |
|
|
|
1174 |
|
|
assign msgcode_tc0 = msgcode_sigdef;
|
1175 |
|
|
|
1176 |
|
|
// Check for Malformed TC
|
1177 |
|
|
|
1178 |
|
|
always @(posedge clk_i) begin
|
1179 |
|
|
if (reset_i) begin
|
1180 |
|
|
malformed_tc <= #`TCQ 0;
|
1181 |
|
|
end else if (eval_formats_i) begin
|
1182 |
|
|
if (!tc0_i) begin
|
1183 |
|
|
malformed_tc <= #`TCQ fulltype_tc0 || (ismsgany && msgcode_tc0);
|
1184 |
|
|
end else begin
|
1185 |
|
|
// tc was 0, we must be good!
|
1186 |
|
|
malformed_tc <= #`TCQ 0;
|
1187 |
|
|
end
|
1188 |
|
|
end
|
1189 |
|
|
end
|
1190 |
|
|
|
1191 |
|
|
// Check if type is valid based on allowable full types
|
1192 |
|
|
// (of spec, not what we actually support in our core)
|
1193 |
|
|
// Valid but unsupported types get turned into a UR/UC
|
1194 |
|
|
//-------------------------------------------------------
|
1195 |
|
|
always @(posedge clk_i) begin
|
1196 |
|
|
if (reset_i) begin
|
1197 |
|
|
malformed_fulltype <= #`TCQ 0;
|
1198 |
|
|
end else if (eval_formats_i) begin
|
1199 |
|
|
casex (fulltype_in)
|
1200 |
|
|
MWR32, MWR64, MRD32, MRD64, MRD32LK, MRD64LK,
|
1201 |
|
|
CFGRD0, CFGWR0, CFGRD1, CFGWR1,
|
1202 |
|
|
CPL, CPLD, CPLLK, CPLDLK,
|
1203 |
|
|
MSG, MSGD, IORD, IOWR:
|
1204 |
|
|
malformed_fulltype <= #`TCQ 0;
|
1205 |
|
|
default:
|
1206 |
|
|
malformed_fulltype <= #`TCQ 1;
|
1207 |
|
|
endcase
|
1208 |
|
|
end
|
1209 |
|
|
end
|
1210 |
|
|
|
1211 |
|
|
//====================================================================
|
1212 |
|
|
// UR/UC checks
|
1213 |
|
|
//====================================================================
|
1214 |
|
|
|
1215 |
|
|
// Completions lead to Unexpected Completion, others lead to
|
1216 |
|
|
// Unsupported Request
|
1217 |
|
|
//--------------------------------------------------------------
|
1218 |
|
|
always @(posedge clk_i) begin
|
1219 |
|
|
if (reset_i) begin
|
1220 |
|
|
cpl_ip <= #`TCQ 0;
|
1221 |
|
|
end else if (eval_formats_i) begin
|
1222 |
|
|
casex (fulltype_in)
|
1223 |
|
|
CPL, CPLD, CPLLK, CPLDLK: begin
|
1224 |
|
|
cpl_ip <= #`TCQ 1;
|
1225 |
|
|
end
|
1226 |
|
|
default: begin
|
1227 |
|
|
cpl_ip <= #`TCQ 0;
|
1228 |
|
|
end
|
1229 |
|
|
endcase
|
1230 |
|
|
end
|
1231 |
|
|
end
|
1232 |
|
|
|
1233 |
|
|
// Grab some fields that are special cases in our UC/UR
|
1234 |
|
|
// determination
|
1235 |
|
|
// * We don't drop vendor messages on bar misses
|
1236 |
|
|
// * A locked mem access when not in legacy mode is unsupported
|
1237 |
|
|
// * A locked completion when not in legacy mode is unexpected
|
1238 |
|
|
// * We reject most types while in power management mode
|
1239 |
|
|
//-------------------------------------------------------------
|
1240 |
|
|
|
1241 |
|
|
// We can receive the legacy UNLOCK message code if the user design is
|
1242 |
|
|
// a legacy device, or if this is a downstream port.
|
1243 |
|
|
|
1244 |
|
|
wire allow_legacy = legacy_mode_i || DOWNSTREAM_PORT;
|
1245 |
|
|
|
1246 |
|
|
always @(posedge clk_i) begin
|
1247 |
|
|
if (reset_i) begin
|
1248 |
|
|
ur_mem_lk <= #`TCQ 0;
|
1249 |
|
|
uc_cpl_lk <= #`TCQ 0;
|
1250 |
|
|
ur_pwr_mgmt <= #`TCQ 0;
|
1251 |
|
|
uc_pwr_mgmt <= #`TCQ 0;
|
1252 |
|
|
ur_type1_cfg <= #`TCQ 0;
|
1253 |
|
|
end else if (eval_formats_i) begin
|
1254 |
|
|
if (!allow_legacy) begin
|
1255 |
|
|
ur_mem_lk <= #`TCQ (fulltype_in == MRD32LK) ||
|
1256 |
|
|
(fulltype_in == MRD64LK);
|
1257 |
|
|
uc_cpl_lk <= #`TCQ (fulltype_in == CPLLK) ||
|
1258 |
|
|
(fulltype_in == CPLDLK);
|
1259 |
|
|
end else begin
|
1260 |
|
|
ur_mem_lk <= #`TCQ 0;
|
1261 |
|
|
uc_cpl_lk <= #`TCQ 0;
|
1262 |
|
|
end
|
1263 |
|
|
|
1264 |
|
|
if (TYPE1_UR && (fulltype_in == CFGWR1 || fulltype_in == CFGRD1 ||
|
1265 |
|
|
fulltype_in == CFGWR1)) begin
|
1266 |
|
|
// If TYPE1_UR is left as its default (0) all the ur_type1_cfg
|
1267 |
|
|
// logic should be optimized out
|
1268 |
|
|
ur_type1_cfg <= #`TCQ 1'b1;
|
1269 |
|
|
end else begin
|
1270 |
|
|
ur_type1_cfg <= #`TCQ 1'b0;
|
1271 |
|
|
end
|
1272 |
|
|
|
1273 |
|
|
casex (fulltype_in)
|
1274 |
|
|
CPL, CPLD, CPLLK, CPLDLK: begin
|
1275 |
|
|
uc_pwr_mgmt <= #`TCQ pwr_mgmt_on_i;
|
1276 |
|
|
ur_pwr_mgmt <= #`TCQ 0;
|
1277 |
|
|
end
|
1278 |
|
|
MRD32, MRD64, MRD32LK, MRD64LK, MWR32, MWR64, IORD, IOWR: begin
|
1279 |
|
|
uc_pwr_mgmt <= #`TCQ 0;
|
1280 |
|
|
ur_pwr_mgmt <= #`TCQ pwr_mgmt_on_i;
|
1281 |
|
|
end
|
1282 |
|
|
CFGWR1, CFGRD1, CFGANY1: begin
|
1283 |
|
|
uc_pwr_mgmt <= #`TCQ 0;
|
1284 |
|
|
ur_pwr_mgmt <= #`TCQ 0;
|
1285 |
|
|
end
|
1286 |
|
|
default: begin
|
1287 |
|
|
uc_pwr_mgmt <= #`TCQ 0;
|
1288 |
|
|
ur_pwr_mgmt <= #`TCQ 0;
|
1289 |
|
|
end
|
1290 |
|
|
endcase
|
1291 |
|
|
end
|
1292 |
|
|
end
|
1293 |
|
|
|
1294 |
|
|
// There are three components to a UR/UC...
|
1295 |
|
|
// 1. We're in power management mode, and this type is
|
1296 |
|
|
// not supported during power management
|
1297 |
|
|
// 2. There is a bad field determination.. we grab this
|
1298 |
|
|
// when the formats are ready, and if they are good, we
|
1299 |
|
|
// reset the register back to zero
|
1300 |
|
|
// 3. Our bar hit/miss information is available at hit_src_rdy..
|
1301 |
|
|
// if we were a miss set the field
|
1302 |
|
|
// Otherwise, use the previous value
|
1303 |
|
|
//-------------------------------------------------------------
|
1304 |
|
|
always @(posedge clk_i) begin
|
1305 |
|
|
if (reset_i) begin
|
1306 |
|
|
ur_format <= #`TCQ 0;
|
1307 |
|
|
ur_format_lock <= #`TCQ 0;
|
1308 |
|
|
uc_format <= #`TCQ 0;
|
1309 |
|
|
filter_msgcode_q <= #`TCQ 0;
|
1310 |
|
|
end else if (bar_sync) begin
|
1311 |
|
|
// 1. In power management -OR-
|
1312 |
|
|
// 2. Our packet has a message or type we don't support -OR-
|
1313 |
|
|
// 3. Our packet is a type-1 config access and it's not allowed
|
1314 |
|
|
|
1315 |
|
|
// Unsupported Request
|
1316 |
|
|
ur_format <= #`TCQ ur_pwr_mgmt || ur_mem_lk || ur_type1_cfg;
|
1317 |
|
|
ur_format_lock <= #`TCQ ur_mem_lk; //needed by errman to generate CplLk
|
1318 |
|
|
|
1319 |
|
|
// Unexpected completion
|
1320 |
|
|
uc_format <= #`TCQ uc_pwr_mgmt || uc_cpl_lk;
|
1321 |
|
|
|
1322 |
|
|
// Unpassed message (silently filtered in non-legacy mode)
|
1323 |
|
|
filter_msgcode_q <= #`TCQ filter_msgcode;
|
1324 |
|
|
end
|
1325 |
|
|
end
|
1326 |
|
|
|
1327 |
|
|
// hits are ready, or & grab the format information
|
1328 |
|
|
always @(posedge clk_i) begin
|
1329 |
|
|
if (reset_i) begin
|
1330 |
|
|
tlp_ur_o <= #`TCQ 0;
|
1331 |
|
|
tlp_ur_lock_o <= #`TCQ 0;
|
1332 |
|
|
tlp_uc_o <= #`TCQ 0;
|
1333 |
|
|
tlp_filt_o <= #`TCQ 0;
|
1334 |
|
|
end else if (hit_src_rdy_i) begin
|
1335 |
|
|
if (ur_format) begin
|
1336 |
|
|
tlp_ur_o <= #`TCQ 1;
|
1337 |
|
|
tlp_ur_lock_o <= #`TCQ ur_format_lock;
|
1338 |
|
|
end else if (!cpl_ip && hit_ack_i && !hit_i && UPSTREAM_PORT) begin
|
1339 |
|
|
tlp_ur_o <= #`TCQ 1;
|
1340 |
|
|
tlp_ur_lock_o <= #`TCQ hit_lock_i;
|
1341 |
|
|
end else begin
|
1342 |
|
|
tlp_ur_o <= #`TCQ 0;
|
1343 |
|
|
tlp_ur_lock_o <= #`TCQ 0;
|
1344 |
|
|
end
|
1345 |
|
|
if (uc_format) begin
|
1346 |
|
|
tlp_uc_o <= #`TCQ 1;
|
1347 |
|
|
end else if (cpl_ip && hit_ack_i && !hit_i && UPSTREAM_PORT) begin
|
1348 |
|
|
tlp_uc_o <= #`TCQ 1;
|
1349 |
|
|
end else begin
|
1350 |
|
|
tlp_uc_o <= #`TCQ 0;
|
1351 |
|
|
end
|
1352 |
|
|
if (filter_msgcode_q) begin
|
1353 |
|
|
tlp_filt_o <= #`TCQ 1;
|
1354 |
|
|
end else begin
|
1355 |
|
|
tlp_filt_o <= #`TCQ 0;
|
1356 |
|
|
end
|
1357 |
|
|
end
|
1358 |
|
|
end
|
1359 |
|
|
|
1360 |
|
|
//---------------------------------------------------------------------
|
1361 |
|
|
// Check if the message is constructed properly according to the spec
|
1362 |
|
|
// * routing must be correct by spec
|
1363 |
|
|
// * routing must match our ability to route (endpoint/trunk)
|
1364 |
|
|
// * Msg/MsgD type must match message value
|
1365 |
|
|
//----------------------------------------------------------------------
|
1366 |
|
|
|
1367 |
|
|
// Check for valid message code, other than Vendor_Defined. The message
|
1368 |
|
|
// code is valid if it is both:
|
1369 |
|
|
// * Defined in the spec
|
1370 |
|
|
// * Legal for the port direction
|
1371 |
|
|
|
1372 |
|
|
always @(posedge clk_i) begin
|
1373 |
|
|
if (eval_msgcode_i) begin
|
1374 |
|
|
casex (msgcode_i)
|
1375 |
|
|
UNLOCK, PME_TURN_OFF, PM_ACTIVE_STATE_NAK,
|
1376 |
|
|
SET_SLOT_POWER_LIMIT, ATTENTION_BUTTON_PRESSED,
|
1377 |
|
|
ATTENTION_INDICATOR_ON, ATTENTION_INDICATOR_OFF,
|
1378 |
|
|
ATTENTION_INDICATOR_BLINK, POWER_INDICATOR_ON,
|
1379 |
|
|
POWER_INDICATOR_OFF, POWER_INDICATOR_BLINK:
|
1380 |
|
|
msgcode_sigdef <= #`TCQ UPSTREAM_PORT;
|
1381 |
|
|
|
1382 |
|
|
ASSERT_INTA, DEASSERT_INTA, ASSERT_INTB, DEASSERT_INTB,
|
1383 |
|
|
ASSERT_INTC, DEASSERT_INTC, ASSERT_INTD, DEASSERT_INTD,
|
1384 |
|
|
ERR_COR, ERR_NONFATAL, ERR_FATAL, PME_TO_ACK:
|
1385 |
|
|
msgcode_sigdef <= #`TCQ DOWNSTREAM_PORT;
|
1386 |
|
|
|
1387 |
|
|
default:
|
1388 |
|
|
msgcode_sigdef <= #`TCQ 0;
|
1389 |
|
|
endcase
|
1390 |
|
|
end
|
1391 |
|
|
end
|
1392 |
|
|
|
1393 |
|
|
// Check for Msg vs. MsgD. In 64-bit, fulltype_i and msgcode_i are
|
1394 |
|
|
// available on the same clock cycle. In 32-bit, ismsg and ismsgd are
|
1395 |
|
|
// calculated before msgcode_i is available.
|
1396 |
|
|
|
1397 |
|
|
generate
|
1398 |
|
|
if (DW == 32) begin : msgd_check_32
|
1399 |
|
|
|
1400 |
|
|
always @(posedge clk_i) begin
|
1401 |
|
|
if (eval_msgcode_i) begin
|
1402 |
|
|
casex (msgcode_i)
|
1403 |
|
|
SET_SLOT_POWER_LIMIT:
|
1404 |
|
|
msgcode_dmatch <= #`TCQ ismsgd;
|
1405 |
|
|
default:
|
1406 |
|
|
msgcode_dmatch <= #`TCQ ismsg;
|
1407 |
|
|
endcase
|
1408 |
|
|
end
|
1409 |
|
|
end
|
1410 |
|
|
|
1411 |
|
|
end else begin : msgd_check_64
|
1412 |
|
|
|
1413 |
|
|
always @(posedge clk_i) begin
|
1414 |
|
|
if (eval_msgcode_i) begin
|
1415 |
|
|
casex (fulltype_i)
|
1416 |
|
|
MSG:
|
1417 |
|
|
msgcode_dmatch <= #`TCQ (msgcode_i != SET_SLOT_POWER_LIMIT);
|
1418 |
|
|
default:
|
1419 |
|
|
msgcode_dmatch <= #`TCQ (msgcode_i == SET_SLOT_POWER_LIMIT);
|
1420 |
|
|
endcase
|
1421 |
|
|
end
|
1422 |
|
|
end
|
1423 |
|
|
|
1424 |
|
|
end
|
1425 |
|
|
endgenerate
|
1426 |
|
|
|
1427 |
|
|
// Check the type of routing required by the Message code. Most codes
|
1428 |
|
|
// only take one routing type, but Vendor_Defined can take three types
|
1429 |
|
|
// (four if received on a downstream port) so it needs a special
|
1430 |
|
|
// register.
|
1431 |
|
|
|
1432 |
|
|
always @(posedge clk_i) begin
|
1433 |
|
|
if (eval_fulltype_i) begin
|
1434 |
|
|
routing_vendef <= #`TCQ (routing == ROUTE_LOCAL) ||
|
1435 |
|
|
(routing == ROUTE_BROAD) ||
|
1436 |
|
|
(routing == ROUTE_BY_ID);
|
1437 |
|
|
end
|
1438 |
|
|
end
|
1439 |
|
|
|
1440 |
|
|
// Create different casex blocks depending on whether
|
1441 |
|
|
// in downstream port mode or not. This is done so that when not in
|
1442 |
|
|
// downstream port mode, the interrupt-message checks will not be included.
|
1443 |
|
|
// Interrupts should not be received when in upstream mode so we
|
1444 |
|
|
// don't want to risk having their checks impact timing.
|
1445 |
|
|
|
1446 |
|
|
generate
|
1447 |
|
|
if (DOWNSTREAM_PORT == 0) begin : dont_check_int
|
1448 |
|
|
always @(posedge clk_i) begin
|
1449 |
|
|
if (eval_msgcode_i) begin
|
1450 |
|
|
casex (msgcode_i)
|
1451 |
|
|
UNLOCK, PME_TURN_OFF:
|
1452 |
|
|
msgcode_routing <= #`TCQ ROUTE_BROAD;
|
1453 |
|
|
|
1454 |
|
|
PME_TO_ACK:
|
1455 |
|
|
msgcode_routing <= #`TCQ ROUTE_GATHR;
|
1456 |
|
|
|
1457 |
|
|
PM_ACTIVE_STATE_NAK, ATTENTION_BUTTON_PRESSED,
|
1458 |
|
|
ATTENTION_INDICATOR_ON, ATTENTION_INDICATOR_OFF,
|
1459 |
|
|
ATTENTION_INDICATOR_BLINK, POWER_INDICATOR_ON,
|
1460 |
|
|
POWER_INDICATOR_OFF, POWER_INDICATOR_BLINK,
|
1461 |
|
|
SET_SLOT_POWER_LIMIT:
|
1462 |
|
|
msgcode_routing <= #`TCQ ROUTE_LOCAL;
|
1463 |
|
|
|
1464 |
|
|
// Vendor_Defined can take other values besides Route to RC;
|
1465 |
|
|
// these are covered by routing_vendef.
|
1466 |
|
|
default:
|
1467 |
|
|
msgcode_routing <= #`TCQ ROUTE_TO_RC;
|
1468 |
|
|
endcase
|
1469 |
|
|
end
|
1470 |
|
|
end
|
1471 |
|
|
end else begin : check_int
|
1472 |
|
|
always @(posedge clk_i) begin
|
1473 |
|
|
if (eval_msgcode_i) begin
|
1474 |
|
|
casex (msgcode_i)
|
1475 |
|
|
UNLOCK, PME_TURN_OFF:
|
1476 |
|
|
msgcode_routing <= #`TCQ ROUTE_BROAD;
|
1477 |
|
|
|
1478 |
|
|
PME_TO_ACK:
|
1479 |
|
|
msgcode_routing <= #`TCQ ROUTE_GATHR;
|
1480 |
|
|
|
1481 |
|
|
PM_ACTIVE_STATE_NAK, ATTENTION_BUTTON_PRESSED,
|
1482 |
|
|
ATTENTION_INDICATOR_ON, ATTENTION_INDICATOR_OFF,
|
1483 |
|
|
ATTENTION_INDICATOR_BLINK, POWER_INDICATOR_ON,
|
1484 |
|
|
POWER_INDICATOR_OFF, POWER_INDICATOR_BLINK,
|
1485 |
|
|
ASSERT_INTA, ASSERT_INTB, ASSERT_INTC, ASSERT_INTD,
|
1486 |
|
|
DEASSERT_INTA, DEASSERT_INTB, DEASSERT_INTC, DEASSERT_INTD,
|
1487 |
|
|
SET_SLOT_POWER_LIMIT:
|
1488 |
|
|
msgcode_routing <= #`TCQ ROUTE_LOCAL;
|
1489 |
|
|
|
1490 |
|
|
// Vendor_Defined can take other values besides Route to RC;
|
1491 |
|
|
// these are covered by routing_vendef.
|
1492 |
|
|
default:
|
1493 |
|
|
msgcode_routing <= #`TCQ ROUTE_TO_RC;
|
1494 |
|
|
endcase
|
1495 |
|
|
end
|
1496 |
|
|
end
|
1497 |
|
|
end
|
1498 |
|
|
endgenerate
|
1499 |
|
|
|
1500 |
|
|
// Make sure the Message parameters agree with each other:
|
1501 |
|
|
//
|
1502 |
|
|
// 1. Message code must be valid per spec
|
1503 |
|
|
// 2. Type (Msg or MsgD) must agree with the Message code
|
1504 |
|
|
// 3. If not Vendor_Defined, the Routing type must agree with the one
|
1505 |
|
|
// allowed by the Message code
|
1506 |
|
|
// 4. If Vendor_Defined, the Routing type must be:
|
1507 |
|
|
// a. Broadcast, Local or Route By ID (routing_vendef), or
|
1508 |
|
|
// b. Route to Root Complex if a downstream port
|
1509 |
|
|
// NOTE: Vendor_Defined does not care about Msg vs. MsgD.
|
1510 |
|
|
|
1511 |
|
|
always @(posedge clk_i) begin
|
1512 |
|
|
if (reset_i) begin
|
1513 |
|
|
malformed_message <= #`TCQ 0;
|
1514 |
|
|
end else if (eval_formats_i) begin
|
1515 |
|
|
if (!msgcode_vendef) begin
|
1516 |
|
|
malformed_message <= #`TCQ !msgcode_sigdef || // #1
|
1517 |
|
|
!msgcode_dmatch || // #2
|
1518 |
|
|
(routing_in != msgcode_routing); // #3
|
1519 |
|
|
end else begin
|
1520 |
|
|
malformed_message <= #`TCQ !routing_vendef && // #4
|
1521 |
|
|
!(DOWNSTREAM_PORT &&
|
1522 |
|
|
(routing_in == ROUTE_TO_RC));
|
1523 |
|
|
end
|
1524 |
|
|
end
|
1525 |
|
|
end
|
1526 |
|
|
|
1527 |
|
|
//---------------------------------------------------------------------
|
1528 |
|
|
// Check if the message is supported by our core
|
1529 |
|
|
// * routing must match our ability to route (endpoint/trunk)
|
1530 |
|
|
//----------------------------------------------------------------------
|
1531 |
|
|
|
1532 |
|
|
always @(posedge clk_i) begin
|
1533 |
|
|
if (eval_msgcode_i) begin
|
1534 |
|
|
casex (msgcode_i)
|
1535 |
|
|
UNLOCK:
|
1536 |
|
|
msgcode_legacy <= #`TCQ 1;
|
1537 |
|
|
default:
|
1538 |
|
|
msgcode_legacy <= #`TCQ 0;
|
1539 |
|
|
endcase
|
1540 |
|
|
end
|
1541 |
|
|
end
|
1542 |
|
|
|
1543 |
|
|
always @(posedge clk_i) begin
|
1544 |
|
|
if (eval_msgcode_i) begin
|
1545 |
|
|
casex (msgcode_i)
|
1546 |
|
|
POWER_INDICATOR_ON, POWER_INDICATOR_OFF,
|
1547 |
|
|
POWER_INDICATOR_BLINK, ATTENTION_INDICATOR_ON,
|
1548 |
|
|
ATTENTION_INDICATOR_OFF, ATTENTION_INDICATOR_BLINK,
|
1549 |
|
|
ATTENTION_BUTTON_PRESSED:
|
1550 |
|
|
msgcode_hotplug <= #`TCQ 1;
|
1551 |
|
|
default:
|
1552 |
|
|
msgcode_hotplug <= #`TCQ 0;
|
1553 |
|
|
endcase
|
1554 |
|
|
end
|
1555 |
|
|
end
|
1556 |
|
|
|
1557 |
|
|
always @(posedge clk_i) begin
|
1558 |
|
|
if (eval_msgcode_i) begin
|
1559 |
|
|
casex (msgcode_i)
|
1560 |
|
|
VENDOR_DEFINED_TYPE_0, VENDOR_DEFINED_TYPE_1:
|
1561 |
|
|
msgcode_vendef <= #`TCQ 1;
|
1562 |
|
|
default:
|
1563 |
|
|
msgcode_vendef <= #`TCQ 0;
|
1564 |
|
|
endcase
|
1565 |
|
|
end
|
1566 |
|
|
end
|
1567 |
|
|
|
1568 |
|
|
always @(posedge clk_i) begin
|
1569 |
|
|
if (reset_i) begin
|
1570 |
|
|
filter_msgcode <= #`TCQ 0;
|
1571 |
|
|
end else if (eval_formats_i) begin
|
1572 |
|
|
if (ismsgany) begin
|
1573 |
|
|
filter_msgcode <= #`TCQ !allow_legacy && msgcode_legacy;
|
1574 |
|
|
end else begin // not a Message
|
1575 |
|
|
filter_msgcode <= #`TCQ 0;
|
1576 |
|
|
end
|
1577 |
|
|
end
|
1578 |
|
|
end
|
1579 |
|
|
|
1580 |
|
|
//====================================================================
|
1581 |
|
|
// Steer packets to the CMM.
|
1582 |
|
|
|
1583 |
|
|
always @(posedge clk_i) begin
|
1584 |
|
|
if (reset_i) begin
|
1585 |
|
|
cfg0_ip <= #`TCQ 0;
|
1586 |
|
|
cfg1_ip <= #`TCQ 0;
|
1587 |
|
|
end else if (eval_formats_i) begin
|
1588 |
|
|
casex (fulltype_in)
|
1589 |
|
|
CFGANY0: cfg0_ip <= #`TCQ 1;
|
1590 |
|
|
default: cfg0_ip <= #`TCQ 0;
|
1591 |
|
|
endcase
|
1592 |
|
|
casex (fulltype_in)
|
1593 |
|
|
CFGANY1: cfg1_ip <= #`TCQ 1;
|
1594 |
|
|
default: cfg1_ip <= #`TCQ 0;
|
1595 |
|
|
endcase
|
1596 |
|
|
end
|
1597 |
|
|
end
|
1598 |
|
|
|
1599 |
|
|
// The user gets a Type 0 packet if:
|
1600 |
|
|
//
|
1601 |
|
|
// 1. The packet's address range is between 192 and 255 inclusive, and
|
1602 |
|
|
// the user implements legacy config space, or
|
1603 |
|
|
// 2. The packet's address range is at or above 1024 (4*256) and the
|
1604 |
|
|
// user implements extended config space.
|
1605 |
|
|
|
1606 |
|
|
always @(posedge clk_i) begin
|
1607 |
|
|
if (reset_i) begin
|
1608 |
|
|
is_usr_leg_ap <= #`TCQ 0;
|
1609 |
|
|
end else if (load_aperture_i) begin
|
1610 |
|
|
is_usr_leg_ap <= #`TCQ (aperture_i == 0) && (offset_i[7:6] == 3) &&
|
1611 |
|
|
legacy_cfg_access_i;
|
1612 |
|
|
end
|
1613 |
|
|
end
|
1614 |
|
|
|
1615 |
|
|
always @(posedge clk_i) begin
|
1616 |
|
|
if (reset_i) begin
|
1617 |
|
|
is_usr_ext_ap <= #`TCQ 0;
|
1618 |
|
|
end else if (load_aperture_i) begin
|
1619 |
|
|
is_usr_ext_ap <= #`TCQ |aperture_i[3:2] && ext_cfg_access_i;
|
1620 |
|
|
end
|
1621 |
|
|
end
|
1622 |
|
|
|
1623 |
|
|
always @(posedge clk_i) begin
|
1624 |
|
|
if (reset_i) begin
|
1625 |
|
|
load_aperture_q <= #`TCQ 0;
|
1626 |
|
|
end else begin
|
1627 |
|
|
load_aperture_q <= #`TCQ load_aperture_i;
|
1628 |
|
|
end
|
1629 |
|
|
end
|
1630 |
|
|
|
1631 |
|
|
// The packet goes to the CMM if:
|
1632 |
|
|
// 1. It is Config Type 1, OR
|
1633 |
|
|
// 2. It is Config Type 0 and the packet doesn't fall into either of
|
1634 |
|
|
// the user categories above.
|
1635 |
|
|
|
1636 |
|
|
always @(posedge clk_i) begin
|
1637 |
|
|
if (reset_i) begin
|
1638 |
|
|
cfg_o <= #`TCQ 0;
|
1639 |
|
|
end else if (load_aperture_q) begin
|
1640 |
|
|
cfg_o <= #`TCQ cfg1_ip || (cfg0_ip && !is_usr_leg_ap && !is_usr_ext_ap);
|
1641 |
|
|
end
|
1642 |
|
|
end
|
1643 |
|
|
|
1644 |
|
|
// Signal receipt of a hot-plug Message. These have been obsoleted
|
1645 |
|
|
// starting with PCIe 1.1, so the user is given the option of dropping
|
1646 |
|
|
// them.
|
1647 |
|
|
|
1648 |
|
|
always @(posedge clk_i) begin
|
1649 |
|
|
if (reset_i) begin
|
1650 |
|
|
hp_msg_detect_o <= #`TCQ 0;
|
1651 |
|
|
end else if (eval_formats_q) begin
|
1652 |
|
|
hp_msg_detect_o <= #`TCQ ismsgany && msgcode_hotplug;
|
1653 |
|
|
end
|
1654 |
|
|
end
|
1655 |
|
|
`else // `ifdef AS
|
1656 |
|
|
//====================================================================
|
1657 |
|
|
// Check for valid PI and PI chain.
|
1658 |
|
|
//====================================================================
|
1659 |
|
|
|
1660 |
|
|
// Make sure that PIs are not latched past the end of the chain. Valid
|
1661 |
|
|
// chains are:
|
1662 |
|
|
// * 0 -> 0
|
1663 |
|
|
// * 0 -> 1 -> PDU (8-126)
|
1664 |
|
|
// * 0 -> 1 -> 2 -> PDU
|
1665 |
|
|
// * 0 -> 2 -> PDU
|
1666 |
|
|
// * 1 -> PDU
|
1667 |
|
|
// * 1 -> 2 -> PDU
|
1668 |
|
|
// * 2 -> PDU
|
1669 |
|
|
// * 4
|
1670 |
|
|
// * 5
|
1671 |
|
|
// * PDU
|
1672 |
|
|
|
1673 |
|
|
// The secondary and tertiary PIs appear on the same clock cycle in
|
1674 |
|
|
// 64-bit, which is why the equation for load_pi_3rd is more complex
|
1675 |
|
|
// than the other ones.
|
1676 |
|
|
|
1677 |
|
|
assign load_pi_1st = load_pi_1st_i;
|
1678 |
|
|
|
1679 |
|
|
assign load_pi_2nd = load_pi_2nd_i && (pi_1st <= 2);
|
1680 |
|
|
|
1681 |
|
|
// In 64-bit, the secondary and tertiary PIs come on the same cycle,
|
1682 |
|
|
// so checks on the 3rd PI involve the live version of the 2nd PI.
|
1683 |
|
|
assign load_pi_3rd = load_pi_3rd_i && ((DW == 64) ?
|
1684 |
|
|
((pi_2nd_i == 1) || (pi_2nd_i == 2)) :
|
1685 |
|
|
((pi_2nd == 1) || (pi_2nd == 2)));
|
1686 |
|
|
|
1687 |
|
|
assign load_pi_4th = load_pi_4th_i && (pi_3rd_i <= 2);
|
1688 |
|
|
|
1689 |
|
|
// PIs 128-130 are "placeholders": If their corresponding registers
|
1690 |
|
|
// are not written into, they will still be greater than higher-order
|
1691 |
|
|
// PIs for the purposes of chain validation.
|
1692 |
|
|
|
1693 |
|
|
always @(posedge clk_i) begin
|
1694 |
|
|
if (sof_i) begin
|
1695 |
|
|
pi_1st <= #`TCQ load_pi_1st ? pi_1st_i : 0;
|
1696 |
|
|
pi_2nd <= #`TCQ 128;
|
1697 |
|
|
pi_3rd <= #`TCQ 129;
|
1698 |
|
|
pi_4th <= #`TCQ 130;
|
1699 |
|
|
end else begin
|
1700 |
|
|
if (load_pi_2nd) begin
|
1701 |
|
|
pi_2nd[7] <= #`TCQ 0;
|
1702 |
|
|
pi_2nd[6:0] <= #`TCQ pi_2nd_i;
|
1703 |
|
|
end
|
1704 |
|
|
if (load_pi_3rd) begin
|
1705 |
|
|
pi_3rd[7] <= #`TCQ 0;
|
1706 |
|
|
pi_3rd[6:0] <= #`TCQ pi_3rd_i;
|
1707 |
|
|
end
|
1708 |
|
|
if (load_pi_4th) begin
|
1709 |
|
|
pi_4th[7] <= #`TCQ 0;
|
1710 |
|
|
pi_4th[6:0] <= #`TCQ pi_4th_i;
|
1711 |
|
|
end
|
1712 |
|
|
end
|
1713 |
|
|
end
|
1714 |
|
|
|
1715 |
|
|
// Distill certain PIs into one-hot signals
|
1716 |
|
|
|
1717 |
|
|
always @(posedge clk_i) begin
|
1718 |
|
|
if (reset_i) begin
|
1719 |
|
|
primary_pi0 <= #`TCQ 0;
|
1720 |
|
|
primary_pi4 <= #`TCQ 0;
|
1721 |
|
|
primary_pi5 <= #`TCQ 0;
|
1722 |
|
|
end else if (load_pi_1st) begin
|
1723 |
|
|
primary_pi0 <= #`TCQ (pi_1st_i == 0);
|
1724 |
|
|
primary_pi4 <= #`TCQ (pi_1st_i == 4);
|
1725 |
|
|
primary_pi5 <= #`TCQ (pi_1st_i == 5);
|
1726 |
|
|
end
|
1727 |
|
|
end
|
1728 |
|
|
|
1729 |
|
|
always @(posedge clk_i) begin
|
1730 |
|
|
if (reset_i) begin
|
1731 |
|
|
secondary_pi0 <= #`TCQ 0;
|
1732 |
|
|
end else if (load_pi_2nd) begin
|
1733 |
|
|
secondary_pi0 <= #`TCQ (pi_2nd_i == 0);
|
1734 |
|
|
end
|
1735 |
|
|
end
|
1736 |
|
|
|
1737 |
|
|
// Check for invalid PIs. Note that placeholder PIs (128+) which
|
1738 |
|
|
// represent "blanks" are always valid.
|
1739 |
|
|
//--------------------------------------------------------------------
|
1740 |
|
|
|
1741 |
|
|
always @(posedge clk_i) begin
|
1742 |
|
|
if (reset_i) begin
|
1743 |
|
|
pi_1st_vld <= #`TCQ 1;
|
1744 |
|
|
pi_2nd_vld <= #`TCQ 1;
|
1745 |
|
|
pi_3rd_vld <= #`TCQ 1;
|
1746 |
|
|
pi_4th_vld <= #`TCQ 1;
|
1747 |
|
|
end else begin
|
1748 |
|
|
// Primary PI: Legal values are 0-2, 4, 5, 8-126
|
1749 |
|
|
pi_1st_vld <= #`TCQ (pi_1st != 3) && (pi_1st != 6) && (pi_1st != 7) &&
|
1750 |
|
|
(pi_1st != 127);
|
1751 |
|
|
|
1752 |
|
|
// Secondary PI: Legal values are 0-2, 8-126
|
1753 |
|
|
pi_2nd_vld <= #`TCQ ((pi_2nd <= 2) || (pi_2nd >= 8)) && (pi_2nd != 127);
|
1754 |
|
|
|
1755 |
|
|
// Tertiary PI: Legal values are 2, 8-126
|
1756 |
|
|
pi_3rd_vld <= #`TCQ ((pi_2nd == 2) || (pi_2nd >= 8)) && (pi_3rd != 127);
|
1757 |
|
|
|
1758 |
|
|
// Quaternary PI: Legal values are 8-126
|
1759 |
|
|
pi_4th_vld <= #`TCQ (pi_4th >= 8) && (pi_4th != 127);
|
1760 |
|
|
end
|
1761 |
|
|
end
|
1762 |
|
|
|
1763 |
|
|
// Check for invalid PI sequences. Note that the placeholder PIs will
|
1764 |
|
|
// always represent valid chains since they are greater than any legal
|
1765 |
|
|
// PI and are loaded in an increasing progression. In addition,
|
1766 |
|
|
//--------------------------------------------------------------------
|
1767 |
|
|
|
1768 |
|
|
always @(posedge clk_i) begin
|
1769 |
|
|
if (reset_i) begin
|
1770 |
|
|
pi_2nd_seq_vld <= #`TCQ 1;
|
1771 |
|
|
pi_3rd_seq_vld <= #`TCQ 1;
|
1772 |
|
|
pi_4th_seq_vld <= #`TCQ 1;
|
1773 |
|
|
end else begin
|
1774 |
|
|
// Secondary PI is sequence-valid if 1st PI = 0 or 2nd PI > 1st PI
|
1775 |
|
|
pi_2nd_seq_vld <= #`TCQ !((pi_1st < 4) && pi_2nd[7]) &&
|
1776 |
|
|
(pi_2nd > pi_1st);
|
1777 |
|
|
|
1778 |
|
|
// Tertiary PI is sequence-valid if 3rd PI > 2nd PI
|
1779 |
|
|
pi_3rd_seq_vld <= #`TCQ !(((pi_2nd > 0) || (pi_2nd < 4)) && pi_3rd[7]) &&
|
1780 |
|
|
(pi_3rd > pi_2nd);
|
1781 |
|
|
|
1782 |
|
|
// Quaternary PI is sequence-valid if 4th PI > 3rd PI
|
1783 |
|
|
pi_4th_seq_vld <= #`TCQ !(((pi_3rd > 0) || (pi_3rd < 4)) && pi_4th[7]) &&
|
1784 |
|
|
(pi_4th > pi_3rd);
|
1785 |
|
|
end
|
1786 |
|
|
end
|
1787 |
|
|
|
1788 |
|
|
// Latch any PI error condition.
|
1789 |
|
|
//--------------------------------------------------------------------
|
1790 |
|
|
|
1791 |
|
|
always @(posedge clk_i) begin
|
1792 |
|
|
if (reset_i) begin
|
1793 |
|
|
bad_pi_chain_o <= #`TCQ 1;
|
1794 |
|
|
end else if (eof_q1) begin
|
1795 |
|
|
bad_pi_chain_o <= #`TCQ !pi_1st_vld || !pi_2nd_vld ||
|
1796 |
|
|
!pi_3rd_vld || !pi_4th_vld ||
|
1797 |
|
|
!pi_2nd_seq_vld || !pi_3rd_seq_vld ||
|
1798 |
|
|
!pi_4th_seq_vld;
|
1799 |
|
|
end
|
1800 |
|
|
end
|
1801 |
|
|
|
1802 |
|
|
//====================================================================
|
1803 |
|
|
// Check the Turn Pointer. Must be zero for any forward-routed packet
|
1804 |
|
|
// received by an Endpoint that is not PI-0.
|
1805 |
|
|
|
1806 |
|
|
always @(posedge clk_i) begin
|
1807 |
|
|
if (reset_i) begin
|
1808 |
|
|
non_zero_turn_pointer_o <= #`TCQ 0;
|
1809 |
|
|
end else if (eval_formats_i) begin
|
1810 |
|
|
non_zero_turn_pointer_o <= #`TCQ !dir_i && !switch_mode_i &&
|
1811 |
|
|
(pi_1st != 0) && (turn_pointer_i != 0);
|
1812 |
|
|
end
|
1813 |
|
|
end
|
1814 |
|
|
|
1815 |
|
|
//====================================================================
|
1816 |
|
|
// Check the Header CRC. Path-building and multicast packets (PI-0)
|
1817 |
|
|
// have a mutable Turn Pool which must be masked out when performing
|
1818 |
|
|
// the CRC calculation. For timing purposes, both the path-build and
|
1819 |
|
|
// non-path-build CRCs are calculated and the correct one is later
|
1820 |
|
|
// chosen for comparison.
|
1821 |
|
|
|
1822 |
|
|
tlm_hcrc hcrc
|
1823 |
|
|
(.d_i (route_header_i[50:0]),
|
1824 |
|
|
.hcrc_o (header_crc_d));
|
1825 |
|
|
|
1826 |
|
|
tlm_hcrc hcrc_pb
|
1827 |
|
|
(.d_i ({route_header_i[50:32],32'b0}),
|
1828 |
|
|
.hcrc_o (header_crc_pb_d));
|
1829 |
|
|
|
1830 |
|
|
always @(posedge clk_i) begin
|
1831 |
|
|
if (reset_i) begin
|
1832 |
|
|
path_build <= #`TCQ 0;
|
1833 |
|
|
end else if (eval_formats_i) begin
|
1834 |
|
|
path_build <= #`TCQ (pi_1st == 0);
|
1835 |
|
|
end
|
1836 |
|
|
end
|
1837 |
|
|
|
1838 |
|
|
always @(posedge clk_i) begin
|
1839 |
|
|
if (reset_i) begin
|
1840 |
|
|
header_crc <= #`TCQ 0;
|
1841 |
|
|
header_crc_pb <= #`TCQ 0;
|
1842 |
|
|
end else if (eval_formats_i) begin
|
1843 |
|
|
header_crc <= #`TCQ header_crc_d;
|
1844 |
|
|
header_crc_pb <= #`TCQ header_crc_pb_d;
|
1845 |
|
|
end
|
1846 |
|
|
end
|
1847 |
|
|
|
1848 |
|
|
always @(posedge clk_i) begin
|
1849 |
|
|
if (reset_i) begin
|
1850 |
|
|
bad_header_crc_o <= #`TCQ 0;
|
1851 |
|
|
end else if (eof_q1) begin
|
1852 |
|
|
bad_header_crc_o <= #`TCQ (hcrc_i !=
|
1853 |
|
|
(path_build ? header_crc_pb : header_crc));
|
1854 |
|
|
end
|
1855 |
|
|
end
|
1856 |
|
|
|
1857 |
|
|
//====================================================================
|
1858 |
|
|
// Check whether we've received an packet intended for an unsupported
|
1859 |
|
|
// OVC or MVC.
|
1860 |
|
|
|
1861 |
|
|
always @(posedge clk_i) begin
|
1862 |
|
|
if (reset_i) begin
|
1863 |
|
|
unsup_ovc_o <= #`TCQ 0;
|
1864 |
|
|
end else if (eval_formats_i) begin
|
1865 |
|
|
unsup_ovc_o <= #`TCQ oo_i && BVC;
|
1866 |
|
|
end
|
1867 |
|
|
end
|
1868 |
|
|
|
1869 |
|
|
always @(posedge clk_i) begin
|
1870 |
|
|
if (reset_i) begin
|
1871 |
|
|
unsup_mvc_o <= #`TCQ 0;
|
1872 |
|
|
end else if (eof_q1) begin
|
1873 |
|
|
unsup_mvc_o <= #`TCQ primary_pi0 && (pi_2nd != 0) && !MVC;
|
1874 |
|
|
end
|
1875 |
|
|
end
|
1876 |
|
|
|
1877 |
|
|
//====================================================================
|
1878 |
|
|
// Drop packets depending on link state. In DL_Inactive or DL_init,
|
1879 |
|
|
// only PI-0:0 packets are allowed through. In DL_Protected, only
|
1880 |
|
|
// PI-0:0, PI-4 and PI-5 packets are allowed.
|
1881 |
|
|
|
1882 |
|
|
localparam [1:0] DL_INACTIVE = 2'b00;
|
1883 |
|
|
localparam [1:0] DL_INIT = 2'b01;
|
1884 |
|
|
localparam [1:0] DL_PROTECTED = 2'b10;
|
1885 |
|
|
localparam [1:0] DL_ACTIVE = 2'b11;
|
1886 |
|
|
|
1887 |
|
|
// Only change link state in between packets.
|
1888 |
|
|
|
1889 |
|
|
always @(posedge clk_i) begin
|
1890 |
|
|
if (reset_i) begin
|
1891 |
|
|
packet_ip <= #`TCQ 0;
|
1892 |
|
|
end else if (sof_i) begin
|
1893 |
|
|
packet_ip <= #`TCQ 1;
|
1894 |
|
|
end else if (eof_i) begin
|
1895 |
|
|
packet_ip <= #`TCQ 0;
|
1896 |
|
|
end
|
1897 |
|
|
end
|
1898 |
|
|
|
1899 |
|
|
always @(posedge clk_i) begin
|
1900 |
|
|
if (reset_i) begin
|
1901 |
|
|
lnk_state_d <= #`TCQ DL_INACTIVE;
|
1902 |
|
|
end else if (lnk_state_src_rdy_i) begin
|
1903 |
|
|
lnk_state_d <= #`TCQ lnk_state_i;
|
1904 |
|
|
end
|
1905 |
|
|
end
|
1906 |
|
|
|
1907 |
|
|
always @(posedge clk_i) begin
|
1908 |
|
|
if (reset_i) begin
|
1909 |
|
|
lnk_state <= #`TCQ DL_INACTIVE;
|
1910 |
|
|
end else if (!packet_ip) begin
|
1911 |
|
|
lnk_state <= #`TCQ lnk_state_d;
|
1912 |
|
|
end
|
1913 |
|
|
end
|
1914 |
|
|
|
1915 |
|
|
// Signal packet drop
|
1916 |
|
|
|
1917 |
|
|
always @(posedge clk_i) begin
|
1918 |
|
|
if (reset_i) begin
|
1919 |
|
|
packet_keep <= #`TCQ 1'b1;
|
1920 |
|
|
end else if (eof_q1) begin
|
1921 |
|
|
case (lnk_state)
|
1922 |
|
|
DL_INACTIVE: packet_keep <= #`TCQ (pi_1st == 0) && (pi_2nd == 0);
|
1923 |
|
|
DL_INIT: packet_keep <= #`TCQ (pi_1st == 0) && (pi_2nd == 0);
|
1924 |
|
|
DL_PROTECTED: packet_keep <= #`TCQ ((pi_1st == 0) && (pi_2nd == 0)) ||
|
1925 |
|
|
(pi_1st == 4) || (pi_1st == 5);
|
1926 |
|
|
DL_ACTIVE: packet_keep <= #`TCQ 1'b1;
|
1927 |
|
|
endcase
|
1928 |
|
|
end
|
1929 |
|
|
end
|
1930 |
|
|
|
1931 |
|
|
assign filter_drop_o = !packet_keep;
|
1932 |
|
|
|
1933 |
|
|
//====================================================================
|
1934 |
|
|
// Flag PI-0:0 and PI-4 packets as config. For PI-4, make sure the
|
1935 |
|
|
// config address is in the CMM's range.
|
1936 |
|
|
|
1937 |
|
|
always @(posedge clk_i) begin
|
1938 |
|
|
if (reset_i) begin
|
1939 |
|
|
pi4_ap0 <= #`TCQ 1'b0;
|
1940 |
|
|
pi4_ap1 <= #`TCQ 1'b0;
|
1941 |
|
|
end else if (load_aperture_i) begin
|
1942 |
|
|
pi4_ap0 <= #`TCQ primary_pi4 && (aperture_i == 0);
|
1943 |
|
|
pi4_ap1 <= #`TCQ primary_pi4 && (aperture_i == 1);
|
1944 |
|
|
end
|
1945 |
|
|
end
|
1946 |
|
|
|
1947 |
|
|
always @(posedge clk_i) begin
|
1948 |
|
|
if (reset_i) begin
|
1949 |
|
|
in_ap0_range <= #`TCQ 0;
|
1950 |
|
|
in_ap1_range <= #`TCQ 0;
|
1951 |
|
|
end else if (load_offset_i) begin
|
1952 |
|
|
in_ap0_range <= #`TCQ (offset_i < cmm_ap0_space_end_i);
|
1953 |
|
|
in_ap1_range <= #`TCQ (offset_i >= cmm_ap1_space_start_i) &&
|
1954 |
|
|
(offset_i < cmm_ap1_space_end_i);
|
1955 |
|
|
end
|
1956 |
|
|
end
|
1957 |
|
|
|
1958 |
|
|
always @(posedge clk_i) begin
|
1959 |
|
|
if (reset_i) begin
|
1960 |
|
|
load_offset_q <= #`TCQ 0;
|
1961 |
|
|
end else begin
|
1962 |
|
|
load_offset_q <= #`TCQ load_offset_i;
|
1963 |
|
|
end
|
1964 |
|
|
end
|
1965 |
|
|
|
1966 |
|
|
// The packet goes to the CMM if:
|
1967 |
|
|
// 1. It is PI-0:0 and we are not a Fabric Manager, OR
|
1968 |
|
|
// 2. It is PI-4 Aperture 0, and in the Aperture 0 address range, OR
|
1969 |
|
|
// 3. It is PI-4 Aperture 1, and in the Aperture 1 address range.
|
1970 |
|
|
|
1971 |
|
|
always @(posedge clk_i) begin
|
1972 |
|
|
if (reset_i) begin
|
1973 |
|
|
cfg_o <= #`TCQ 0;
|
1974 |
|
|
end else if (load_offset_q) begin
|
1975 |
|
|
cfg_o <= #`TCQ (primary_pi0 && secondary_pi0 &&
|
1976 |
|
|
!fabric_manager_mode_i) ||
|
1977 |
|
|
(pi4_ap0 && in_ap0_range) ||
|
1978 |
|
|
(pi4_ap1 && in_ap1_range);
|
1979 |
|
|
end
|
1980 |
|
|
end
|
1981 |
|
|
`endif
|
1982 |
|
|
|
1983 |
|
|
//====================================================================
|
1984 |
|
|
// delay of control signals
|
1985 |
|
|
|
1986 |
|
|
always @(posedge clk_i) begin
|
1987 |
|
|
if (reset_i) begin
|
1988 |
|
|
`ifdef PCIE
|
1989 |
|
|
sof_q1 <= #`TCQ 0;
|
1990 |
|
|
sof_q2 <= #`TCQ 0;
|
1991 |
|
|
sof_q3 <= #`TCQ 0;
|
1992 |
|
|
sof_q4 <= #`TCQ 0;
|
1993 |
|
|
eof_q2 <= #`TCQ 0;
|
1994 |
|
|
eof_q3 <= #`TCQ 0;
|
1995 |
|
|
eval_formats_q <= #`TCQ 0;
|
1996 |
|
|
eval_formats_q2 <= #`TCQ 0;
|
1997 |
|
|
`endif
|
1998 |
|
|
eof_q1 <= #`TCQ 0;
|
1999 |
|
|
end else begin
|
2000 |
|
|
`ifdef PCIE
|
2001 |
|
|
sof_q1 <= #`TCQ sof_i;
|
2002 |
|
|
sof_q2 <= #`TCQ sof_q1;
|
2003 |
|
|
sof_q3 <= #`TCQ sof_q2;
|
2004 |
|
|
sof_q4 <= #`TCQ sof_q3;
|
2005 |
|
|
eof_q2 <= #`TCQ eof_q1;
|
2006 |
|
|
eof_q3 <= #`TCQ eof_q2;
|
2007 |
|
|
eval_formats_q <= #`TCQ eval_formats_i;
|
2008 |
|
|
eval_formats_q2 <= #`TCQ eval_formats_q;
|
2009 |
|
|
`endif
|
2010 |
|
|
eof_q1 <= #`TCQ eof_i;
|
2011 |
|
|
end
|
2012 |
|
|
end
|
2013 |
|
|
endmodule
|