DS_DMA
pcie_src/pcie_core64_m1/source_virtex6/axi_basic_tx_pipeline.vhd
00001 -------------------------------------------------------------------------------
00002 --
00003 -- (c) Copyright 2009-2011 Xilinx, Inc. All rights reserved.
00004 --
00005 -- This file contains confidential and proprietary information
00006 -- of Xilinx, Inc. and is protected under U.S. and
00007 -- international copyright and other intellectual property
00008 -- laws.
00009 --
00010 -- DISCLAIMER
00011 -- This disclaimer is not a license and does not grant any
00012 -- rights to the materials distributed herewith. Except as
00013 -- otherwise provided in a valid license issued to you by
00014 -- Xilinx, and to the maximum extent permitted by applicable
00015 -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND
00016 -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES
00017 -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING
00018 -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-
00019 -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and
00020 -- (2) Xilinx shall not be liable (whether in contract or tort,
00021 -- including negligence, or under any other theory of
00022 -- liability) for any loss or damage of any kind or nature
00023 -- related to, arising under or in connection with these
00024 -- materials, including for any direct, or any indirect,
00025 -- special, incidental, or consequential loss or damage
00026 -- (including loss of data, profits, goodwill, or any type of
00027 -- loss or damage suffered as a result of any action brought
00028 -- by a third party) even if such damage or loss was
00029 -- reasonably foreseeable or Xilinx had been advised of the
00030 -- possibility of the same.
00031 --
00032 -- CRITICAL APPLICATIONS
00033 -- Xilinx products are not designed or intended to be fail-
00034 -- safe, or for use in any application requiring fail-safe
00035 -- performance, such as life-support or safety devices or
00036 -- systems, Class III medical devices, nuclear facilities,
00037 -- applications related to the deployment of airbags, or any
00038 -- other applications that could lead to death, personal
00039 -- injury, or severe property or environmental damage
00040 -- (individually and collectively, "Critical
00041 -- Applications"). Customer assumes the sole risk and
00042 -- liability of any use of Xilinx products in Critical
00043 -- Applications, subject only to applicable laws and
00044 -- regulations governing limitations on product liability.
00045 --
00046 -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS
00047 -- PART OF THIS FILE AT ALL TIMES.
00048 --
00049 -------------------------------------------------------------------------------
00050 -- Project    : Virtex-6 Integrated Block for PCI Express
00051 -- File       : axi_basic_tx_pipeline.vhd
00052 -- Version    : 2.3
00053 --
00054 -- Description:
00055 --AXI to TRN TX pipeline. Converts transmitted data from AXI protocol to
00056 --  TRN.
00057 --
00058 --  Notes:
00059 --  Optional notes section.
00060 --
00061 --  Hierarchical:
00062 --    axi_basic_top
00063 --      axi_basic_tx
00064 --        axi_basic_tx_pipeline
00065 --------------------------------------------------------------------------------
00066 -- Library Declarations
00067 --------------------------------------------------------------------------------
00068 
00069 LIBRARY ieee;
00070    USE ieee.std_logic_1164.all;
00071    USE ieee.std_logic_unsigned.all;
00072 
00073 
00074 ENTITY axi_basic_tx_pipeline IS
00075    GENERIC (
00076       C_DATA_WIDTH            : INTEGER := 128;     -- RX/TX interface data width
00077       C_PM_PRIORITY           : BOOLEAN := FALSE;  -- Disable TX packet boundary thrtl
00078       TCQ                     : INTEGER := 1;       -- Clock to Q time
00079 
00080       C_REM_WIDTH             : INTEGER :=  1;      -- trem/rrem width
00081       C_STRB_WIDTH            : INTEGER :=  8       -- TSTRB width
00082    );
00083    PORT (
00084 
00085       -----------------------------------------------
00086       -- User Design I/O
00087       -----------------------------------------------
00088 
00089       -- AXI TX
00090       -------------
00091       S_AXIS_TX_TDATA         : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX data from user
00092       S_AXIS_TX_TVALID        : IN STD_LOGIC                                    := '0';           -- TX data is valid
00093       S_AXIS_TX_TREADY        : OUT STD_LOGIC                                   := '0';           -- TX ready for data
00094       S_AXIS_TX_TSTRB         : IN STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX strobe byte enables
00095       S_AXIS_TX_TLAST         : IN STD_LOGIC                                    := '0';           -- TX data is last
00096       S_AXIS_TX_TUSER         : IN STD_LOGIC_VECTOR(3 DOWNTO 0)                 := (OTHERS=>'0'); -- TX user signals
00097 
00098       -----------------------------------------------//
00099       -- PCIe Block I/O                              //
00100       -----------------------------------------------//
00101 
00102       -- TRN TX
00103       -------------
00104       TRN_TD                  : OUT STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) := (OTHERS=>'0'); -- TX data from block
00105       TRN_TSOF                : OUT STD_LOGIC                                   := '0';           -- TX start of packet
00106       TRN_TEOF                : OUT STD_LOGIC                                   := '0';           -- TX end of packet
00107       TRN_TSRC_RDY            : OUT STD_LOGIC                                   := '0';           -- TX source ready
00108       TRN_TDST_RDY            : IN STD_LOGIC                                    := '0';           -- TX destination ready
00109       TRN_TSRC_DSC            : OUT STD_LOGIC                                   := '0';           -- TX source discontinue
00110       TRN_TREM                : OUT STD_LOGIC_VECTOR(C_REM_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX remainder
00111       TRN_TERRFWD             : OUT STD_LOGIC                                   := '0';           -- TX error forward
00112       TRN_TSTR                : OUT STD_LOGIC                                   := '0';           -- TX streaming enable
00113       TRN_TECRC_GEN           : OUT STD_LOGIC                                   := '0';           -- TX ECRC generate
00114       TRN_LNK_UP              : IN STD_LOGIC                                    := '0';           -- PCIe link up
00115 
00116       -- System
00117       -------------
00118       TREADY_THRTL            : IN STD_LOGIC                                    := '0';           -- TREADY from thrtl ctl
00119       USER_CLK                : IN STD_LOGIC                                    := '0';           -- user clock from block
00120       USER_RST                : IN STD_LOGIC                                    := '0'            -- user reset from block
00121    );
00122 END axi_basic_tx_pipeline;
00123 
00124 ARCHITECTURE trans OF axi_basic_tx_pipeline IS
00125 
00126    -- Input register stage
00127    SIGNAL reg_tdata              : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
00128    SIGNAL tdata_prev             : STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0);
00129    SIGNAL tstrb_prev             : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
00130    SIGNAL tvalid_prev            : STD_LOGIC;
00131    SIGNAL tlast_prev             : STD_LOGIC;
00132    SIGNAL reg_tdst_rdy           : STD_LOGIC;
00133    SIGNAL data_hold              : STD_LOGIC;
00134    SIGNAL data_prev              : STD_LOGIC;
00135    SIGNAL tuser_prev             : STD_LOGIC_VECTOR(3 DOWNTO 0);
00136    SIGNAL reg_tvalid             : STD_LOGIC;
00137    SIGNAL reg_tstrb              : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
00138    SIGNAL reg_tuser              : STD_LOGIC_VECTOR(3 DOWNTO 0);
00139    SIGNAL reg_tlast              : STD_LOGIC;
00140    SIGNAL reg_tready             : STD_LOGIC;
00141 
00142    -- Pipeline utility signals
00143    SIGNAL trn_in_packet          : STD_LOGIC;
00144    SIGNAL axi_in_packet          : STD_LOGIC;
00145    SIGNAL flush_axi              : STD_LOGIC;
00146    SIGNAL disable_trn            : STD_LOGIC;
00147    SIGNAL reg_disable_trn        : STD_LOGIC;
00148    SIGNAL axi_beat_live          : STD_LOGIC;
00149    SIGNAL axi_end_packet         : STD_LOGIC;
00150 
00151    SIGNAL reg_tsrc_rdy           : STD_LOGIC;
00152 
00153    -- Declare intermediate signals for referenced outputs
00154    SIGNAL s_axis_tx_tready_xhdl0 : STD_LOGIC;
00155    SIGNAL trn_tsof_xhdl2         : STD_LOGIC;
00156    SIGNAL trn_teof_xhdl1         : STD_LOGIC;
00157    SIGNAL trn_tsrc_rdy_xhdl3     : STD_LOGIC;
00158    SIGNAL axi_DW_1               : STD_LOGIC;
00159    SIGNAL axi_DW_2               : STD_LOGIC;
00160    SIGNAL axi_DW_3               : STD_LOGIC;
00161 BEGIN
00162    -- Drive referenced outputs
00163    S_AXIS_TX_TREADY <= s_axis_tx_tready_xhdl0;
00164    TRN_TSOF         <= trn_tsof_xhdl2;
00165    TRN_TEOF         <= trn_teof_xhdl1;
00166    TRN_TSRC_RDY     <= trn_tsrc_rdy_xhdl3;
00167 
00168    axi_beat_live  <= '1' WHEN (S_AXIS_TX_TVALID = '1' AND s_axis_tx_tready_xhdl0 = '1') ELSE '0';
00169    axi_end_packet <= '1' WHEN (axi_beat_live = '1' AND S_AXIS_TX_TLAST = '1') ELSE '0';
00170 
00171    ------------------------------------------------------------------------------
00172    -- Convert TRN data format to AXI data format. AXI is DWORD swapped from TRN.
00173    -- 128-bit:                 64-bit:                  32-bit:
00174    -- TRN DW0 maps to AXI DW3  TRN DW0 maps to AXI DW1  TNR DW0 maps to AXI DW0
00175    -- TRN DW1 maps to AXI DW2  TRN DW1 maps to AXI DW0
00176    -- TRN DW2 maps to AXI DW1
00177    -- TRN DW3 maps to AXI DW0
00178    ------------------------------------------------------------------------------
00179 
00180    xhdl4 : IF (C_DATA_WIDTH = 128) GENERATE
00181       TRN_TD <= (reg_tdata(31 DOWNTO 0) & reg_tdata(63 DOWNTO 32) & reg_tdata(95 DOWNTO 64) & reg_tdata(127 DOWNTO 96));
00182    END GENERATE;
00183 
00184    xhdl5 : IF (C_DATA_WIDTH = 64) GENERATE
00185            TRN_TD <= (reg_tdata(31 DOWNTO 0) & reg_tdata(63 DOWNTO 32));
00186    END GENERATE;
00187 
00188    xhdl6 : IF (NOT(C_DATA_WIDTH = 64) AND NOT(C_DATA_WIDTH = 128)) GENERATE
00189            TRN_TD <= reg_tdata;
00190    END GENERATE;
00191 
00192    ------------------------------------------------------------------------------//
00193    -- Create trn_tsof. If we're not currently in a packet and TVALID goes high,  //
00194    -- assert TSOF.                                                               //
00195    ------------------------------------------------------------------------------//
00196    trn_tsof_xhdl2 <= ((NOT(trn_in_packet)) AND reg_tvalid);
00197 
00198    ------------------------------------------------------------------------------//
00199    -- Create trn_in_packet. This signal tracks if the TRN interface is currently //
00200    -- in the middle of a packet, which is needed to generate trn_tsof            //
00201    ------------------------------------------------------------------------------//
00202    PROCESS (USER_CLK)
00203    BEGIN
00204       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00205               IF (USER_RST = '1') THEN
00206                       trn_in_packet <= '0'  AFTER (TCQ)*1 ps;
00207               ELSE
00208                       IF ((trn_teof_xhdl1 = '0') AND (trn_tsof_xhdl2 = '1') AND (trn_tsrc_rdy_xhdl3 = '1') AND (TRN_TDST_RDY = '1')) THEN
00209                               trn_in_packet <= '1'  AFTER (TCQ)*1 ps;
00210                       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
00211                               trn_in_packet <= '0'  AFTER (TCQ)*1 ps;
00212                       END IF;
00213               END IF;
00214       END IF;
00215    END PROCESS;
00216 
00217 
00218    ------------------------------------------------------------------------------//
00219    -- Create axi_in_packet. This signal tracks if the AXI interface is currently //
00220    -- in the middle of a packet, which is needed in case the link goes down.     //
00221    ------------------------------------------------------------------------------//
00222    PROCESS (USER_CLK)
00223    BEGIN
00224       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00225               IF (USER_RST = '1') THEN
00226                       axi_in_packet <= '0' AFTER (TCQ)*1 ps;
00227               ELSE
00228                       IF (axi_beat_live = '1' AND S_AXIS_TX_TLAST = '0') THEN
00229                               axi_in_packet <= '1' AFTER (TCQ)*1 ps;
00230                       ELSIF (axi_beat_live = '1') THEN
00231                               axi_in_packet <= '0' AFTER (TCQ)*1 ps;
00232                       END IF;
00233               END IF;
00234       END IF;
00235    END PROCESS;
00236 
00237    ------------------------------------------------------------------------------//
00238    -- Create disable_trn. This signal asserts when the link goes down and        //
00239    -- triggers the deassertiong of trn_tsrc_rdy. The deassertion of disable_trn  //
00240    -- depends on C_PM_PRIORITY, as described below.                              //
00241    ------------------------------------------------------------------------------//
00242    PM_PRIORITY_TRN_FLUSH : IF (C_PM_PRIORITY) GENERATE
00243      -- In the C_PM_PRIORITY pipeline, we disable the TRN interfacefrom the time
00244      -- the link goes down until the the AXI interface is ready to accept packets
00245      -- again (via assertion of TREADY). By waiting for TREADY, we allow the
00246      -- previous value buffer to fill, so we're ready for any throttling by the
00247      -- user or the block.
00248 
00249      PROCESS (USER_CLK)
00250      BEGIN
00251         IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00252                 IF (USER_RST = '1') THEN
00253                         reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
00254                 ELSE
00255                         IF (trn_lnk_up = '0') THEN
00256                                 reg_disable_trn <= '1' AFTER (TCQ)*1 ps;
00257                         ELSIF (flush_axi = '0' AND s_axis_tx_tready_xhdl0 = '1') THEN
00258                                 reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
00259                         END IF;
00260                 END IF;
00261         END IF;
00262      END PROCESS;
00263 
00264      disable_trn <= reg_disable_trn;
00265    END GENERATE;
00266 
00267    -- In the throttle-controlled pipeline, we don't have a previous value buffer.
00268    -- The throttle control mechanism handles TREADY, so all we need to do is
00269    -- detect when the link goes down and disable the TRN interface until the link
00270    -- comes back up and the AXI interface is finished flushing any packets.
00271    TNRTL_CTL_TRN_FLUSH : IF (NOT(C_PM_PRIORITY)) GENERATE
00272      PROCESS (USER_CLK)
00273      BEGIN
00274         IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00275                 IF (USER_RST = '1') THEN
00276                         reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
00277                 ELSE
00278                         IF (axi_in_packet = '1' AND trn_lnk_up = '0' AND axi_end_packet = '0') THEN
00279                                 reg_disable_trn <= '1' AFTER (TCQ)*1 ps;
00280                         ELSIF (axi_end_packet = '1') THEN
00281                                 reg_disable_trn <= '0' AFTER (TCQ)*1 ps;
00282                         END IF;
00283                 END IF;
00284         END IF;
00285      END PROCESS;
00286 
00287      disable_trn <= '1' WHEN (reg_disable_trn = '1' OR trn_lnk_up = '0') ELSE '0';
00288    END GENERATE;
00289 
00290 
00291    ------------------------------------------------------------------------------//
00292    -- Convert STRB to RREM. Here, we are converting the encoding method for the  //
00293    -- location of the EOF from AXI (TSTRB) to TRN flavor (rrem).                 //
00294    ------------------------------------------------------------------------------//
00295    xhdl8 : IF (C_DATA_WIDTH = 128) GENERATE
00296    -----------------------------------------
00297    -- Conversion table:
00298    -- trem    | tstrb
00299    -- [1] [0] | [15:12] [11:8] [7:4] [3:0]
00300    -- -------------------------------------
00301    --  1   1  |   D3      D2    D1    D0
00302    --  1   0  |   --      D2    D1    D0
00303    --  0   1  |   --      --    D1    D0
00304    --  0   0  |   --      --    --    D0
00305    -----------------------------------------
00306            axi_DW_1    <= reg_tstrb(7);
00307            axi_DW_2    <= reg_tstrb(11);
00308            axi_DW_3    <= reg_tstrb(15);
00309            TRN_TREM(1) <= axi_DW_2;
00310            TRN_TREM(0) <= (axi_DW_3 OR (axi_DW_1 AND NOT(axi_DW_2)));
00311    END GENERATE;
00312 
00313    xhdl9 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
00314            xhdl10 : IF (C_DATA_WIDTH = 64) GENERATE
00315                    TRN_TREM(0) <= reg_tstrb(7);
00316            END GENERATE;
00317            xhdl11 : IF (NOT(C_DATA_WIDTH = 64)) GENERATE
00318                    TRN_TREM <= x"0";
00319            END GENERATE;
00320    END GENERATE;
00321 
00322    ------------------------------------------------------------------------------
00323    -- Create remaining TRN signals
00324    ------------------------------------------------------------------------------
00325    trn_teof_xhdl1   <= reg_tlast;
00326    TRN_TECRC_GEN    <= reg_tuser(0);
00327    TRN_TERRFWD      <= reg_tuser(1);
00328    TRN_TSTR         <= reg_tuser(2);
00329    TRN_TSRC_DSC     <= reg_tuser(3);
00330 
00331    ------------------------------------------------------------------------------
00332    -- Pipeline stage
00333    ------------------------------------------------------------------------------
00334    -- We need one of two approaches for the pipeline stage depending on the
00335    -- C_PM_PRIORITY parameter.
00336    xhdl12 : IF (NOT(C_PM_PRIORITY)) GENERATE
00337            PROCESS (USER_CLK)
00338            BEGIN
00339                    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00340                            IF (USER_RST = '1') THEN
00341                                    reg_tdata      <= (others => '0') AFTER (TCQ)*1 ps;
00342                                    reg_tvalid     <= '0'  AFTER (TCQ)*1 ps;
00343                                    reg_tstrb      <= (others => '0') AFTER (TCQ)*1 ps;
00344                                    reg_tlast      <= '0'    AFTER (TCQ)*1 ps;
00345                                    reg_tuser      <= (others => '0') AFTER (TCQ)*1 ps;
00346                                    reg_tsrc_rdy   <= '0'    AFTER (TCQ)*1 ps;
00347                            ELSE
00348                                    reg_tdata      <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
00349                                    reg_tvalid     <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
00350                                    reg_tstrb      <= S_AXIS_TX_TSTRB   AFTER (TCQ)*1 ps;
00351                                    reg_tlast      <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
00352                                    reg_tuser      <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
00353 
00354                                    -- Hold trn_tsrc_rdy low when flushing a packet
00355                                    reg_tsrc_rdy   <= (axi_beat_live AND (NOT disable_trn)) AFTER (TCQ)*1 ps;
00356                            END IF;
00357                    END IF;
00358            END PROCESS;
00359 
00360            trn_tsrc_rdy_xhdl3     <= reg_tsrc_rdy;
00361            -- With TX packet boundary throttling, TREADY is pipelined in
00362            -- axi_basic_tx_thrtl_ctl and wired through here.
00363            s_axis_tx_tready_xhdl0 <= TREADY_THRTL;
00364 
00365    END GENERATE;
00366 
00367    --**************************************************************************--
00368 
00369    -- If C_PM_PRIORITY is set to TRUE, that means the user prefers to have all PM
00370    -- functionality intact isntead of TX packet boundary throttling. Now the
00371    -- Block could back-pressure at any time, which creates the standard problem
00372    -- of potential data loss due to the handshaking latency. Here we need a
00373    -- previous value buffer, just like the RX data path.
00374    xhdl13 : IF (C_PM_PRIORITY) GENERATE
00375 
00376     --------------------------------------------------------------------------
00377     -- Previous value buffer
00378     -- ---------------------
00379     -- We are inserting a pipeline stage in between AXI and TRN, which causes
00380     -- some issues with handshaking signals trn_tsrc_rdy/s_axis_tx_tready.
00381     -- The added cycle of latency in the path causes the Block to fall behind
00382     -- the AXI interface whenever it throttles.
00383     --
00384     -- To avoid loss of data, we must keep the previous value of all
00385     -- s_axis_tx_* signals in case the Block throttles.
00386     --------------------------------------------------------------------------
00387            PROCESS (USER_CLK)
00388       BEGIN
00389          IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00390             IF (USER_RST = '1') THEN
00391                tdata_prev     <= (others =>'0' ) AFTER (TCQ)*1 ps;
00392                tvalid_prev    <= '0'             AFTER (TCQ)*1 ps;
00393                tstrb_prev     <= (others =>'0' ) AFTER (TCQ)*1 ps;
00394                tlast_prev     <= '0'             AFTER (TCQ)*1 ps;
00395                tuser_prev     <= "0000"          AFTER (TCQ)*1 ps;
00396             ELSE
00397                -- prev buffer works by checking s_axis_tx_tready. When s_axis_tx_tready is
00398                -- asserted, a new value is present on the interface.
00399                IF ((NOT(s_axis_tx_tready_xhdl0)) = '1') THEN
00400                   tdata_prev  <= tdata_prev   AFTER (TCQ)*1 ps;
00401                   tvalid_prev <= tvalid_prev  AFTER (TCQ)*1 ps;
00402                   tstrb_prev  <= tstrb_prev   AFTER (TCQ)*1 ps;
00403                   tlast_prev  <= tlast_prev   AFTER (TCQ)*1 ps;
00404                   tuser_prev  <= tuser_prev   AFTER (TCQ)*1 ps;
00405                ELSE
00406                   tdata_prev  <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
00407                   tvalid_prev <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
00408                   tstrb_prev  <= S_AXIS_TX_TSTRB   AFTER (TCQ)*1 ps;
00409                   tlast_prev  <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
00410                   tuser_prev  <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
00411                END IF;
00412             END IF;
00413          END IF;
00414       END PROCESS;
00415 
00416       -- Create special buffer which locks in the propper value of TDATA depending
00417       -- on whether the user is throttling or not. This buffer has three states:
00418       --
00419       --       HOLD state: TDATA maintains its current value
00420       --                   - the Block has throttled the PCIe block
00421       --   PREVIOUS state: the buffer provides the previous value on TDATA
00422       --                   - the Block has finished throttling, and is a little
00423       --                     behind the PCIe user
00424       --    CURRENT state: the buffer passes the current value on TDATA
00425       --                   - the Block is caught up and ready to receive the latest
00426       --                     data from the PCIe user
00427       PROCESS (USER_CLK)
00428       BEGIN
00429          IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00430             IF (USER_RST = '1') THEN
00431                reg_tdata <= (others => '0') AFTER (TCQ)*1 ps;
00432                reg_tvalid <= '0'  AFTER (TCQ)*1 ps;
00433                reg_tstrb <= (others => '0')  AFTER (TCQ)*1 ps;
00434                reg_tlast <= '0'  AFTER (TCQ)*1 ps;
00435 
00436                reg_tuser <= (others => '0') AFTER (TCQ)*1 ps;
00437                reg_tdst_rdy <= '0' AFTER (TCQ)*1 ps;
00438             ELSE
00439 
00440                reg_tdst_rdy <= trn_tdst_rdy AFTER (TCQ)*1 ps;
00441                IF ((NOT(data_hold)) = '1') THEN
00442                   -- PREVIOUS state
00443                   IF (data_prev = '1') THEN
00444                      reg_tdata  <= tdata_prev   AFTER (TCQ)*1 ps;
00445                      reg_tvalid <= tvalid_prev AFTER (TCQ)*1 ps;
00446                      reg_tstrb  <= tstrb_prev   AFTER (TCQ)*1 ps;
00447                      reg_tlast  <= tlast_prev   AFTER (TCQ)*1 ps;
00448                      reg_tuser  <= tuser_prev   AFTER (TCQ)*1 ps;
00449                   ELSE
00450                      -- CURRENT state
00451                      reg_tdata  <= S_AXIS_TX_TDATA   AFTER (TCQ)*1 ps;
00452                      reg_tvalid <= S_AXIS_TX_TVALID  AFTER (TCQ)*1 ps;
00453                      reg_tstrb  <= S_AXIS_TX_TSTRB   AFTER (TCQ)*1 ps;
00454                      reg_tlast  <= S_AXIS_TX_TLAST   AFTER (TCQ)*1 ps;
00455                      reg_tuser  <= S_AXIS_TX_TUSER   AFTER (TCQ)*1 ps;
00456                   END IF;
00457                END IF;
00458             -- else HOLD state
00459             END IF;
00460          END IF;
00461       END PROCESS;
00462 
00463 
00464       -- Logic to instruct pipeline to hold its value
00465       data_hold <= ((NOT(TRN_TDST_RDY) AND trn_tsrc_rdy_xhdl3));
00466 
00467      -- Logic to instruct pipeline to use previous bus values. Always use
00468      -- previous value after holding a value.
00469       PROCESS (USER_CLK)
00470       BEGIN
00471          IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00472             IF (USER_RST = '1') THEN
00473                data_prev <= '0'  AFTER (TCQ)*1 ps;
00474             ELSE
00475                data_prev <= data_hold  AFTER (TCQ)*1 ps;
00476             END IF;
00477          END IF;
00478       END PROCESS;
00479 
00480 
00481       --------------------------------------------------------------------------
00482       --  Create trn_tsrc_rdy. If we're flushing the TRN hold trn_tsrc_rdy low.
00483       --------------------------------------------------------------------------
00484       trn_tsrc_rdy_xhdl3 <= reg_tvalid;
00485 
00486       --------------------------------------------------------------------------//
00487       -- Create TREADY                                                          //
00488       --------------------------------------------------------------------------//
00489       PROCESS (USER_CLK)
00490       BEGIN
00491          IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00492             IF (USER_RST = '1') THEN
00493                reg_tready <= '0' AFTER (TCQ)*1 ps;
00494             ELSE
00495                -- If the link went down and we need to flush a packet in flight, hold
00496                -- TREADY high
00497                IF (flush_axi = '1' AND axi_end_packet = '0') THEN
00498                   reg_tready <= '1' AFTER (TCQ)*1 ps;
00499 
00500                -- If the link is up, TREADY is as follows:
00501                --   TREADY = 1 when trn_tsrc_rdy == 0
00502                --      - While idle, keep the pipeline primed and ready for the next
00503                --        packet
00504                --
00505                --   TREADY = trn_tdst_rdy when trn_tsrc_rdy == 1
00506                --      - While in packet, throttle pipeline based on state of TRN
00507                ELSIF(trn_lnk_up = '1') THEN
00508                   reg_tready <= TRN_TDST_RDY OR (NOT trn_tsrc_rdy_xhdl3) AFTER (TCQ)*1 ps;
00509                ELSE
00510                   -- If the link is down and we're not flushing a packet, hold TREADY low
00511                   -- wait for link to come back up
00512                   reg_tready <= '0'  AFTER (TCQ)*1 ps;
00513                END IF;
00514             END IF;
00515          END IF;
00516       END PROCESS;
00517 
00518       s_axis_tx_tready_xhdl0 <= reg_tready;
00519 
00520       ----------------------------------------------------------------------------//
00521       -- Create flush_axi. This signal detects if the link goes down while the    //
00522       -- AXI interface is in packet. In this situation, we need to flush the      //
00523       -- packet through the AXI interface and discard it.                         //
00524       ----------------------------------------------------------------------------//
00525       PROCESS (USER_CLK)
00526       BEGIN
00527          IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00528             IF (USER_RST = '1') THEN
00529                flush_axi <= '0' AFTER (TCQ)*1 ps;
00530             ELSE
00531                -- If the AXI interface is in packet and the link goes down, purge it.
00532                IF (axi_in_packet = '1' AND trn_lnk_up = '0' AND axi_end_packet = '0') THEN
00533                   flush_axi <= '1' AFTER (TCQ)*1 ps;
00534                -- The packet is finished, so we're done flushing.
00535                ELSIF (axi_end_packet = '1') THEN
00536                   flush_axi <= '0' AFTER (TCQ)*1 ps;
00537                END IF;
00538             END IF;
00539          END IF;
00540       END PROCESS;
00541    END GENERATE;
00542 END trans;