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_tx_pipeline.vhd] - Blame information for rev 48

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_tx_pipeline.vhd
52 48 dsmv
-- Version    : 1.10
53 46 dsmv
--
54
-- Description:
55
--AXI to TRN TX pipeline. Converts transmitted data from AXI protocol to
56
--  TRN.
57
--
58
--  Notes:
59
--  Optional notes section.
60
--
61
--  Hierarchical:
62
--    axi_basic_top
63
--      axi_basic_tx
64
--        axi_basic_tx_pipeline
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_tx_pipeline IS
75
  GENERIC (
76
     C_DATA_WIDTH            : INTEGER := 128;     -- RX/TX interface data width
77
     C_PM_PRIORITY           : BOOLEAN := FALSE;  -- Disable TX packet boundary thrtl
78
     TCQ                     : INTEGER := 1;       -- Clock to Q time
79
 
80
     C_REM_WIDTH             : INTEGER :=  1       -- trem/rrem width
81
  );
82
  PORT (
83
 
84
    -----------------------------------------------
85
    -- User Design I/O
86
    -----------------------------------------------
87
 
88
    -- AXI TX
89
    -------------
90
    S_AXIS_TX_TDATA         : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX data from user
91
    S_AXIS_TX_TVALID        : IN STD_LOGIC                                    := '0';           -- TX data is valid
92
    S_AXIS_TX_TREADY        : OUT STD_LOGIC                                   := '0';           -- TX ready for data
93
    s_axis_tx_tkeep         : IN STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0)  := (OTHERS=>'0'); -- TX strobe byte enables
94
    S_AXIS_TX_TLAST         : IN STD_LOGIC                                    := '0';           -- TX data is last
95
    S_AXIS_TX_TUSER         : IN STD_LOGIC_VECTOR(3 DOWNTO 0)                 := (OTHERS=>'0'); -- TX user signals
96
 
97
    -----------------------------------------------//
98
    -- PCIe Block I/O                              //
99
    -----------------------------------------------//
100
 
101
    -- TRN TX
102
    -------------
103
    TRN_TD                  : OUT STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) := (OTHERS=>'0'); -- TX data from block
104
    TRN_TSOF                : OUT STD_LOGIC                                   := '0';           -- TX start of packet
105
    TRN_TEOF                : OUT STD_LOGIC                                   := '0';           -- TX end of packet
106
    TRN_TSRC_RDY            : OUT STD_LOGIC                                   := '0';           -- TX source ready
107
    TRN_TDST_RDY            : IN STD_LOGIC                                    := '0';           -- TX destination ready
108
    TRN_TSRC_DSC            : OUT STD_LOGIC                                   := '0';           -- TX source discontinue
109
    TRN_TREM                : OUT STD_LOGIC_VECTOR(C_REM_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX remainder
110
    TRN_TERRFWD             : OUT STD_LOGIC                                   := '0';           -- TX error forward
111
    TRN_TSTR                : OUT STD_LOGIC                                   := '0';           -- TX streaming enable
112
    TRN_TECRC_GEN           : OUT STD_LOGIC                                   := '0';           -- TX ECRC generate
113
    TRN_LNK_UP              : IN STD_LOGIC                                    := '0';           -- PCIe link up
114
 
115
    -- System
116
    -------------
117
    TREADY_THRTL            : IN STD_LOGIC                                    := '0';           -- TREADY from thrtl ctl
118
    USER_CLK                : IN STD_LOGIC                                    := '0';           -- user clock from block
119
    USER_RST                : IN STD_LOGIC                                    := '0'            -- user reset from block
120
  );
121
END cl_a7pcie_x4_axi_basic_tx_pipeline;
122
 
123
ARCHITECTURE trans OF cl_a7pcie_x4_axi_basic_tx_pipeline IS
124
 
125
  -- Input register stage
126
  SIGNAL reg_tdata              : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
127
  SIGNAL tdata_prev             : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
128
  SIGNAL tkeep_prev             : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
129
  SIGNAL tvalid_prev            : STD_LOGIC;
130
  SIGNAL tlast_prev             : STD_LOGIC;
131
  SIGNAL reg_tdst_rdy           : STD_LOGIC;
132
  SIGNAL data_hold              : STD_LOGIC;
133
  SIGNAL data_prev              : STD_LOGIC;
134
  SIGNAL tuser_prev             : STD_LOGIC_VECTOR(3 DOWNTO 0);
135
  SIGNAL reg_tvalid             : STD_LOGIC;
136
  SIGNAL reg_tkeep              : STD_LOGIC_VECTOR((C_DATA_WIDTH/8)-1 DOWNTO 0);
137
  SIGNAL reg_tuser              : STD_LOGIC_VECTOR(3 DOWNTO 0);
138
  SIGNAL reg_tlast              : STD_LOGIC;
139
  SIGNAL reg_tready             : STD_LOGIC;
140
 
141
  -- Pipeline utility signals
142
  SIGNAL trn_in_packet          : STD_LOGIC;
143
  SIGNAL axi_in_packet          : STD_LOGIC;
144
  SIGNAL flush_axi              : STD_LOGIC;
145
  SIGNAL disable_trn            : STD_LOGIC;
146
  SIGNAL reg_disable_trn        : STD_LOGIC;
147
  SIGNAL axi_beat_live          : STD_LOGIC;
148
  SIGNAL axi_end_packet         : STD_LOGIC;
149
 
150
  SIGNAL reg_tsrc_rdy           : STD_LOGIC;
151
 
152
  -- Declare intermediate signals for referenced outputs
153
  SIGNAL s_axis_tx_tready_xhdl0 : STD_LOGIC;
154
  SIGNAL trn_tsof_xhdl2         : STD_LOGIC;
155
  SIGNAL trn_teof_xhdl1         : STD_LOGIC;
156
  SIGNAL trn_tsrc_rdy_xhdl3     : STD_LOGIC;
157
  SIGNAL axi_DW_1               : STD_LOGIC;
158
  SIGNAL axi_DW_2               : STD_LOGIC;
159
  SIGNAL axi_DW_3               : STD_LOGIC;
160
 
161
BEGIN
162
  -- Drive referenced outputs
163
  S_AXIS_TX_TREADY <= s_axis_tx_tready_xhdl0;
164
  TRN_TSOF         <= trn_tsof_xhdl2;
165
  TRN_TEOF         <= trn_teof_xhdl1;
166
  TRN_TSRC_RDY     <= trn_tsrc_rdy_xhdl3;
167
 
168
  axi_beat_live  <= '1' WHEN (S_AXIS_TX_TVALID = '1' AND s_axis_tx_tready_xhdl0 = '1') ELSE '0';
169
  axi_end_packet <= '1' WHEN (axi_beat_live = '1' AND S_AXIS_TX_TLAST = '1') ELSE '0';
170
 
171
  ------------------------------------------------------------------------------
172
  -- Convert TRN data format to AXI data format. AXI is DWORD swapped from TRN.
173
  -- 128-bit:                 64-bit:                  32-bit:
174
  -- TRN DW0 maps to AXI DW3  TRN DW0 maps to AXI DW1  TNR DW0 maps to AXI DW0
175
  -- TRN DW1 maps to AXI DW2  TRN DW1 maps to AXI DW0
176
  -- TRN DW2 maps to AXI DW1
177
  -- TRN DW3 maps to AXI DW0
178
  ------------------------------------------------------------------------------
179
 
180
  xhdl4 : IF (C_DATA_WIDTH = 128) GENERATE
181
    TRN_TD <= (reg_tdata(31 DOWNTO 0) & reg_tdata(63 DOWNTO 32) & reg_tdata(95 DOWNTO 64) & reg_tdata(127 DOWNTO 96));
182
  END GENERATE;
183
 
184
  xhdl5 : IF (C_DATA_WIDTH = 64) GENERATE
185
    TRN_TD <= (reg_tdata(31 DOWNTO 0) & reg_tdata(63 DOWNTO 32));
186
  END GENERATE;
187
 
188
  xhdl6 : IF (NOT(C_DATA_WIDTH = 64) AND NOT(C_DATA_WIDTH = 128)) GENERATE
189
    TRN_TD <= reg_tdata;
190
  END GENERATE;
191
 
192
  ------------------------------------------------------------------------------//
193
  -- Create trn_tsof. If we're not currently in a packet and TVALID goes high,  //
194
  -- assert TSOF.                                                               //
195
  ------------------------------------------------------------------------------//
196
  trn_tsof_xhdl2 <= ((NOT(trn_in_packet)) AND reg_tvalid);
197
 
198
  ------------------------------------------------------------------------------//
199
  -- Create trn_in_packet. This signal tracks if the TRN interface is currently //
200
  -- in the middle of a packet, which is needed to generate trn_tsof            //
201
  ------------------------------------------------------------------------------//
202
  PROCESS (USER_CLK)
203
  BEGIN
204
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
205
      IF (USER_RST = '1') THEN
206
        trn_in_packet <= '0'  AFTER (TCQ)*1 ps;
207
      ELSE
208
        IF ((trn_teof_xhdl1 = '0') AND (trn_tsof_xhdl2 = '1') AND (trn_tsrc_rdy_xhdl3 = '1') AND (TRN_TDST_RDY = '1')) THEN
209
          trn_in_packet <= '1'  AFTER (TCQ)*1 ps;
210
        ELSIF (((trn_in_packet = '1') AND (trn_teof_xhdl1 = '1') AND (trn_tsrc_rdy_xhdl3 = '1')) OR (trn_lnk_up = '0')) THEN
211
          trn_in_packet <= '0'  AFTER (TCQ)*1 ps;
212
        END IF;
213
      END IF;
214
    END IF;
215
  END PROCESS;
216
 
217
 
218
  ------------------------------------------------------------------------------//
219
  -- Create axi_in_packet. This signal tracks if the AXI interface is currently //
220
  -- in the middle of a packet, which is needed in case the link goes down.     //
221
  ------------------------------------------------------------------------------//
222
  PROCESS (USER_CLK)
223
  BEGIN
224
    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
225
      IF (USER_RST = '1') THEN
226
        axi_in_packet <= '0' AFTER (TCQ)*1 ps;
227
      ELSE
228
        IF (axi_beat_live = '1' AND S_AXIS_TX_TLAST = '0') THEN
229
          axi_in_packet <= '1' AFTER (TCQ)*1 ps;
230
        ELSIF (axi_beat_live = '1') THEN
231
          axi_in_packet <= '0' AFTER (TCQ)*1 ps;
232
        END IF;
233
      END IF;
234
    END IF;
235
  END PROCESS;
236
 
237
  ------------------------------------------------------------------------------//
238
  -- Create disable_trn. This signal asserts when the link goes down and        //
239
  -- triggers the deassertiong of trn_tsrc_rdy. The deassertion of disable_trn  //
240
  -- depends on C_PM_PRIORITY, as described below.                              //
241
  ------------------------------------------------------------------------------//
242
  PM_PRIORITY_TRN_FLUSH : IF (C_PM_PRIORITY) GENERATE
243
    -- In the C_PM_PRIORITY pipeline, we disable the TRN interfacefrom the time
244
    -- the link goes down until the the AXI interface is ready to accept packets
245
    -- again (via assertion of TREADY). By waiting for TREADY, we allow the
246
    -- previous value buffer to fill, so we're ready for any throttling by the
247
    -- user or the block.
248
 
249
    PROCESS (USER_CLK)
250
    BEGIN
251
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
252
        IF (USER_RST = '1') THEN
253
          reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
254
        ELSE
255
          IF (trn_lnk_up = '0') THEN
256
            reg_disable_trn <= '1' AFTER (TCQ)*1 ps;
257
          ELSIF (flush_axi = '0' AND s_axis_tx_tready_xhdl0 = '1') THEN
258
            reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
259
          END IF;
260
        END IF;
261
      END IF;
262
    END PROCESS;
263
 
264
    disable_trn <= reg_disable_trn;
265
  END GENERATE;
266
 
267
  -- In the throttle-controlled pipeline, we don't have a previous value buffer.
268
  -- The throttle control mechanism handles TREADY, so all we need to do is
269
  -- detect when the link goes down and disable the TRN interface until the link
270
  -- comes back up and the AXI interface is finished flushing any packets.
271
  TNRTL_CTL_TRN_FLUSH : IF (NOT(C_PM_PRIORITY)) GENERATE
272
    PROCESS (USER_CLK)
273
    BEGIN
274
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
275
        IF (USER_RST = '1') THEN
276
          reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
277
        ELSE
278
          IF (axi_in_packet = '1' AND trn_lnk_up = '0' AND axi_end_packet = '0') THEN
279
            reg_disable_trn <= '1' AFTER (TCQ)*1 ps;
280
          ELSIF (axi_end_packet = '1') THEN
281
            reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
282
          END IF;
283
        END IF;
284
      END IF;
285
    END PROCESS;
286
 
287
    disable_trn <= '1' WHEN (reg_disable_trn = '1' OR trn_lnk_up = '0') ELSE '0';
288
  END GENERATE;
289
 
290
 
291
  ------------------------------------------------------------------------------//
292
  -- Convert STRB to RREM. Here, we are converting the encoding method for the  //
293
  -- location of the EOF from AXI (tkeep) to TRN flavor (rrem).                 //
294
  ------------------------------------------------------------------------------//
295
  xhdl8 : IF (C_DATA_WIDTH = 128) GENERATE
296
  -----------------------------------------
297
  -- Conversion table:
298
  -- trem    | tkeep
299
  -- [1] [0] | [15:12] [11:8] [7:4] [3:0]
300
  -- -------------------------------------
301
  --  1   1  |   D3      D2    D1    D0
302
  --  1   0  |   --      D2    D1    D0
303
  --  0   1  |   --      --    D1    D0
304
  --  0   0  |   --      --    --    D0
305
  -----------------------------------------
306
    axi_DW_1    <= reg_tkeep(7);
307
    axi_DW_2    <= reg_tkeep(11);
308
    axi_DW_3    <= reg_tkeep(15);
309
    TRN_TREM(1) <= axi_DW_2;
310
    TRN_TREM(0) <= (axi_DW_3 OR (axi_DW_1 AND NOT(axi_DW_2)));
311
  END GENERATE;
312
 
313
  xhdl9 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
314
    xhdl10 : IF (C_DATA_WIDTH = 64) GENERATE
315
      TRN_TREM(0) <= reg_tkeep(7);
316
    END GENERATE;
317
    xhdl11 : IF (NOT(C_DATA_WIDTH = 64)) GENERATE
318
      TRN_TREM <= x"0";
319
    END GENERATE;
320
  END GENERATE;
321
 
322
  ------------------------------------------------------------------------------
323
  -- Create remaining TRN signals
324
  ------------------------------------------------------------------------------
325
  trn_teof_xhdl1   <= reg_tlast;
326
  TRN_TECRC_GEN    <= reg_tuser(0);
327
  TRN_TERRFWD      <= reg_tuser(1);
328
  TRN_TSTR         <= reg_tuser(2);
329
  TRN_TSRC_DSC     <= reg_tuser(3);
330
 
331
  ------------------------------------------------------------------------------
332
  -- Pipeline stage
333
  ------------------------------------------------------------------------------
334
  -- We need one of two approaches for the pipeline stage depending on the
335
  -- C_PM_PRIORITY parameter.
336
  xhdl12 : IF (NOT(C_PM_PRIORITY)) GENERATE
337
    PROCESS (USER_CLK)
338
    BEGIN
339
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
340
        IF (USER_RST = '1') THEN
341
          reg_tdata      <= (others => '0') AFTER (TCQ)*1 ps;
342
          reg_tvalid     <= '0'  AFTER (TCQ)*1 ps;
343
          reg_tkeep      <= (others => '0') AFTER (TCQ)*1 ps;
344
          reg_tlast      <= '0'    AFTER (TCQ)*1 ps;
345
          reg_tuser      <= (others => '0') AFTER (TCQ)*1 ps;
346
          reg_tsrc_rdy   <= '0'    AFTER (TCQ)*1 ps;
347
        ELSE
348
          reg_tdata      <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
349
          reg_tvalid     <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
350
          reg_tkeep      <= s_axis_tx_tkeep   AFTER (TCQ)*1 ps;
351
          reg_tlast      <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
352
          reg_tuser      <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
353
 
354
          -- Hold trn_tsrc_rdy low when flushing a packet
355
          reg_tsrc_rdy   <= (axi_beat_live AND (NOT disable_trn)) AFTER (TCQ)*1 ps;
356
        END IF;
357
      END IF;
358
    END PROCESS;
359
 
360
    trn_tsrc_rdy_xhdl3     <= reg_tsrc_rdy;
361
    -- With TX packet boundary throttling, TREADY is pipelined in
362
    -- axi_basic_tx_thrtl_ctl and wired through here.
363
    s_axis_tx_tready_xhdl0 <= TREADY_THRTL;
364
 
365
  END GENERATE;
366
 
367
  --**************************************************************************--
368
 
369
  -- If C_PM_PRIORITY is set to TRUE, that means the user prefers to have all PM
370
  -- functionality intact isntead of TX packet boundary throttling. Now the
371
  -- Block could back-pressure at any time, which creates the standard problem
372
  -- of potential data loss due to the handshaking latency. Here we need a
373
  -- previous value buffer, just like the RX data path.
374
  xhdl13 : IF (C_PM_PRIORITY) GENERATE
375
 
376
    --------------------------------------------------------------------------
377
    -- Previous value buffer
378
    -- ---------------------
379
    -- We are inserting a pipeline stage in between AXI and TRN, which causes
380
    -- some issues with handshaking signals trn_tsrc_rdy/s_axis_tx_tready.
381
    -- The added cycle of latency in the path causes the Block to fall behind
382
    -- the AXI interface whenever it throttles.
383
    --
384
    -- To avoid loss of data, we must keep the previous value of all
385
    -- s_axis_tx_* signals in case the Block throttles.
386
    --------------------------------------------------------------------------
387
    PROCESS (USER_CLK)
388
      BEGIN
389
        IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
390
          IF (USER_RST = '1') THEN
391
            tdata_prev     <= (others =>'0' ) AFTER (TCQ)*1 ps;
392
            tvalid_prev    <= '0'             AFTER (TCQ)*1 ps;
393
            tkeep_prev     <= (others =>'0' ) AFTER (TCQ)*1 ps;
394
            tlast_prev     <= '0'             AFTER (TCQ)*1 ps;
395
            tuser_prev     <= "0000"          AFTER (TCQ)*1 ps;
396
          ELSE
397
            -- prev buffer works by checking s_axis_tx_tready. When s_axis_tx_tready is
398
            -- asserted, a new value is present on the interface.
399
            IF ((NOT(s_axis_tx_tready_xhdl0)) = '1') THEN
400
              tdata_prev  <= tdata_prev   AFTER (TCQ)*1 ps;
401
              tvalid_prev <= tvalid_prev  AFTER (TCQ)*1 ps;
402
              tkeep_prev  <= tkeep_prev   AFTER (TCQ)*1 ps;
403
              tlast_prev  <= tlast_prev   AFTER (TCQ)*1 ps;
404
              tuser_prev  <= tuser_prev   AFTER (TCQ)*1 ps;
405
            ELSE
406
              tdata_prev  <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
407
              tvalid_prev <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
408
              tkeep_prev  <= s_axis_tx_tkeep   AFTER (TCQ)*1 ps;
409
              tlast_prev  <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
410
              tuser_prev  <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
411
            END IF;
412
          END IF;
413
        END IF;
414
      END PROCESS;
415
 
416
      -- Create special buffer which locks in the propper value of TDATA depending
417
      -- on whether the user is throttling or not. This buffer has three states:
418
      --
419
      --       HOLD state: TDATA maintains its current value
420
      --                   - the Block has throttled the PCIe block
421
      --   PREVIOUS state: the buffer provides the previous value on TDATA
422
      --                   - the Block has finished throttling, and is a little
423
      --                     behind the PCIe user
424
      --    CURRENT state: the buffer passes the current value on TDATA
425
      --                   - the Block is caught up and ready to receive the latest
426
      --                     data from the PCIe user
427
      PROCESS (USER_CLK)
428
      BEGIN
429
        IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
430
          IF (USER_RST = '1') THEN
431
            reg_tdata <= (others => '0') AFTER (TCQ)*1 ps;
432
            reg_tvalid <= '0'  AFTER (TCQ)*1 ps;
433
            reg_tkeep <= (others => '0')  AFTER (TCQ)*1 ps;
434
            reg_tlast <= '0'  AFTER (TCQ)*1 ps;
435
 
436
            reg_tuser <= (others => '0') AFTER (TCQ)*1 ps;
437
            reg_tdst_rdy <= '0' AFTER (TCQ)*1 ps;
438
          ELSE
439
 
440
            reg_tdst_rdy <= trn_tdst_rdy AFTER (TCQ)*1 ps;
441
            IF ((NOT(data_hold)) = '1') THEN
442
              -- PREVIOUS state
443
              IF (data_prev = '1') THEN
444
                reg_tdata  <= tdata_prev   AFTER (TCQ)*1 ps;
445
                reg_tvalid <= tvalid_prev AFTER (TCQ)*1 ps;
446
                reg_tkeep  <= tkeep_prev   AFTER (TCQ)*1 ps;
447
                reg_tlast  <= tlast_prev   AFTER (TCQ)*1 ps;
448
                reg_tuser  <= tuser_prev   AFTER (TCQ)*1 ps;
449
              ELSE
450
                -- CURRENT state
451
                reg_tdata  <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
452
                reg_tvalid <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
453
                reg_tkeep  <= s_axis_tx_tkeep   AFTER (TCQ)*1 ps;
454
                reg_tlast  <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
455
                reg_tuser  <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
456
              END IF;
457
            END IF;
458
          -- else HOLD state
459
          END IF;
460
        END IF;
461
      END PROCESS;
462
 
463
 
464
      -- Logic to instruct pipeline to hold its value
465
      data_hold <= ((NOT(TRN_TDST_RDY) AND trn_tsrc_rdy_xhdl3));
466
 
467
    -- Logic to instruct pipeline to use previous bus values. Always use
468
    -- previous value after holding a value.
469
    PROCESS (USER_CLK)
470
    BEGIN
471
       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
472
          IF (USER_RST = '1') THEN
473
             data_prev <= '0'  AFTER (TCQ)*1 ps;
474
          ELSE
475
             data_prev <= data_hold  AFTER (TCQ)*1 ps;
476
          END IF;
477
       END IF;
478
    END PROCESS;
479
 
480
 
481
      --------------------------------------------------------------------------
482
      --  Create trn_tsrc_rdy. If we're flushing the TRN hold trn_tsrc_rdy low.
483
      --------------------------------------------------------------------------
484
      trn_tsrc_rdy_xhdl3 <= reg_tvalid;
485
 
486
      --------------------------------------------------------------------------//
487
      -- Create TREADY                                                          //
488
      --------------------------------------------------------------------------//
489
      PROCESS (USER_CLK)
490
      BEGIN
491
        IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
492
          IF (USER_RST = '1') THEN
493
            reg_tready <= '0' AFTER (TCQ)*1 ps;
494
          ELSE
495
            -- If the link went down and we need to flush a packet in flight, hold
496
            -- TREADY high
497
            IF (flush_axi = '1' AND axi_end_packet = '0') THEN
498
              reg_tready <= '1' AFTER (TCQ)*1 ps;
499
 
500
              -- If the link is up, TREADY is as follows:
501
              --   TREADY = 1 when trn_tsrc_rdy == 0
502
              --      - While idle, keep the pipeline primed and ready for the next
503
              --        packet
504
              --
505
              --   TREADY = trn_tdst_rdy when trn_tsrc_rdy == 1
506
              --      - While in packet, throttle pipeline based on state of TRN
507
            ELSIF(trn_lnk_up = '1') THEN
508
              reg_tready <= TRN_TDST_RDY OR (NOT trn_tsrc_rdy_xhdl3) AFTER (TCQ)*1 ps;
509
            ELSE
510
              -- If the link is down and we're not flushing a packet, hold TREADY low
511
              -- wait for link to come back up
512
              reg_tready <= '0'  AFTER (TCQ)*1 ps;
513
            END IF;
514
          END IF;
515
        END IF;
516
      END PROCESS;
517
 
518
    s_axis_tx_tready_xhdl0 <= reg_tready;
519
 
520
    ----------------------------------------------------------------------------//
521
    -- Create flush_axi. This signal detects if the link goes down while the    //
522
    -- AXI interface is in packet. In this situation, we need to flush the      //
523
    -- packet through the AXI interface and discard it.                         //
524
    ----------------------------------------------------------------------------//
525
    PROCESS (USER_CLK)
526
    BEGIN
527
      IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
528
        IF (USER_RST = '1') THEN
529
          flush_axi <= '0' AFTER (TCQ)*1 ps;
530
        ELSE
531
          -- If the AXI interface is in packet and the link goes down, purge it.
532
          IF (axi_in_packet = '1' AND trn_lnk_up = '0' AND axi_end_packet = '0') THEN
533
            flush_axi <= '1' AFTER (TCQ)*1 ps;
534
          -- The packet is finished, so we're done flushing.
535
          ELSIF (axi_end_packet = '1') THEN
536
            flush_axi <= '0' AFTER (TCQ)*1 ps;
537
          END IF;
538
        END IF;
539
      END IF;
540
    END PROCESS;
541
  END GENERATE;
542
END trans;

powered by: WebSVN 2.1.0

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