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_virtex6/] [axi_basic_tx_pipeline.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 dsmv
-------------------------------------------------------------------------------
2
--
3
-- (c) Copyright 2009-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    : Virtex-6 Integrated Block for PCI Express
51
-- File       : axi_basic_tx_pipeline.vhd
52
-- Version    : 2.3
53
--
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 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
      C_STRB_WIDTH            : INTEGER :=  8       -- TSTRB width
82
   );
83
   PORT (
84
 
85
      -----------------------------------------------
86
      -- User Design I/O
87
      -----------------------------------------------
88
 
89
      -- AXI TX
90
      -------------
91
      S_AXIS_TX_TDATA         : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX data from user
92
      S_AXIS_TX_TVALID        : IN STD_LOGIC                                    := '0';           -- TX data is valid
93
      S_AXIS_TX_TREADY        : OUT STD_LOGIC                                   := '0';           -- TX ready for data
94
      S_AXIS_TX_TSTRB         : IN STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX strobe byte enables
95
      S_AXIS_TX_TLAST         : IN STD_LOGIC                                    := '0';           -- TX data is last
96
      S_AXIS_TX_TUSER         : IN STD_LOGIC_VECTOR(3 DOWNTO 0)                 := (OTHERS=>'0'); -- TX user signals
97
 
98
      -----------------------------------------------//
99
      -- PCIe Block I/O                              //
100
      -----------------------------------------------//
101
 
102
      -- TRN TX
103
      -------------
104
      TRN_TD                  : OUT STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) := (OTHERS=>'0'); -- TX data from block
105
      TRN_TSOF                : OUT STD_LOGIC                                   := '0';           -- TX start of packet
106
      TRN_TEOF                : OUT STD_LOGIC                                   := '0';           -- TX end of packet
107
      TRN_TSRC_RDY            : OUT STD_LOGIC                                   := '0';           -- TX source ready
108
      TRN_TDST_RDY            : IN STD_LOGIC                                    := '0';           -- TX destination ready
109
      TRN_TSRC_DSC            : OUT STD_LOGIC                                   := '0';           -- TX source discontinue
110
      TRN_TREM                : OUT STD_LOGIC_VECTOR(C_REM_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX remainder
111
      TRN_TERRFWD             : OUT STD_LOGIC                                   := '0';           -- TX error forward
112
      TRN_TSTR                : OUT STD_LOGIC                                   := '0';           -- TX streaming enable
113
      TRN_TECRC_GEN           : OUT STD_LOGIC                                   := '0';           -- TX ECRC generate
114
      TRN_LNK_UP              : IN STD_LOGIC                                    := '0';           -- PCIe link up
115
 
116
      -- System
117
      -------------
118
      TREADY_THRTL            : IN STD_LOGIC                                    := '0';           -- TREADY from thrtl ctl
119
      USER_CLK                : IN STD_LOGIC                                    := '0';           -- user clock from block
120
      USER_RST                : IN STD_LOGIC                                    := '0'            -- user reset from block
121
   );
122
END axi_basic_tx_pipeline;
123
 
124
ARCHITECTURE trans OF axi_basic_tx_pipeline IS
125
 
126
   -- Input register stage
127
   SIGNAL reg_tdata              : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
128
   SIGNAL tdata_prev             : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
129
   SIGNAL tstrb_prev             : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
130
   SIGNAL tvalid_prev            : STD_LOGIC;
131
   SIGNAL tlast_prev             : STD_LOGIC;
132
   SIGNAL reg_tdst_rdy           : STD_LOGIC;
133
   SIGNAL data_hold              : STD_LOGIC;
134
   SIGNAL data_prev              : STD_LOGIC;
135
   SIGNAL tuser_prev             : STD_LOGIC_VECTOR(3 DOWNTO 0);
136
   SIGNAL reg_tvalid             : STD_LOGIC;
137
   SIGNAL reg_tstrb              : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
138
   SIGNAL reg_tuser              : STD_LOGIC_VECTOR(3 DOWNTO 0);
139
   SIGNAL reg_tlast              : STD_LOGIC;
140
   SIGNAL reg_tready             : STD_LOGIC;
141
 
142
   -- Pipeline utility signals
143
   SIGNAL trn_in_packet          : STD_LOGIC;
144
   SIGNAL axi_in_packet          : STD_LOGIC;
145
   SIGNAL flush_axi              : STD_LOGIC;
146
   SIGNAL disable_trn            : STD_LOGIC;
147
   SIGNAL reg_disable_trn        : STD_LOGIC;
148
   SIGNAL axi_beat_live          : STD_LOGIC;
149
   SIGNAL axi_end_packet         : STD_LOGIC;
150
 
151
   SIGNAL reg_tsrc_rdy           : STD_LOGIC;
152
 
153
   -- Declare intermediate signals for referenced outputs
154
   SIGNAL s_axis_tx_tready_xhdl0 : STD_LOGIC;
155
   SIGNAL trn_tsof_xhdl2         : STD_LOGIC;
156
   SIGNAL trn_teof_xhdl1         : STD_LOGIC;
157
   SIGNAL trn_tsrc_rdy_xhdl3     : STD_LOGIC;
158
   SIGNAL axi_DW_1               : STD_LOGIC;
159
   SIGNAL axi_DW_2               : STD_LOGIC;
160
   SIGNAL axi_DW_3               : STD_LOGIC;
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') AND (TRN_TDST_RDY = '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 (TSTRB) to TRN flavor (rrem).                 //
294
   ------------------------------------------------------------------------------//
295
   xhdl8 : IF (C_DATA_WIDTH = 128) GENERATE
296
   -----------------------------------------
297
   -- Conversion table:
298
   -- trem    | tstrb
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_tstrb(7);
307
           axi_DW_2    <= reg_tstrb(11);
308
           axi_DW_3    <= reg_tstrb(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_tstrb(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_tstrb      <= (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_tstrb      <= S_AXIS_TX_TSTRB   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
               tstrb_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
                  tstrb_prev  <= tstrb_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
                  tstrb_prev  <= S_AXIS_TX_TSTRB   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_tstrb <= (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_tstrb  <= tstrb_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_tstrb  <= S_AXIS_TX_TSTRB   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.