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_artix7/] [cl_a7pcie_x4_axi_basic_rx_pipeline.vhd] - Blame information for rev 46

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 46 dsmv
-------------------------------------------------------------------------------
2
--
3
-- (c) Copyright 2010-2011 Xilinx, Inc. All rights reserved.
4
--
5
-- This file contains confidential and proprietary information
6
-- of Xilinx, Inc. and is protected under U.S. and
7
-- international copyright and other intellectual property
8
-- laws.
9
--
10
-- DISCLAIMER
11
-- This disclaimer is not a license and does not grant any
12
-- rights to the materials distributed herewith. Except as
13
-- otherwise provided in a valid license issued to you by
14
-- Xilinx, and to the maximum extent permitted by applicable
15
-- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
16
-- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
17
-- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
18
-- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
19
-- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
20
-- (2) Xilinx shall not be liable (whether in contract or tort,
21
-- including negligence, or under any other theory of
22
-- liability) for any loss or damage of any kind or nature
23
-- related to, arising under or in connection with these
24
-- materials, including for any direct, or any indirect,
25
-- special, incidental, or consequential loss or damage
26
-- (including loss of data, profits, goodwill, or any type of
27
-- loss or damage suffered as a result of any action brought
28
-- by a third party) even if such damage or loss was
29
-- reasonably foreseeable or Xilinx had been advised of the
30
-- possibility of the same.
31
--
32
-- CRITICAL APPLICATIONS
33
-- Xilinx products are not designed or intended to be fail-
34
-- safe, or for use in any application requiring fail-safe
35
-- performance, such as life-support or safety devices or
36
-- systems, Class III medical devices, nuclear facilities,
37
-- applications related to the deployment of airbags, or any
38
-- other applications that could lead to death, personal
39
-- injury, or severe property or environmental damage
40
-- (individually and collectively, "Critical
41
-- Applications"). Customer assumes the sole risk and
42
-- liability of any use of Xilinx products in Critical
43
-- Applications, subject only to applicable laws and
44
-- regulations governing limitations on product liability.
45
--
46
-- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
47
-- PART OF THIS FILE AT ALL TIMES.
48
--
49
-------------------------------------------------------------------------------
50
-- Project    : Series-7 Integrated Block for PCI Express
51
-- File       : cl_a7pcie_x4_axi_basic_rx_pipeline.vhd
52
-- Version    : 1.9
53
--
54
-- Description:
55
--  TRN to AXI RX pipeline. Converts received data from TRN protocol to AXI.
56
--
57
--  Notes:
58
--  Optional notes section.
59
--
60
--  Hierarchical:
61
--    axi_basic_top
62
--      axi_basic_rx
63
--        axi_basic_rx_pipeline
64
--
65
-------------------------------------------------------------------------------
66
-- Library Declarations
67
--------------------------------------------------------------------------------
68
 
69
LIBRARY ieee;
70
  USE ieee.std_logic_1164.all;
71
  USE ieee.std_logic_unsigned.all;
72
 
73
 
74
ENTITY cl_a7pcie_x4_axi_basic_rx_pipeline IS
75
  GENERIC (
76
     C_DATA_WIDTH            : INTEGER := 128;           -- RX/TX interface data width
77
     C_FAMILY                : STRING := "X7";           -- Targeted FPGA family
78
     TCQ                     : INTEGER := 1;             -- Clock to Q time
79
 
80
     C_REM_WIDTH             : INTEGER := 1              -- trem/rrem width
81
  );
82
  PORT (
83
 
84
     -- AXI RX
85
     -------------
86
     M_AXIS_RX_TDATA         : OUT STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) ;       -- RX data to user
87
     M_AXIS_RX_TVALID        : OUT STD_LOGIC                                   ;       -- RX data is valid
88
     M_AXIS_RX_TREADY        : IN STD_LOGIC                                    ;       -- RX ready for data
89
     m_axis_rx_tkeep         : OUT STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0) ;       -- RX strobe byte enables
90
     M_AXIS_RX_TLAST         : OUT STD_LOGIC                                   ;       -- RX data is last
91
     M_AXIS_RX_TUSER         : OUT STD_LOGIC_VECTOR(21 DOWNTO 0)               ;       -- RX user signals
92
 
93
      -- TRN RX
94
      -------------
95
     TRN_RD                  : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  ;       -- RX data from block
96
     TRN_RSOF                : IN STD_LOGIC                                    ;       -- RX start of packet
97
     TRN_REOF                : IN STD_LOGIC                                    ;       -- RX end of packet
98
     TRN_RSRC_RDY            : IN STD_LOGIC                                    ;       -- RX source ready
99
     TRN_RDST_RDY            : OUT STD_LOGIC                                   ;       -- RX destination ready
100
     TRN_RSRC_DSC            : IN STD_LOGIC                                    ;       -- RX source discontinue
101
     TRN_RREM                : IN STD_LOGIC_VECTOR(C_REM_WIDTH - 1 DOWNTO 0)   ;       -- RX remainder
102
     TRN_RERRFWD             : IN STD_LOGIC                                    ;       -- RX error forward
103
     TRN_RBAR_HIT            : IN STD_LOGIC_VECTOR(6 DOWNTO 0)                 ;       -- RX BAR hit
104
     TRN_RECRC_ERR           : IN STD_LOGIC                                    ;       -- RX ECRC error
105
 
106
     -- Null Inputs
107
     -------------
108
     NULL_RX_TVALID          : IN STD_LOGIC                                    ;       -- NULL generated tvalid
109
     NULL_RX_TLAST           : IN STD_LOGIC                                    ;       -- NULL generated tlast
110
     NULL_RX_tkeep           : IN STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0)  ;       -- NULL generated tkeep
111
     NULL_RDST_RDY           : IN STD_LOGIC                                    ;       -- NULL generated rdst_rdy
112
     NULL_IS_EOF             : IN STD_LOGIC_VECTOR(4 DOWNTO 0)                 ;       -- NULL generated is_eof
113
 
114
     -- System
115
     -------------
116
     NP_COUNTER              : OUT STD_LOGIC_VECTOR(2 DOWNTO 0)                ;       -- Non-posted counter
117
     USER_CLK                : IN STD_LOGIC                                    ;       -- user clock from block
118
     USER_RST                : IN STD_LOGIC                                            -- user reset from block
119
  );
120
END cl_a7pcie_x4_axi_basic_rx_pipeline;
121
 
122
ARCHITECTURE trans OF cl_a7pcie_x4_axi_basic_rx_pipeline IS
123
 
124
  SIGNAL is_sof                 : STD_LOGIC_VECTOR(4 DOWNTO 0);
125
  SIGNAL is_sof_prev            : STD_LOGIC_VECTOR(4 DOWNTO 0);
126
 
127
  SIGNAL is_eof                 : STD_LOGIC_VECTOR(4 DOWNTO 0);
128
  SIGNAL is_eof_prev            : STD_LOGIC_VECTOR(4 DOWNTO 0);
129
 
130
  SIGNAL reg_tkeep              : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
131
  SIGNAL tkeep                  : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
132
  SIGNAL tkeep_prev             : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
133
 
134
  SIGNAL reg_tlast              : STD_LOGIC;
135
  SIGNAL rsrc_rdy_filtered      : STD_LOGIC;
136
 
137
  SIGNAL trn_rd_DW_swapped      : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
138
  SIGNAL trn_rd_prev            : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
139
 
140
  SIGNAL data_hold              : STD_LOGIC;
141
  SIGNAL data_prev              : STD_LOGIC;
142
 
143
  SIGNAL trn_reof_prev          : STD_LOGIC;
144
  SIGNAL trn_rrem_prev          : STD_LOGIC_VECTOR(C_REM_WIDTH - 1 DOWNTO 0);
145
  SIGNAL trn_rsrc_rdy_prev      : STD_LOGIC;
146
  SIGNAL trn_rsrc_dsc_prev      : STD_LOGIC;
147
  SIGNAL trn_rsof_prev          : STD_LOGIC;
148
  SIGNAL trn_rbar_hit_prev      : STD_LOGIC_VECTOR(6 DOWNTO 0);
149
  SIGNAL trn_rerrfwd_prev       : STD_LOGIC;
150
  SIGNAL trn_recrc_err_prev     : STD_LOGIC;
151
 
152
  -- Null packet handling signals
153
  SIGNAL null_mux_sel           : STD_LOGIC;
154
  SIGNAL trn_in_packet          : STD_LOGIC;
155
  SIGNAL dsc_flag               : STD_LOGIC;
156
  SIGNAL dsc_detect             : STD_LOGIC;
157
  SIGNAL reg_dsc_detect         : STD_LOGIC;
158
  SIGNAL trn_rsrc_dsc_d         : STD_LOGIC;
159
 
160
  -- Declare intermediate signals for referenced outputs
161
  SIGNAL m_axis_rx_tdata_xhdl0  : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
162
  SIGNAL m_axis_rx_tvalid_xhdl2 : STD_LOGIC;
163
  SIGNAL m_axis_rx_tuser_xhdl1  : STD_LOGIC_VECTOR(21 DOWNTO 0);
164
  SIGNAL trn_rdst_rdy_xhdl4     : STD_LOGIC;
165
  SIGNAL mrd_lower              : STD_LOGIC;
166
  SIGNAL mrd_lk_lower           : STD_LOGIC;
167
  SIGNAL io_rdwr_lower          : STD_LOGIC;
168
  SIGNAL cfg_rdwr_lower         : STD_LOGIC;
169
  SIGNAL atomic_lower           : STD_LOGIC;
170
  SIGNAL np_pkt_lower           : STD_LOGIC;
171
  SIGNAL mrd_upper              : STD_LOGIC;
172
  SIGNAL mrd_lk_upper           : STD_LOGIC;
173
  SIGNAL io_rdwr_upper          : STD_LOGIC;
174
  SIGNAL cfg_rdwr_upper         : STD_LOGIC;
175
  SIGNAL atomic_upper           : STD_LOGIC;
176
  SIGNAL np_pkt_upper           : STD_LOGIC;
177
  SIGNAL pkt_accepted           : STD_LOGIC;
178
  SIGNAL reg_np_counter         : STD_LOGIC_VECTOR(2 DOWNTO 0);
179
 
180
BEGIN
181
  -- Drive referenced outputs
182
  M_AXIS_RX_TDATA     <= m_axis_rx_tdata_xhdl0;
183
  M_AXIS_RX_TVALID    <= m_axis_rx_tvalid_xhdl2;
184
  M_AXIS_RX_TUSER     <= m_axis_rx_tuser_xhdl1;
185
  TRN_RDST_RDY        <= trn_rdst_rdy_xhdl4;
186
 
187
  -- Create "filtered" version of rsrc_rdy, where discontinued SOFs are removed
188
  rsrc_rdy_filtered <= trn_rsrc_rdy AND (trn_in_packet OR (trn_rsof AND NOT trn_rsrc_dsc));
189
 
190
  --------------------------------------------------------------------------------
191
  -- Previous value buffer                                                      --
192
  -- ---------------------                                                      --
193
  -- We are inserting a pipeline stage in between TRN and AXI, which causes     --
194
  -- some issues with handshaking signals m_axis_rx_tready/trn_rdst_rdy. The    --
195
  -- added cycle of latency in the path causes the user design to fall behind   --
196
  -- the TRN interface whenever it throttles.                                   --
197
  --                                                                            --
198
  -- To avoid loss of data, we must keep the previous value of all trn_r*       --
199
  -- signals in case the user throttles.                                        --
200
  --------------------------------------------------------------------------------
201
  PROCESS (USER_CLK)
202
  BEGIN
203
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
204
      IF (USER_RST = '1') THEN
205
        trn_rd_prev        <=  (others => '0')AFTER 1 ps;
206
        trn_rsof_prev      <=  '0'  AFTER (TCQ)*1 ps;
207
        trn_rrem_prev      <=  (others => '0') AFTER (TCQ)*1 ps;
208
        trn_rsrc_rdy_prev  <=  '0' AFTER 1 ps;
209
        trn_rbar_hit_prev  <=  (others => '0') AFTER 1 ps;
210
        trn_rerrfwd_prev   <=  '0' AFTER 1 ps;
211
        trn_recrc_err_prev <=  '0' AFTER 1 ps;
212
        trn_reof_prev      <=  '0' AFTER 1 ps;
213
        trn_rsrc_dsc_prev  <=  '0' AFTER 1 ps;
214
      ELSE
215
              -- prev buffer works by checking trn_rdst_rdy. When trn_rdst_rdy is
216
              -- asserted, a new value is present on the interface.
217
 
218
        IF (trn_rdst_rdy_xhdl4 = '1') THEN
219
          trn_rd_prev        <= trn_rd_DW_swapped  AFTER (TCQ)*1 ps;
220
          trn_rsof_prev      <= TRN_RSOF           AFTER (TCQ)*1 ps;
221
          trn_rrem_prev      <= TRN_RREM           AFTER (TCQ)*1 ps;
222
          trn_rbar_hit_prev  <= TRN_RBAR_HIT       AFTER (TCQ)*1 ps;
223
          trn_rerrfwd_prev   <= TRN_RERRFWD        AFTER (TCQ)*1 ps;
224
          trn_recrc_err_prev <= TRN_RECRC_ERR      AFTER (TCQ)*1 ps;
225
          trn_rsrc_rdy_prev  <= rsrc_rdy_filtered  AFTER (TCQ)*1 ps;
226
          trn_reof_prev      <= trn_reof           AFTER (TCQ)*1 ps;
227
          trn_rsrc_dsc_prev  <= TRN_RSRC_DSC OR dsc_flag AFTER (TCQ)*1 ps;
228
        END IF;
229
      END IF;
230
    END IF;
231
  END PROCESS;
232
 
233
  --------------------------------------------------------------------------------
234
  -- Create TDATA
235
  ------------------------------------------------------------------------------
236
  -- Convert TRN data format to AXI data format. AXI is DWORD swapped from TRN
237
  -- 128-bit:                 64-bit:                  32-bit:
238
  -- TRN DW0 maps to AXI DW3  TRN DW0 maps to AXI DW1  TNR DW0 maps to AXI DW0
239
  -- TRN DW1 maps to AXI DW2  TRN DW1 maps to AXI DW0
240
  -- TRN DW2 maps to AXI DW1
241
  -- TRN DW3 maps to AXI DW0
242
 
243
  xhdl7 : IF (C_DATA_WIDTH = 128) GENERATE
244
    trn_rd_DW_swapped <= (TRN_RD(31 DOWNTO 0) & TRN_RD(63 DOWNTO 32) & TRN_RD(95 DOWNTO 64) & TRN_RD(127 DOWNTO 96));
245
  END GENERATE;
246
 
247
  xhdl9 : IF (C_DATA_WIDTH = 64) GENERATE
248
    trn_rd_DW_swapped <= (TRN_RD(31 DOWNTO 0) & TRN_RD(63 DOWNTO 32));
249
  END GENERATE;
250
 
251
  xhdl10 : IF (NOT(C_DATA_WIDTH = 64) AND NOT(C_DATA_WIDTH = 128)) GENERATE
252
    trn_rd_DW_swapped <= TRN_RD;
253
  END GENERATE;
254
 
255
  -- Create special buffer which locks in the proper value of TDATA depending
256
  -- on whether the user is throttling or not. This buffer has three states:
257
  --
258
  --   HOLD state: TDATA maintains its current value
259
  --                   - the user has throttled the PCIe block
260
  --   PREVIOUS state: the buffer provides the previous value on trn_rd
261
  --                   - the user has finished throttling, and is a little behind
262
  --                     the PCIe block
263
  --   CURRENT state: the buffer passes the current value on trn_rd
264
  --                   - the user is caught up and ready to receive the latest
265
  --                     data from the PCIe block
266
 
267
  PROCESS (USER_CLK)
268
  BEGIN
269
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
270
      IF (USER_RST = '1') THEN
271
        m_axis_rx_tdata_xhdl0 <= (OTHERS=>'0') AFTER (TCQ)*1 ps;
272
      ELSE
273
        IF ((NOT(data_hold)) = '1') THEN
274
           -- PREVIOUS state
275
          IF (data_prev = '1') THEN
276
            m_axis_rx_tdata_xhdl0 <= trn_rd_prev  AFTER (TCQ)*1 ps;
277
          -- CURRENT state
278
          ELSE
279
            m_axis_rx_tdata_xhdl0 <= trn_rd_DW_swapped  AFTER (TCQ)*1 ps;
280
          END IF;
281
        END IF;
282
        -- else HOLD state
283
      END IF;
284
    END IF;
285
  END PROCESS;
286
 
287
  -- Logic to instruct pipeline to hold its value
288
  data_hold <= (NOT(M_AXIS_RX_TREADY) AND m_axis_rx_tvalid_xhdl2);
289
 
290
  -- Logic to instruct pipeline to use previous bus values. Always use previous value after holding a value.
291
  PROCESS (USER_CLK)
292
  BEGIN
293
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
294
      IF (USER_RST = '1') THEN
295
        data_prev <= '0'  AFTER (TCQ)*1 ps;
296
      ELSE
297
        data_prev <= data_hold  AFTER (TCQ)*1 ps;
298
      END IF;
299
    END IF;
300
  END PROCESS;
301
 
302
  ------------------------------------------------------------------------------
303
  -- Create TVALID, TLAST, tkeep, TUSER
304
  -- -----------------------------------
305
  -- Use the same strategy for these signals as for TDATA, except here we need
306
  -- an extra provision for null packets.
307
  ------------------------------------------------------------------------------
308
  PROCESS (USER_CLK)
309
  BEGIN
310
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
311
      IF (USER_RST = '1') THEN
312
        m_axis_rx_tvalid_xhdl2 <= '0'  AFTER (TCQ)*1 ps;
313
        reg_tlast <= '0' AFTER (TCQ)*1 ps;
314
        reg_tkeep <= (others => '1') AFTER (TCQ)*1 ps;
315
        m_axis_rx_tuser_xhdl1 <= (others => '0')  AFTER (TCQ)*1 ps;
316
      ELSE
317
        IF (data_hold = '0') THEN
318
          -- If in a null packet, use null generated value
319
          IF (null_mux_sel = '1') THEN
320
            m_axis_rx_tvalid_xhdl2 <= NULL_RX_TVALID  AFTER (TCQ)*1 ps;
321
            reg_tlast <= NULL_RX_TLAST AFTER (TCQ)*1 ps;
322
            reg_tkeep <= NULL_RX_tkeep AFTER (TCQ)*1 ps;
323
            m_axis_rx_tuser_xhdl1 <= (NULL_IS_EOF & "00000000000000000") AFTER (TCQ)*1 ps;
324
 
325
          -- PREVIOUS state
326
          ELSIF (data_prev = '1') THEN
327
            m_axis_rx_tvalid_xhdl2 <= (trn_rsrc_rdy_prev  OR dsc_flag) AFTER (TCQ)*1 ps;
328
            reg_tlast <= trn_reof_prev AFTER (TCQ)*1 ps;
329
            reg_tkeep <= tkeep_prev AFTER (TCQ)*1 ps;
330
            m_axis_rx_tuser_xhdl1 <= (is_eof_prev & "00" & is_sof_prev & '0' & trn_rbar_hit_prev &
331
                                      trn_rerrfwd_prev & trn_recrc_err_prev) AFTER (TCQ)*1 ps;
332
            -- TUSER bits [21:17] & TUSER bits [16:15] & TUSER bits [14:10] & TUSER bits [9] &
333
            -- TUSER bits [8:2] & TUSER bit  [1] & TUSER bit  [0]
334
 
335
          -- CURRENT state
336
          ELSE
337
 
338
            m_axis_rx_tvalid_xhdl2 <= (rsrc_rdy_filtered OR dsc_flag) AFTER (TCQ)*1 ps;
339
            reg_tlast <= TRN_REOF AFTER (TCQ)*1 ps;
340
            reg_tkeep <= tkeep AFTER (TCQ)*1 ps;
341
            m_axis_rx_tuser_xhdl1 <= (is_eof & "00" & is_sof & '0' & trn_rbar_hit & TRN_RERRFWD & TRN_RECRC_ERR) AFTER (TCQ)*1 ps;
342
            -- TUSER bits [21:17] & TUSER bits [16:15] & TUSER bits [14:10] & TUSER bits [9] &
343
            -- TUSER bits [8:2] & TUSER bit  [1] & TUSER bit  [0]
344
          END IF;
345
        END IF;
346
        -- else HOLD state
347
      END IF;
348
    END IF;
349
  END PROCESS;
350
 
351
  -- Hook up TLAST and tkeep depending on interface width
352
  xhdl11 : IF (C_DATA_WIDTH = 128) GENERATE
353
    -- For 128-bit interface, don't pass TLAST and tkeep to user (is_eof and is_data passed to user instead).
354
    -- reg_tlast is still used internally.
355
    M_AXIS_RX_TLAST <= '0';
356
    m_axis_rx_tkeep <= (others => '1');
357
  END GENERATE;
358
 
359
 
360
  -- For 64/32-bit interface, pass TLAST to user.
361
  xhdl12 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
362
    M_AXIS_RX_TLAST <= reg_tlast;
363
    m_axis_rx_tkeep <= reg_tkeep;
364
  END GENERATE;
365
 
366
  --------------------------------------------------------------------------------
367
  -- Create tkeep                                                              ---
368
  -- ------------                                                              ---
369
  -- Convert RREM to STRB. Here, we are converting the encoding method for the ---
370
  -- location of the EOF from TRN flavor (rrem) to AXI (tkeep).                ---
371
  --                                                                           ---
372
  -- NOTE: for each configuration, we need two values of tkeep, the current and---
373
  --       previous values. The need for these two values is described below.  ---
374
  --------------------------------------------------------------------------------
375
  xhdl13 : IF (C_DATA_WIDTH = 128) GENERATE
376
    -- TLAST and tkeep not used in 128-bit interface. is_sof and is_eof used instead.
377
    tkeep <= x"0000";
378
    tkeep_prev <= x"0000";
379
  END GENERATE;
380
 
381
  xhdl14 : IF (C_DATA_WIDTH /= 128) GENERATE
382
    xhdl15 : IF (C_DATA_WIDTH = 64) GENERATE
383
      -- 64-bit interface: contains 2 DWORDs per cycle, for a total of 8 bytes
384
      -- tkeep has only two possible values here, 0xFF or 0x0F
385
      tkeep      <= x"FF" WHEN (TRN_RREM = "1") ELSE x"0F";
386
      tkeep_prev <= x"FF" WHEN (trn_rrem_prev = "1" ) ELSE x"0F";
387
    END GENERATE;
388
    xhdl16 : IF (C_DATA_WIDTH /= 64) GENERATE
389
      -- 32-bit interface: contains 1 DWORD per cycle, for a total of 4 bytes
390
      -- tkeep is always 0xF in this case, due to the nature of the PCIe block
391
      tkeep      <= "1111";
392
      tkeep_prev <= "1111";
393
    END GENERATE;
394
  END GENERATE;
395
 
396
  ------------------------------------------------------------------------------//
397
  -- Create is_sof                                                              //
398
  -- -------------                                                              //
399
  -- is_sof is a signal to the user indicating the location of SOF in TDATA   . //
400
  -- Due to inherent 64-bit alignment of packets from the block, the only       //
401
  -- possible values are:                                                       //
402
  --                      Value                      Valid data widths          //
403
  --                      5'b11000 (sof @ byte 8)    128                        //
404
  --                      5'b10000 (sof @ byte 0)    128, 64, 32                //
405
  --                      5'b00000 (sof not present) 128, 64, 32                //
406
  ------------------------------------------------------------------------------//
407
  xhdl17 : IF (C_DATA_WIDTH = 128) GENERATE
408
    is_sof <= (((NOT(TRN_RSRC_DSC)) AND TRN_RSOF) & ((NOT(TRN_RREM(1))) AND TRN_RSOF ) & "000");
409
    is_sof_prev <= (((trn_rsof_prev AND (NOT(trn_rsrc_dsc_prev)))) & (trn_rsof_prev AND (NOT(trn_rrem_prev(1)))) & "000");
410
    -- bit 4:   enable bit 3:   sof @ byte 8? bit 2-0: hardwired 0
411
  END GENERATE;
412
 
413
  xhdl18 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
414
    is_sof      <= ((TRN_RSOF AND (NOT TRN_RSRC_DSC)) & "0000"); -- bit 4: enable, bits 3-0: hardwired 0
415
    is_sof_prev <= ((trn_rsof_prev AND (NOT trn_rsrc_dsc_prev)) & "0000");
416
  END GENERATE;
417
 
418
  ------------------------------------------------------------------------------//
419
  -- Create is_eof                                                              //
420
  -- -------------                                                              //
421
  -- is_eof is a signal to the user indicating the location of EOF in TDATA   . //
422
  -- Due to DWORD granularity of packets from the block, the only               //
423
  -- possible values are:                                                       //
424
  --                      Value                      Valid data widths          //
425
  --                      5'b11111 (eof @ byte 15)   128                        //
426
  --                      5'b11011 (eof @ byte 11)   128                        //
427
  --                      5'b10111 (eof @ byte 7)    128, 64                    //
428
  --                      5'b10011 (eof @ byte 3)`   128, 64, 32                //
429
  --                      5'b00011 (eof not present) 128, 64, 32                //
430
  ------------------------------------------------------------------------------//
431
  xhdl19 : IF (C_DATA_WIDTH = 128) GENERATE
432
    is_eof       <= (TRN_REOF & TRN_RREM & "11");
433
    is_eof_prev  <= (trn_reof_prev & trn_rrem_prev & "11");
434
    -- bit 4:   enable bit 3-2: encoded eof loc from block  bit 1-0: hardwired 1
435
  END GENERATE;
436
 
437
  xhdl20 : IF (C_DATA_WIDTH = 64) GENERATE
438
    is_eof       <= (TRN_REOF & '0' & TRN_RREM & "11");
439
    is_eof_prev  <= (trn_reof_prev & '0' & trn_rrem_prev & "11");
440
    -- bit 4: enable, bit 3: hardwired 0, bit 2: encoded eof loc from  block, bit 1-0: hardwired 1
441
  END GENERATE;
442
 
443
  --------------------------------------------------------------------------------
444
  xhdl20A : IF (C_DATA_WIDTH = 32) GENERATE
445
    is_eof       <= (TRN_REOF & "0011");
446
    is_eof_prev  <= (trn_reof_prev & "0011");
447
    -- bit 4: enable, bit 3: hardwired 0, bit 2: encoded eof loc from  block, bit 1-0: hardwired 1
448
  END GENERATE;
449
 
450
 
451
  -- Create trn_rdst_rdy                                                        --
452
  --------------------------------------------------------------------------------
453
  PROCESS (USER_CLK)
454
  BEGIN
455
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
456
      IF (USER_RST = '1') THEN
457
        trn_rdst_rdy_xhdl4 <= '0' AFTER (TCQ)*1 ps;
458
      ELSE
459
        -- If in a null packet, use null generated value
460
        IF (null_mux_sel = '1' AND M_AXIS_RX_TREADY = '1') THEN
461
          trn_rdst_rdy_xhdl4 <= NULL_RDST_RDY AFTER (TCQ)*1 ps;
462
        -- If a discontinue needs to be serviced, throttle the block until we are
463
        -- ready to pad out the packet
464
        ELSIF (dsc_flag = '1') THEN
465
          trn_rdst_rdy_xhdl4 <= '0' AFTER (TCQ)*1 ps;
466
        -- If in a packet, pass user back-pressure directly to block
467
        ELSIF (m_axis_rx_tvalid_xhdl2 = '1') THEN
468
          trn_rdst_rdy_xhdl4 <= M_AXIS_RX_TREADY AFTER (TCQ)*1 ps;
469
        -- If idle, default to no back-pressure. We need to default to the
470
        -- "ready to accept data" state to make sure we catch the first
471
        -- clock of data of a new packet.
472
        ELSE
473
          trn_rdst_rdy_xhdl4 <= '1' AFTER (TCQ)*1 ps;
474
        END IF;
475
      END IF;
476
    END IF;
477
  END PROCESS;
478
 
479
  ------------------------------------------------------------------------------//
480
  -- Create null_mux_sel                                                        //
481
  -- null_mux_sel is the signal used to detect a discontinue situation and      //
482
  -- mux in the null packet generated in rx_null_gen. Only mux in null data     //
483
  -- when not at the beginningof a packet. SOF discontinues do not require      //
484
  -- padding, as the whole packet is simply squashed instead.                   //
485
  ------------------------------------------------------------------------------//
486
  PROCESS (USER_CLK)
487
  BEGIN
488
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
489
      IF (USER_RST = '1') THEN
490
        null_mux_sel <= '0' AFTER (TCQ)*1 ps;
491
      ELSE
492
        -- NULL packet done
493
        IF (null_mux_sel = '1' AND NULL_RX_TLAST = '1' AND M_AXIS_RX_TREADY = '1') THEN
494
          null_mux_sel <= '0' AFTER (TCQ)*1 ps;
495
        -- Discontinue detected and we're in packet, so switch to NULL packet
496
        ELSIF (dsc_flag = '1' AND data_hold = '0') THEN
497
          null_mux_sel <= '1' AFTER (TCQ)*1 ps;
498
        END IF;
499
      END IF;
500
    END IF;
501
  END PROCESS;
502
 
503
  ------------------------------------------------------------------------------//
504
  -- Create discontinue tracking signals                                        //
505
  ------------------------------------------------------------------------------//
506
  -- Create signal trn_in_packet, which is needed to validate trn_rsrc_dsc. We
507
  -- should ignore trn_rsrc_dsc when it's asserted out-of-packet.
508
  PROCESS (USER_CLK)
509
  BEGIN
510
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
511
      IF (USER_RST = '1') THEN
512
        trn_in_packet <= '0' AFTER (TCQ)*1 ps;
513
      ELSE
514
        IF ((TRN_RSOF = '1') AND (NOT(TRN_REOF = '1')) AND rsrc_rdy_filtered = '1' AND trn_rdst_rdy_xhdl4 = '1') THEN
515
          trn_in_packet <= '1' AFTER (TCQ)*1 ps;
516
        ELSIF (TRN_RSRC_DSC = '1') THEN
517
          trn_in_packet <= '0' AFTER (TCQ)*1 ps;
518
        ELSIF (TRN_REOF= '1' AND (NOT(TRN_RSOF= '1')) AND TRN_RSRC_RDY = '1' AND trn_rdst_rdy_xhdl4 = '1') THEN
519
          trn_in_packet <= '0';
520
        END IF;
521
      END IF;
522
    END IF;
523
  END PROCESS;
524
 
525
  -- Create dsc_flag, which identifies and stores mid-packet discontinues that
526
  -- require null packet padding. This signal is edge sensitive to trn_rsrc_dsc,
527
  -- to make sure we don't service the same dsc twice in the event that
528
  -- trn_rsrc_dsc stays asserted for longer than it takes to pad out the packet.
529
 
530
  dsc_detect <= TRN_RSRC_DSC and (not(trn_rsrc_dsc_d)) and trn_in_packet and ((not(TRN_RSOF)) or TRN_REOF) and
531
                (not(trn_rdst_rdy_xhdl4 and TRN_REOF));
532
 
533
  PROCESS (USER_CLK,USER_RST)
534
  BEGIN
535
    IF (USER_CLk'EVENT AND USER_CLK = '1') THEN
536
      IF (USER_RST = '1') THEN
537
        reg_dsc_detect <= '0' AFTER (TCQ)*1 ps;
538
        trn_rsrc_dsc_d <= '0' AFTER (TCQ)*1 ps;
539
      ELSE
540
        IF (dsc_detect = '1') THEN
541
          reg_dsc_detect <= '1' AFTER (TCQ)*1 ps;
542
        ELSIF (null_mux_sel = '1') THEN
543
          reg_dsc_detect <= '0' AFTER (TCQ)*1 ps;
544
        END IF;
545
 
546
        trn_rsrc_dsc_d <= TRN_RSRC_DSC AFTER (TCQ)*1 ps;
547
      END IF;
548
    END IF;
549
  END PROCESS;
550
 
551
  dsc_flag <= dsc_detect OR reg_dsc_detect;
552
 
553
  --------------------------------------------------------------------------------
554
  -- Create np_counter (V6 128-bit only). This counter tells the V6 128-bit     --
555
  -- interface core how many NP packets have left the RX pipeline. The V6       --
556
  -- 128-bit interface uses this count to perform rnp_ok modulation.            --
557
  --------------------------------------------------------------------------------
558
 
559
  xhdl21 : IF ((C_FAMILY = "V6") AND (C_DATA_WIDTH = 128)) GENERATE
560
    -- Look for NP packets beginning on lower (i.e. unaligned) start
561
    mrd_lower      <= '1' WHEN (m_axis_rx_tdata_xhdl0(92 DOWNTO 88) = "00000" AND m_axis_rx_tdata_xhdl0(94) = '0') ELSE '0';
562
    mrd_lk_lower   <= '1' WHEN (m_axis_rx_tdata_xhdl0(92 DOWNTO 88) = "00001") ELSE '0';
563
    io_rdwr_lower  <= '1' WHEN (m_axis_rx_tdata_xhdl0(92 DOWNTO 88) = "00010") ELSE '0';
564
    cfg_rdwr_lower <= '1' WHEN (m_axis_rx_tdata_xhdl0(92 DOWNTO 89) = "0010") ELSE '0';
565
    atomic_lower   <= '1' WHEN (m_axis_rx_tdata_xhdl0(91 DOWNTO 90) = "11" AND m_axis_rx_tdata_xhdl0(94) = '1') ELSE '0';
566
 
567
    np_pkt_lower <= '1' WHEN ((mrd_lower = '1'      OR
568
                               mrd_lk_lower = '1'   OR
569
                               io_rdwr_lower = '1'  OR
570
                               cfg_rdwr_lower = '1' OR
571
                               atomic_lower = '1') AND m_axis_rx_tuser_xhdl1(13) = '1') ELSE '0';
572
 
573
    -- Look for NP packets beginning on upper (i.e. aligned) start
574
    mrd_upper      <= '1' WHEN (m_axis_rx_tdata_xhdl0(28 DOWNTO 24) = "00000" AND m_axis_rx_tdata_xhdl0(30) = '0') ELSE '0';
575
    mrd_lk_upper   <= '1' WHEN (m_axis_rx_tdata_xhdl0(28 DOWNTO 24) = "00001") ELSE '0';
576
    io_rdwr_upper  <= '1' WHEN (m_axis_rx_tdata_xhdl0(28 DOWNTO 24) = "00010") ELSE '0';
577
    cfg_rdwr_upper <= '1' WHEN (m_axis_rx_tdata_xhdl0(28 DOWNTO 25) = "0010") ELSE '0';
578
    atomic_upper   <= '1' WHEN (m_axis_rx_tdata_xhdl0(27 DOWNTO 26) = "11" AND m_axis_rx_tdata_xhdl0(30) = '1') ELSE '0';
579
 
580
    np_pkt_upper <= '1' WHEN ((mrd_upper = '1'      OR
581
                               mrd_lk_upper = '1'   OR
582
                               io_rdwr_upper = '1'  OR
583
                               cfg_rdwr_upper = '1' OR
584
                               atomic_upper = '1') AND m_axis_rx_tuser_xhdl1(13) = '0') ELSE '0';
585
 
586
    pkt_accepted <= '1' WHEN (m_axis_rx_tuser_xhdl1(14) = '1' AND M_AXIS_RX_TREADY = '1' AND m_axis_rx_tvalid_xhdl2 = '1') ELSE '0';
587
 
588
    -- Increment counter whenever an NP packet leaves the RX pipeline
589
    PROCESS (USER_CLK)
590
    BEGIN
591
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
592
        IF (USER_RST = '1') THEN
593
          reg_np_counter <= "000" AFTER (TCQ)*1 ps;
594
        ELSE
595
          IF ((np_pkt_lower = '1' OR np_pkt_upper = '1') AND pkt_accepted = '1') THEN
596
            reg_np_counter <= reg_np_counter + "001" AFTER (TCQ)*1 ps;
597
          END IF;
598
        END IF;
599
      END IF;
600
    END PROCESS;
601
 
602
    NP_COUNTER <= reg_np_counter;
603
  END GENERATE;
604
 
605
  xhdl22 : IF (NOT(C_FAMILY = "V6" AND C_DATA_WIDTH = 128)) GENERATE
606
    NP_COUNTER <= "000";
607
  END GENERATE;
608
END trans;
609
 
610
 

powered by: WebSVN 2.1.0

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