DS_DMA
pcie_src/pcie_core64_m1/source_virtex6/axi_basic_rx_null_gen.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_rx_null_gen.vhd
00052 -- Version    : 2.3
00053 --
00054 -- Description:
00055 -- TRN to AXI RX null generator. Generates null packets for use in discontinue situations.
00056 --
00057 -- Notes:
00058 --   Optional notes section.
00059 --
00060 --   Hierarchical:
00061 --     axi_basic_top
00062 --       axi_basic_rx
00063 --         axi_basic_rx_null_gen
00064 --------------------------------------------------------------------------------
00065 -- Library Declarations
00066 --------------------------------------------------------------------------------
00067 LIBRARY ieee;
00068    USE ieee.std_logic_1164.all;
00069    USE ieee.std_logic_unsigned.all;
00070 
00071 ENTITY axi_basic_rx_null_gen IS
00072    GENERIC (
00073       C_DATA_WIDTH              : INTEGER := 128; -- RX/TX interface data width
00074       TCQ                       : INTEGER := 1;   --  Clock to Q time
00075 
00076       C_STRB_WIDTH              : INTEGER := 4   --TSTRB width
00077    );
00078    PORT (
00079       -- AXI RX
00080       M_AXIS_RX_TDATA           : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0) :=(OTHERS=>'0'); -- RX data to user
00081       M_AXIS_RX_TVALID          : IN STD_LOGIC                                   :='0';           -- RX data is valid
00082       M_AXIS_RX_TREADY          : IN STD_LOGIC                                   :='0';           -- RX ready for data
00083       M_AXIS_RX_TLAST           : IN STD_LOGIC                                   :='0';           -- RX data is last
00084       M_AXIS_RX_TUSER           : IN STD_LOGIC_VECTOR(21 DOWNTO 0)               :=(OTHERS=>'0'); -- RX user signals
00085 
00086       -- Null Inputs
00087       NULL_RX_TVALID            : OUT STD_LOGIC                                  ;           -- NULL generated tvalid
00088       NULL_RX_TLAST             : OUT STD_LOGIC                                  ;           -- NULL generated tlast
00089       NULL_RX_TSTRB             : OUT STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0); -- NULL generated tstrb
00090       NULL_RDST_RDY             : OUT STD_LOGIC                                  ;           -- NULL generated rdst_rdy
00091       NULL_IS_EOF               : OUT STD_LOGIC_VECTOR(4 DOWNTO 0)               ; -- NULL generated is_eof
00092 
00093       -- System
00094       USER_CLK                  : IN STD_LOGIC                                   :='0';
00095       USER_RST                  : IN STD_LOGIC                                   :='0'
00096    );
00097 END axi_basic_rx_null_gen;
00098 
00099 ------------------------------------------------------------------------------//
00100 -- NULL packet gnereator state machine                                        //
00101 -- This state machine shadows the TRN RX interface, tracking each packet as   //
00102 -- it's passed to the AXI user. When a disountine is detected, the rx data    //
00103 -- pipeline switches to a NULL packet and clocks that out instead. It does so //
00104 -- by asserting null_mux_sel, which the rx pipeline uses to mux in NULL vals. //
00105 ------------------------------------------------------------------------------//
00106 
00107 ARCHITECTURE TRANS OF axi_basic_rx_null_gen IS
00108 
00109    --   INTERFACE_WIDTH_DWORDS = (C_DATA_WIDTH == 128) ? 11'd4 : (C_DATA_WIDTH == 64) ? 11'd2 : 11'd1;
00110    function if_wdt_dw (
00111      constant wdt   : integer)
00112      return integer is
00113       variable dw : integer := 1;
00114    begin  -- if_wdt_dw
00115  
00116      if (wdt = 128) then
00117        dw := 4;
00118      elsif (wdt = 64) then
00119        dw := 2;
00120      else
00121        dw := 1;
00122      end if;
00123      return dw;
00124    end if_wdt_dw;
00125 
00126    constant INTERFACE_WIDTH_DWORDS : integer := if_wdt_dw(C_DATA_WIDTH);
00127    constant IDLE : std_logic := '0';
00128    constant IN_PACKET : std_logic := '1';
00129       
00130    -- Signals for tracking a packet on the AXI interface
00131    SIGNAL reg_pkt_len_counter   : STD_LOGIC_VECTOR(11 DOWNTO 0);
00132    SIGNAL pkt_len_counter       : STD_LOGIC_VECTOR(11 DOWNTO 0);
00133    SIGNAL pkt_len_counter_dec   : STD_LOGIC_VECTOR(11 DOWNTO 0);
00134    SIGNAL pkt_done              : STD_LOGIC;
00135 
00136    SIGNAL new_pkt_len           : STD_LOGIC_VECTOR(11 DOWNTO 0);
00137    SIGNAL payload_len           : STD_LOGIC_VECTOR(9 DOWNTO 0);
00138    SIGNAL payload_len_tmp       : STD_LOGIC_VECTOR(9 DOWNTO 0) := (others => '0');
00139    SIGNAL packet_fmt            : STD_LOGIC_VECTOR(1 DOWNTO 0);
00140    SIGNAL packet_td             : STD_LOGIC;
00141    SIGNAL packet_overhead       : STD_LOGIC_VECTOR(3 DOWNTO 0);
00142    -- X-HDL generated signals`
00143 
00144    SIGNAL xhdl2                 : STD_LOGIC_VECTOR(2 DOWNTO 0);
00145    SIGNAL reg_is_eof            : STD_LOGIC_VECTOR(4 DOWNTO 0);
00146    SIGNAL xhdl5                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
00147    SIGNAL xhdl7                 : STD_LOGIC_VECTOR(1 DOWNTO 0);
00148    --State machine variables and states
00149    SIGNAL next_state            : STD_LOGIC;
00150    SIGNAL cur_state             : STD_LOGIC;
00151 
00152    -- Declare intermediate signals for referenced outputs
00153    SIGNAL null_rx_tlast_xhdl0   : STD_LOGIC;
00154 
00155    -- Misc.
00156    SIGNAL eof_tstrb             : STD_LOGIC_VECTOR(C_STRB_WIDTH - 1 DOWNTO 0);
00157    SIGNAL straddle_sof          : STD_LOGIC;
00158    SIGNAL eof                   : STD_LOGIC;
00159 
00160 BEGIN
00161 
00162     -- Create signals to detect sof and eof situations. These signals vary depending
00163     -- on the data width.
00164     eof <= M_AXIS_RX_TUSER(21);
00165     SOF_EOF_128 : IF (C_DATA_WIDTH = 128) GENERATE
00166        straddle_sof <= '1' WHEN (M_AXIS_RX_TUSER(14 DOWNTO 13) = "11") ELSE '0';
00167     END GENERATE;
00168 
00169     SOF_EOF_64_32 : IF (C_DATA_WIDTH /= 128) GENERATE
00170        straddle_sof <= '0';
00171     END GENERATE;
00172 
00173     ------------------------------------------------------------------------------//
00174     -- Calculate the length of the packet being presented on the RX interface. To //
00175     -- do so, we need the relevent packet fields that impact total packet length. //
00176     -- These are:                                                                 //
00177     --   - Header length: obtained from bit 1 of FMT field in 1st DWORD of header //
00178     --   - Payload length: obtained from LENGTH field in 1st DWORD of header      //
00179     --   - TLP digist: obtained from TD field in 1st DWORD of header              //
00180     --   - Current data: the number of bytes that have already been presented     //
00181     --                   on the data interface                                    //
00182     --                                                                            //
00183     -- packet length = header + payload + tlp digest - # of DWORDS already        //
00184     --                 transmitted                                                //
00185     --                                                                            //
00186     -- packet_overhead is where we calculate everything except payload.           //
00187     ------------------------------------------------------------------------------//
00188 
00189     -- Drive referenced outputs
00190     NULL_RX_TLAST <= null_rx_tlast_xhdl0;
00191 
00192     XHDL1 : IF (C_DATA_WIDTH = 128) GENERATE
00193        packet_fmt   <= M_AXIS_RX_TDATA(94 DOWNTO 93) WHEN ((straddle_sof) = '1') ELSE  M_AXIS_RX_TDATA(30 DOWNTO 29);
00194        packet_td    <= M_AXIS_RX_TDATA(79) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(15);
00195        payload_len_tmp  <= M_AXIS_RX_TDATA(73 DOWNTO 64) WHEN (straddle_sof = '1') ELSE M_AXIS_RX_TDATA(9 DOWNTO 0);
00196        payload_len  <= payload_len_tmp WHEN ((packet_fmt(1)) = '1') ELSE  (others => '0');
00197 
00198        xhdl2 <= packet_fmt(0) & packet_td & straddle_sof;
00199        -- In 128-bit mode, the amount of data currently on the interface
00200        -- depends on whether we're straddling or not. If so, 2 DWORDs have been
00201        -- seen. If not, 4 DWORDs.
00202        PROCESS (xhdl2)
00203        BEGIN
00204                CASE xhdl2 IS
00205                        WHEN "000" =>
00206                                packet_overhead <= "0011" + "0000" - "0100";
00207                        WHEN "001" =>
00208                                packet_overhead <= "0011" + "0000" - "0010";
00209                        WHEN "010" =>
00210                                packet_overhead <= "0011" + "0001" - "0100";
00211                        WHEN "011" =>
00212                                packet_overhead <= "0011" + "0001" - "0010";
00213                        WHEN "100" =>
00214                                packet_overhead <= "0100" + "0000" - "0100";
00215                        WHEN "101" =>
00216                                packet_overhead <= "0100" + "0000" - "0010";
00217                        WHEN "110" =>
00218                                packet_overhead <= "0100" + "0001" - "0100";
00219                        WHEN "111" =>
00220                                packet_overhead <= "0100" + "0001" - "0010";
00221                        WHEN OTHERS =>
00222                                packet_overhead <= "0000" + "0000" - "0000";
00223                END CASE;
00224        END PROCESS;
00225        END GENERATE;
00226 
00227       XHDL4 : IF (C_DATA_WIDTH = 64) GENERATE
00228               packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
00229               packet_td <= M_AXIS_RX_TDATA(15);
00230               payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE  "0000000000";
00231 
00232               xhdl5 <= packet_fmt(0) & packet_td;
00233               --  64-bit mode: no straddling, so always 2 DWORDs
00234               PROCESS (packet_fmt, packet_td,xhdl5)
00235               BEGIN
00236                       CASE xhdl5 IS
00237                                                       -- Header +   TD   - Data currently on interface
00238                               WHEN "00" =>
00239                                       packet_overhead <= "0011" + "0000" - "0010";
00240                               WHEN "01" =>
00241                                       packet_overhead <= "0011" + "0001" - "0010";
00242                               WHEN "10" =>
00243                                       packet_overhead <= "0100" + "0000" - "0010";
00244                               WHEN "11" =>
00245                                       packet_overhead <= "0100" + "0001" - "0010";
00246                               WHEN OTHERS =>
00247                                       packet_overhead <= "0000" + "0000" - "0000";
00248                       END CASE;
00249               END PROCESS;
00250       END GENERATE;
00251 
00252     XHDL6 : IF (C_DATA_WIDTH = 32) GENERATE
00253             packet_fmt <= M_AXIS_RX_TDATA(30 DOWNTO 29);
00254             packet_td <= M_AXIS_RX_TDATA(15);
00255             payload_len <= M_AXIS_RX_TDATA(9 DOWNTO 0) WHEN ((packet_fmt(1)) = '1') ELSE "0000000000";
00256 
00257             xhdl7 <= packet_fmt(0) & packet_td;
00258             -- 32-bit mode: no straddling, so always 1 DWORD
00259             PROCESS (packet_fmt, packet_td,xhdl7)
00260             BEGIN
00261                     CASE xhdl7 IS
00262                             WHEN "00" =>
00263                                     packet_overhead <= "0011" + "0000" - "0001";
00264                             WHEN "01" =>
00265                                     packet_overhead <= "0011" + "0001" - "0001";
00266                             WHEN "10" =>
00267                                     packet_overhead <= "0100" + "0000" - "0001";
00268                             WHEN "11" =>
00269                                     packet_overhead <= "0100" + "0001" - "0001";
00270                             WHEN OTHERS =>
00271                                     packet_overhead <= "0000" + "0000" - "0000";
00272                     END CASE;
00273             END PROCESS;
00274     END GENERATE;
00275     --END GENERATE;
00276     -- Now calculate actual packet length, adding the packet overhead and the
00277     -- payload length. This is signed math, so sign-extend packet_overhead.
00278     -- NOTE: a payload length of zero means 1024 DW in the PCIe spec, but this behavior isn't supported in our block.
00279 
00280     new_pkt_len <= (packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(3) & packet_overhead(2 DOWNTO 0)) + ("00" & payload_len);
00281 
00282 
00283     -- Math signals needed in the state machine below. These are seperate wires to
00284     -- help ensure synthesis tools are smart about optimizing them.
00285     pkt_len_counter_dec <= reg_pkt_len_counter - INTERFACE_WIDTH_DWORDS;
00286     pkt_done <= '1' WHEN (reg_pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0';
00287 
00288 
00289     PROCESS (cur_state, M_AXIS_RX_TVALID, M_AXIS_RX_TREADY, eof, new_pkt_len, reg_pkt_len_counter, pkt_len_counter_dec)
00290     BEGIN
00291 
00292        CASE cur_state IS
00293           -- IDLE state: the interface is IDLE and we're waiting for a packet to
00294           -- start. If a packet starts, move to state IN_PACKET and begin tracking it as long as it's NOT
00295           -- a signle cycle packet (indicated by assertion of eof at packet start)
00296                WHEN IDLE =>
00297                        IF ((M_AXIS_RX_TVALID = '1') and (M_AXIS_RX_TREADY = '1') and (eof = '0')) THEN next_state <= IN_PACKET;
00298                        ELSE
00299                                next_state <= IDLE;
00300                        END IF;
00301                        pkt_len_counter <= new_pkt_len;
00302                        -- IN_PACKET: a multi -cycle packet is in progress and we're tracking it. We are
00303                        -- in lock-step with the AXI interface decrementing our packet length
00304                        -- tracking reg, and waiting for the packet to finish.
00305                        -- If packet finished and a new one starts, this is a straddle situation.
00306                        -- Next state is IN_PACKET (128-bit only).
00307                        -- If the current packet is done, next state is IDLE.
00308                        -- Otherwise, next state is IN_PACKET.
00309                WHEN IN_PACKET =>
00310                        -- Straddle packet
00311                        IF ((C_DATA_WIDTH = 128) AND straddle_sof = '1' AND M_AXIS_RX_TVALID = '1') THEN
00312                               pkt_len_counter <= new_pkt_len;
00313                               next_state <= IN_PACKET;
00314                                -- Current packet finished
00315                        ELSIF (M_AXIS_RX_TREADY = '1' AND pkt_done = '1') THEN
00316                               pkt_len_counter <= new_pkt_len;
00317                               next_state <= IDLE ;
00318 
00319                        ELSE
00320                               IF (M_AXIS_RX_TREADY = '1') THEN
00321                                     -- Packet in progress
00322                                     pkt_len_counter <= pkt_len_counter_dec;
00323                               ELSE
00324                                     -- Throttled
00325                                     pkt_len_counter <= reg_pkt_len_counter;
00326                               END IF;
00327 
00328                               next_state <= IN_PACKET;
00329                        END IF;
00330              WHEN OTHERS =>
00331                      pkt_len_counter <= reg_pkt_len_counter;
00332                      next_state <= IDLE ;
00333      END CASE;
00334      END PROCESS;
00335 
00336     --Synchronous NULL packet generator state machine logic
00337     PROCESS (USER_CLK)
00338     BEGIN
00339        IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00340                IF (USER_RST = '1') THEN
00341                        cur_state <= IDLE  AFTER (TCQ)*1 ps;
00342                        reg_pkt_len_counter <= (others => '0')  AFTER (TCQ)*1 ps;
00343                ELSE
00344                        cur_state <= next_state AFTER (TCQ)*1 ps;
00345                        reg_pkt_len_counter <= pkt_len_counter  AFTER (TCQ)*1 ps;
00346                END IF;
00347        END IF;
00348        END PROCESS;
00349 
00350     --Generate TSTRB/is_eof for an end-of-packet situation.
00351     XHDL8 : IF (C_DATA_WIDTH = 128) GENERATE
00352             -- Assign null_is_eof depending on how many DWORDs are left in the packet.
00353             PROCESS (pkt_len_counter)
00354             BEGIN
00355                     CASE pkt_len_counter IS
00356                             WHEN "000000000001" =>
00357                                     null_is_eof <= "10011";
00358                             WHEN "000000000010" =>
00359                                     null_is_eof <= "10111";
00360                             WHEN "000000000011" =>
00361                                     null_is_eof <= "11011";
00362                             WHEN "000000000100" =>
00363                                     null_is_eof <= "11111";
00364                             WHEN OTHERS =>
00365                                     null_is_eof <= "00011";
00366                     END CASE;
00367             END PROCESS;
00368 
00369             --TSTRB not used in 128-bit interface
00370             eof_tstrb <= (others => '0') ; --'0' & '0' & '0' & '0';
00371     END GENERATE;
00372 
00373     XHDL9 : IF (NOT(C_DATA_WIDTH = 128)) GENERATE
00374        XHDL10 : IF (C_DATA_WIDTH = 64) GENERATE
00375             -- Assign null_is_eof depending on how many DWORDs are left in the packet.
00376             PROCESS (pkt_len_counter)
00377             BEGIN
00378                     CASE pkt_len_counter IS
00379                             WHEN "000000000001" =>
00380                                     null_is_eof <= "10011";
00381                             WHEN "000000000010" =>
00382                                     null_is_eof <= "10111";
00383                             WHEN OTHERS =>
00384                                     null_is_eof <= "00011";
00385                     END CASE;
00386             END PROCESS;
00387 
00388                -- Assign TSTRB to 0xFF or 0x0F depending on how many DWORDs are left in the current packet.
00389                eof_tstrb <= X"FF" WHEN (pkt_len_counter = "000000000010") ELSE X"0F";
00390        END GENERATE;
00391 
00392        XHDL11 : IF (NOT(C_DATA_WIDTH = 64)) GENERATE
00393             PROCESS (pkt_len_counter)
00394             BEGIN
00395                     --is_eof is either on or off in 32-bit interface
00396                     IF (pkt_len_counter = "000000000001") THEN
00397                             null_is_eof <= "10011";
00398                     ELSE
00399                             null_is_eof <= "10011";
00400                     END IF;
00401             END PROCESS;
00402 
00403                --The entire DWORD is always valid in 32-bit mode, so TSTRB is always 0xF
00404                eof_tstrb <= "1111";
00405        END GENERATE;
00406        END GENERATE;
00407 
00408     --Finally, use everything we've generated to calculate our NULL outputs
00409        NULL_RX_TVALID <= '1';
00410        null_rx_tlast_xhdl0 <= '1' WHEN (pkt_len_counter <= INTERFACE_WIDTH_DWORDS) ELSE '0' ;
00411        NULL_RX_TSTRB <= eof_tstrb WHEN (null_rx_tlast_xhdl0 = '1') ELSE  (others => '1');
00412        NULL_RDST_RDY <= null_rx_tlast_xhdl0 ;
00413 END TRANS;
00414 
00415