DS_DMA
pcie_src/pcie_core64_m1/source_virtex6/axi_basic_tx_thrtl_ctl.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_thrtl_ctl.vhd
00052 -- Version    : 2.3
00053 --
00054 -- Description:
00055 --    TX throttle controller. Anticipates back-pressure from PCIe block and
00056 --      preemptively back-pressures user design (packet boundary throttling).
00057 --
00058 --      Notes:
00059 --      Optional notes section.
00060 --
00061 --      Hierarchical:
00062 --        axi_basic_top
00063 --          axi_basic_tx
00064 --            axi_basic_tx_thrtl_ctl
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_thrtl_ctl IS
00075    GENERIC (
00076       C_DATA_WIDTH              : INTEGER := 128;      -- RX/TX interface data width
00077       C_FAMILY                  : STRING := "X7";      -- Targeted FPGA family
00078       C_ROOT_PORT               : BOOLEAN := FALSE;   -- PCIe block is in root port mode
00079       TCQ                       : INTEGER := 1         -- Clock to Q time
00080    );
00081    PORT (
00082      -- AXI TX
00083      -------------
00084       S_AXIS_TX_TDATA           : IN STD_LOGIC_VECTOR(C_DATA_WIDTH - 1 DOWNTO 0)  := (OTHERS=>'0'); -- TX data from user
00085       S_AXIS_TX_TVALID          : IN STD_LOGIC                     := '0';    -- TX data is valid
00086       S_AXIS_TX_TUSER           : IN STD_LOGIC_VECTOR(3 DOWNTO 0)  := "0000"; -- TX user signals
00087       S_AXIS_TX_TLAST           : IN STD_LOGIC                     := '0';    -- TX data is last
00088 
00089      -- User Misc.
00090      -------------
00091       USER_TURNOFF_OK           : IN STD_LOGIC                     := '0';    -- Turnoff OK from user
00092       USER_TCFG_GNT             : IN STD_LOGIC                     := '0';    -- Send cfg OK from user
00093 
00094      -- TRN TX
00095      -------------
00096       TRN_TBUF_AV               : IN STD_LOGIC_VECTOR(5 DOWNTO 0)  := "000000"; -- TX buffers available
00097       TRN_TDST_RDY              : IN STD_LOGIC                     := '0';     -- TX destination ready
00098 
00099      -- TRN Misc.
00100      -------------
00101       TRN_TCFG_REQ              : IN STD_LOGIC                     := '0';     -- TX config request
00102       TRN_TCFG_GNT              : OUT STD_LOGIC                    ;--:= '0';     -- RX config grant
00103       TRN_LNK_UP                : IN STD_LOGIC                     := '0';     -- PCIe link up
00104 
00105      -- 7 Series/Virtex6 PM
00106      -------------
00107       CFG_PCIE_LINK_STATE       : IN STD_LOGIC_VECTOR(2 DOWNTO 0)  := "000";    -- Encoded PCIe link state
00108 
00109      -- Virtex6 PM
00110      -------------
00111       CFG_PM_SEND_PME_TO        : IN STD_LOGIC                     := '0';              -- PM send PME turnoff msg
00112       CFG_PMCSR_POWERSTATE      : IN STD_LOGIC_VECTOR(1 DOWNTO 0)  := "00";             -- PMCSR power state
00113       TRN_RDLLP_DATA            : IN STD_LOGIC_VECTOR(31 DOWNTO 0) := x"00000000";      -- RX DLLP data
00114       TRN_RDLLP_SRC_RDY         : IN STD_LOGIC                     := '0';              -- RX DLLP source ready
00115 
00116      -- Virtex6/Spartan6 PM
00117      -------------
00118       CFG_TO_TURNOFF            : IN STD_LOGIC                     := '0';    -- Turnoff request
00119       CFG_TURNOFF_OK            : OUT STD_LOGIC                    ;--:= '0';    -- Turnoff grant
00120 
00121      -- System
00122      -------------
00123       TREADY_THRTL              : OUT STD_LOGIC                    ;--:= '0';   -- TREADY to pipeline
00124       USER_CLK                  : IN STD_LOGIC                     := '0';   -- user clock from block
00125       USER_RST                  : IN STD_LOGIC                     := '0'    -- user reset from block
00126    );
00127 END axi_basic_tx_thrtl_ctl;
00128 
00129 ARCHITECTURE trans OF axi_basic_tx_thrtl_ctl IS
00130 
00131    function tbuf_av_min_fn (
00132      constant wdt   : integer)
00133      return integer is
00134       variable buf_min : integer := 1;
00135    begin  -- tbuf_av_min_fn
00136  
00137      if (wdt = 128) then
00138        buf_min := 5;
00139      elsif (wdt = 64) then
00140        buf_min := 1;
00141      else
00142        buf_min := 0;
00143      end if;
00144      return buf_min;
00145    end tbuf_av_min_fn;
00146 
00147    function tbuf_gap_time_fn (
00148      constant wdt   : integer)
00149      return integer is
00150       variable gap_time : integer := 1;
00151    begin  -- tbuf_gap_time_fn
00152  
00153      if (wdt = 128) then
00154        gap_time := 4;
00155      else
00156        gap_time := 1;
00157      end if;
00158      return gap_time;
00159    end tbuf_gap_time_fn;
00160 
00161    -- Thrtl user when TBUF hits this val
00162    CONSTANT TBUF_AV_MIN               : INTEGER :=  tbuf_av_min_fn(C_DATA_WIDTH);
00163 
00164    -- Pause user when TBUF hits this val
00165    CONSTANT TBUF_AV_GAP               : INTEGER :=  TBUF_AV_MIN + 1;
00166 
00167    -- GAP pause time - the latency from the time a packet is accepted on the TRN
00168    -- interface to the time trn_tbuf_av from the Block will decrement.
00169    CONSTANT TBUF_GAP_TIME             : INTEGER :=  tbuf_gap_time_fn(C_DATA_WIDTH);
00170 
00171    -- Latency time from when tcfg_gnt is asserted to when PCIe block will throttle
00172    CONSTANT TCFG_LATENCY_TIME         : INTEGER :=  2;
00173 
00174    CONSTANT LINKSTATE_L0              : INTEGER := 0;
00175    CONSTANT LINKSTATE_PPM_L1          : INTEGER := 1;
00176    CONSTANT LINKSTATE_PPM_L1_TRANS    : INTEGER := 5;
00177    CONSTANT LINKSTATE_PPM_L23R_TRANS  : INTEGER := 6;
00178    CONSTANT PM_ENTER_L1               : INTEGER := 32;
00179    CONSTANT POWERSTATE_D0             : INTEGER := 0;
00180 
00181    SIGNAL lnk_up_thrtl           : STD_LOGIC;
00182    SIGNAL lnk_up_trig            : STD_LOGIC;
00183    SIGNAL lnk_up_exit            : STD_LOGIC;
00184    SIGNAL tbuf_av_min_thrtl      : STD_LOGIC;
00185    SIGNAL tbuf_av_min_trig       : STD_LOGIC;
00186    SIGNAL tbuf_av_gap_thrtl      : STD_LOGIC;
00187    SIGNAL tbuf_gap_cnt           : STD_LOGIC_VECTOR(2 DOWNTO 0);
00188    SIGNAL tbuf_gap_cnt_t         : STD_LOGIC_VECTOR(2 DOWNTO 0);
00189    SIGNAL tbuf_av_gap_trig       : STD_LOGIC;
00190    SIGNAL tbuf_av_gap_exit       : STD_LOGIC;
00191    SIGNAL gap_trig_tlast         : STD_LOGIC;
00192    SIGNAL gap_trig_tlast_1       : STD_LOGIC;
00193    SIGNAL gap_trig_decr          : STD_LOGIC;
00194    SIGNAL gap_trig_decr_1        : STD_LOGIC;
00195    SIGNAL gap_trig_decr_2        : STD_LOGIC;
00196    SIGNAL tbuf_av_d              : STD_LOGIC_VECTOR(5 DOWNTO 0);
00197    SIGNAL tcfg_req_thrtl         : STD_LOGIC;
00198    SIGNAL tcfg_req_cnt           : STD_LOGIC_VECTOR(1 DOWNTO 0);
00199    SIGNAL trn_tdst_rdy_d         : STD_LOGIC;
00200    SIGNAL tcfg_req_trig          : STD_LOGIC;
00201    SIGNAL tcfg_req_exit          : STD_LOGIC;
00202    SIGNAL pre_throttle           : STD_LOGIC;
00203    SIGNAL reg_throttle           : STD_LOGIC;
00204    SIGNAL exit_crit              : STD_LOGIC;
00205    SIGNAL reg_tcfg_gnt           : STD_LOGIC;
00206    SIGNAL trn_tcfg_req_d         : STD_LOGIC;
00207    SIGNAL tcfg_gnt_pending       : STD_LOGIC;
00208    SIGNAL wire_to_turnoff        : STD_LOGIC;
00209    SIGNAL reg_turnoff_ok         : STD_LOGIC;
00210    SIGNAL tready_thrtl_mux       : STD_LOGIC;
00211    SIGNAL ppm_L1_thrtl           : STD_LOGIC;
00212    SIGNAL ppm_L1_trig            : STD_LOGIC;
00213    SIGNAL ppm_L1_exit            : STD_LOGIC;
00214    SIGNAL cfg_pcie_link_state_d  : STD_LOGIC_VECTOR(2 DOWNTO 0);
00215    SIGNAL trn_rdllp_src_rdy_d    : STD_LOGIC;
00216    SIGNAL ppm_L23_thrtl          : STD_LOGIC;
00217    SIGNAL ppm_L23_trig           : STD_LOGIC;
00218    SIGNAL cfg_turnoff_ok_pending : STD_LOGIC;
00219    SIGNAL reg_tlast              : STD_LOGIC;
00220    SIGNAL cur_state              : STD_LOGIC;
00221    SIGNAL next_state             : STD_LOGIC;
00222 
00223    SIGNAL reg_axi_in_pkt         : STD_LOGIC;
00224    SIGNAL axi_in_pkt             : STD_LOGIC;
00225    SIGNAL axi_pkt_ending         : STD_LOGIC;
00226    SIGNAL axi_throttled          : STD_LOGIC;
00227    SIGNAL axi_thrtl_ok           : STD_LOGIC;
00228    SIGNAL tx_ecrc_pause          : STD_LOGIC;
00229 
00230    SIGNAL gap_trig_tcfg          : STD_LOGIC;
00231    SIGNAL reg_to_turnoff         : STD_LOGIC;
00232    SIGNAL reg_tx_ecrc_pkt        : STD_LOGIC;
00233 
00234    SIGNAL tx_ecrc_pkt            : STD_LOGIC;
00235    SIGNAL packet_fmt             : STD_LOGIC_VECTOR(1 DOWNTO 0);
00236    SIGNAL packet_td              : STD_LOGIC;
00237    SIGNAL header_len             : STD_LOGIC_VECTOR(2 DOWNTO 0);
00238    SIGNAL payload_len            : STD_LOGIC_VECTOR(9 DOWNTO 0);
00239    SIGNAL packet_len             : STD_LOGIC_VECTOR(13 DOWNTO 0);
00240    SIGNAL pause_needed           : STD_LOGIC;
00241 
00242    -- Declare intermediate signals for referenced outputs
00243    SIGNAL trn_tcfg_gnt_xhdl2     : STD_LOGIC;
00244    SIGNAL cfg_turnoff_ok_xhdl0   : STD_LOGIC;
00245    SIGNAL tready_thrtl_xhdl1     : STD_LOGIC;
00246 --   TYPE T_STATE is  (IDLE_A,THROTTLE);
00247 --   SIGNAL CUR_STATE_A, NEXT_STATE_A : T_STATE;
00248    SIGNAL CUR_STATE_A, NEXT_STATE_A : STD_LOGIC;
00249 
00250    constant IDLE : std_logic := '0';
00251    constant THROTTLE : std_logic := '1';
00252 
00253 BEGIN
00254    -- Drive referenced outputs
00255    TRN_TCFG_GNT     <= trn_tcfg_gnt_xhdl2;
00256    CFG_TURNOFF_OK   <= cfg_turnoff_ok_xhdl0;
00257    TREADY_THRTL     <= tready_thrtl_xhdl1;
00258     --------------------------------------------------------------------------------
00259     -- THROTTLE REASON: PCIe link is down                                         --
00260     --   - When to throttle: trn_lnk_up deasserted                                --
00261     --   - When to stop: trn_tdst_rdy assesrted                                   --
00262     --------------------------------------------------------------------------------
00263    lnk_up_trig      <= NOT(TRN_LNK_UP);
00264    lnk_up_exit      <= TRN_TDST_RDY;
00265 
00266    PROCESS (USER_CLK)
00267    BEGIN
00268            IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00269                    IF (USER_RST = '1') THEN
00270                            lnk_up_thrtl <= '1'  AFTER (TCQ)*1 ps;
00271                    ELSE
00272                            IF (lnk_up_trig = '1') THEN
00273                                    lnk_up_thrtl <= '1'   AFTER (TCQ)*1 ps;
00274                            ELSIF (lnk_up_exit = '1') THEN
00275                                    lnk_up_thrtl <= '0'   AFTER (TCQ)*1 ps;
00276                            END IF;
00277                    END IF;
00278            END IF;
00279    END PROCESS;
00280 
00281   --------------------------------------------------------------------------------
00282   -- THROTTLE REASON: Transmit buffers depleted                                 --
00283   --   - When to throttle: trn_tbuf_av falls to 0                               --
00284   --   - When to stop: trn_tbuf_av rises above 0 again                          --
00285   --------------------------------------------------------------------------------
00286    tbuf_av_min_trig <= '1' WHEN (TRN_TBUF_AV <= TBUF_AV_MIN) ELSE '0';
00287 
00288    PROCESS (USER_CLK)
00289    BEGIN
00290       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00291               IF (USER_RST = '1') THEN
00292                       tbuf_av_min_thrtl <= '0'   AFTER (TCQ)*1 ps;
00293               ELSE
00294                       IF (tbuf_av_min_trig = '1') THEN
00295                               tbuf_av_min_thrtl <= '1'  AFTER (TCQ)*1 ps;
00296                       -- The exit condition for tbuf_av_min_thrtl is !tbuf_av_min_trig
00297                       ELSE
00298                               tbuf_av_min_thrtl <= '0'  AFTER (TCQ)*1 ps;
00299                       END IF;
00300               END IF;
00301       END IF;
00302    END PROCESS;
00303 
00304    ------------------------------------------------------------------------------//
00305    -- THROTTLE REASON: Transmit buffers getting low                              //
00306    --   - When to throttle: trn_tbuf_av falls below "gap" threshold TBUF_AV_GAP  //
00307    --   - When to stop: after TBUF_GAP_TIME cycles elapse                        //
00308    --                                                                            //
00309    -- If we're about to run out of transmit buffers, throttle the user for a     //
00310    -- few clock cycles to give the PCIe block time to catch up. This is          //
00311    -- needed to compensate for latency in decrementing trn_tbuf_av in the PCIe   //
00312    -- Block transmit path.                                                       //
00313    ------------------------------------------------------------------------------//
00314 
00315    -- Detect two different scenarios for buffers getting low:
00316    -- 1) If we see a TLAST. a new packet has been inserted into the buffer, and
00317    --    we need to pause and let that packet "soak in"
00318    gap_trig_tlast_1 <=  '1' WHEN (TRN_TBUF_AV <= TBUF_AV_GAP) ELSE '0';
00319    gap_trig_tlast   <=  (gap_trig_tlast_1 AND S_AXIS_TX_TVALID AND tready_thrtl_xhdl1 AND S_AXIS_TX_TLAST );
00320 
00321    -- 2) Any time tbug_avail decrements to the TBUF_AV_GAP threshold, we need to
00322    --    pause and make sure no other packets are about to soak in and cause the
00323    --    buffer availability to drop further.
00324    gap_trig_decr_1    <=  '1' WHEN ( TRN_TBUF_AV = TBUF_AV_GAP) ELSE '0' ;
00325    gap_trig_decr_2  <=  '1' WHEN (tbuf_av_d = TBUF_AV_GAP + 1) ELSE '0' ;
00326 
00327    gap_trig_decr    <= ( gap_trig_decr_1 AND gap_trig_decr_2);
00328 
00329    gap_trig_tcfg    <= ((tcfg_req_thrtl AND tcfg_req_exit));
00330    tbuf_av_gap_trig <= (gap_trig_tlast OR gap_trig_decr OR gap_trig_tcfg) ;
00331    tbuf_av_gap_exit <= '1' WHEN (tbuf_gap_cnt = "000") ELSE '0' ;
00332    tbuf_gap_cnt_t   <= "100" WHEN (C_DATA_WIDTH = 128) ELSE "001";
00333    PROCESS (USER_CLK)
00334    BEGIN
00335            IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00336                    IF (USER_RST = '1') THEN
00337                            tbuf_av_gap_thrtl <= '0'       AFTER (TCQ)*1 ps;
00338                            tbuf_gap_cnt      <= "000"     AFTER (TCQ)*1 ps;
00339                            tbuf_av_d         <= "000000"  AFTER (TCQ)*1 ps;
00340                    ELSE
00341                            IF (tbuf_av_gap_trig = '1') THEN
00342                                    tbuf_av_gap_thrtl <= '1'   AFTER (TCQ)*1 ps;
00343                            ELSIF (tbuf_av_gap_exit = '1') THEN
00344                                    tbuf_av_gap_thrtl <= '0'   AFTER (TCQ)*1 ps;
00345                            END IF;
00346                            -- tbuf gap counter:
00347                            -- This logic controls the length of the throttle condition when tbufs are
00348                            -- getting low.
00349                            IF (tbuf_av_gap_thrtl = '1' AND (CUR_STATE_A = THROTTLE)) THEN
00350                                    IF (tbuf_gap_cnt > "000") THEN
00351                                            tbuf_gap_cnt <= tbuf_gap_cnt - "001"  AFTER (TCQ)*1 ps;
00352                                    END IF;
00353                            ELSE
00354                                    tbuf_gap_cnt <= tbuf_gap_cnt_t AFTER (TCQ)*1 ps;
00355                            END IF;
00356                            tbuf_av_d <= TRN_TBUF_AV  AFTER (TCQ)*1 ps;
00357                    END IF;
00358            END IF;
00359    END PROCESS;
00360 
00361    ------------------------------------------------------------------------------
00362    -- THROTTLE REASON: Block needs to send a CFG response
00363    --   - When to throttle: trn_tcfg_req and user_tcfg_gnt asserted
00364    --   - When to stop: after trn_tdst_rdy transitions to unasserted
00365    --
00366    -- If the block needs to send a response to a CFG packet, this will cause
00367    -- the subsequent deassertion of trn_tdst_rdy. When the user design permits,
00368    -- grant permission to the block to service request and throttle the user.
00369    ------------------------------------------------------------------------------
00370 
00371    tcfg_req_trig <= (TRN_TCFG_REQ AND reg_tcfg_gnt);
00372    tcfg_req_exit <= '1' WHEN (tcfg_req_cnt = "00" AND trn_tdst_rdy_d = '0' AND  TRN_TDST_RDY ='1') ELSE '0';
00373 
00374    PROCESS (USER_CLK)
00375    BEGIN
00376       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00377               IF (USER_RST = '1') THEN
00378                       tcfg_req_thrtl   <= '0'   AFTER (TCQ)*1 ps;
00379                       trn_tcfg_req_d   <= '0'   AFTER (TCQ)*1 ps;
00380                       trn_tdst_rdy_d   <= '1'   AFTER (TCQ)*1 ps;
00381                       reg_tcfg_gnt     <= '0'   AFTER (TCQ)*1 ps;
00382                       tcfg_req_cnt     <= "00"  AFTER (TCQ)*1 ps;
00383                       tcfg_gnt_pending <= '0'   AFTER (TCQ)*1 ps;
00384               ELSE
00385                       IF (tcfg_req_trig = '1') THEN
00386                               tcfg_req_thrtl <= '1'  AFTER (TCQ)*1 ps;
00387                       ELSIF (tcfg_req_exit = '1') THEN
00388                               tcfg_req_thrtl <= '0'  AFTER (TCQ)*1 ps;
00389                       END IF;
00390                       -- We need to wait the appropriate amount of time for the tcfg_gnt to
00391                       -- "sink in" to the PCIe block. After that, we know that the PCIe block will
00392                       -- not reassert trn_tdst_rdy until the CFG request has been serviced. If a
00393                       -- new request is being service (trn_tcfg_gnt == 1), then reset the timer.
00394                       IF ((NOT(trn_tcfg_req_d = '1' ) AND TRN_TCFG_REQ = '1' ) OR tcfg_gnt_pending = '1') THEN
00395                               -- As TCFG_LATENCY_TIME value is 2
00396                               tcfg_req_cnt <= "10"  AFTER (TCQ)*1 ps;
00397                       ELSE
00398                               IF (tcfg_req_cnt > "00") THEN
00399                                       tcfg_req_cnt <= tcfg_req_cnt - "01"  AFTER (TCQ)*1 ps;
00400                               END IF;
00401                       END IF;
00402                       -- Make sure trn_tcfg_gnt pulses once for one clock cycle for every
00403                       -- cfg packet request.
00404                       IF (TRN_TCFG_REQ = '1' AND NOT(trn_tcfg_req_d = '1' )) THEN
00405                               tcfg_gnt_pending   <= '1' AFTER (TCQ)*1 ps;
00406                       ELSIF (trn_tcfg_gnt_xhdl2 = '1') THEN
00407                               tcfg_gnt_pending   <= '0' AFTER (TCQ)*1 ps;
00408                       END IF;
00409 
00410                       trn_tcfg_req_d   <= TRN_TCFG_REQ   AFTER (TCQ)*1 ps;
00411                       trn_tdst_rdy_d   <= TRN_TDST_RDY   AFTER (TCQ)*1 ps;
00412                       reg_tcfg_gnt     <= USER_TCFG_GNT  AFTER (TCQ)*1 ps;
00413               END IF;
00414       END IF;
00415    END PROCESS;
00416 
00417    ------------------------------------------------------------------------------
00418    -- THROTTLE REASON: Block needs to transition to low power state PPM L1
00419    --   - When to throttle: appropriate low power state signal asserted
00420    --     (architecture dependent)
00421    --   - When to stop: cfg_pcie_link_state goes to proper value (C_ROOT_PORT
00422    --     dependent)
00423    --
00424    -- If the block needs to transition to PM state PPM L1, we need to finish
00425    -- up what we're doing and throttle immediately.
00426    ------------------------------------------------------------------------------
00427    xhdl3 : IF ((C_FAMILY = "X7") AND (C_ROOT_PORT)) GENERATE
00428            -- PPM L1 signals for 7 Series in RC mode
00429            ppm_L1_trig <=  '1' WHEN ((cfg_pcie_link_state_d = "000") AND (CFG_PCIE_LINK_STATE = "101")) ELSE '0';
00430            ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "001") ELSE '0';
00431    END GENERATE;
00432 
00433   -- PPM L1 signals for 7 Series in EP mode
00434    xhdl4 : IF (NOT((C_FAMILY = ("X7")) AND (C_ROOT_PORT))) GENERATE
00435            xhdl5 : IF ((C_FAMILY = ("X7")) AND (NOT(C_ROOT_PORT))) GENERATE
00436                    ppm_L1_trig <= '1' WHEN ((cfg_pcie_link_state_d = "000") AND (CFG_PCIE_LINK_STATE = "101")) ELSE '0';
00437                    ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "000") ELSE '0';
00438            END GENERATE;
00439       -- PPM L1 signals for V6 in RC mode
00440            xhdl6 : IF (NOT((C_FAMILY = ("X7")) AND (NOT(C_ROOT_PORT)))) GENERATE
00441                    xhdl7 : IF ((C_FAMILY = ("V6")) AND (C_ROOT_PORT)) GENERATE
00442                            ppm_L1_trig <= '1' WHEN ((TRN_RDLLP_DATA(31 DOWNTO 24) = x"20") AND TRN_RDLLP_SRC_RDY = '1' AND trn_rdllp_src_rdy_d = '0') ELSE '0';
00443                            ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "001") ELSE '0';
00444                    END GENERATE;
00445          -- PPM L1 signals for V6 in EP mode
00446                    xhdl8 : IF (NOT((C_FAMILY = ("V6")) AND (C_ROOT_PORT))) GENERATE
00447                            xhdl9 : IF ((C_FAMILY = ("V6")) AND (NOT(C_ROOT_PORT))) GENERATE
00448                                    ppm_L1_trig <= '1' WHEN (CFG_PMCSR_POWERSTATE /= "000") ELSE '0';
00449                                    ppm_L1_exit <= '1' WHEN (CFG_PCIE_LINK_STATE = "000") ELSE '0';
00450                            END GENERATE;
00451             -- PPM L1 detection not supported for S6
00452                            xhdl10 : IF (NOT((C_FAMILY = ("V6")) AND (NOT(C_ROOT_PORT)))) GENERATE
00453                                    ppm_L1_trig <= '0';
00454                                    ppm_L1_exit <= '1';
00455                            END GENERATE;
00456                    END GENERATE;
00457            END GENERATE;
00458    END GENERATE;
00459 
00460    PROCESS (USER_CLK)
00461    BEGIN
00462       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00463               IF (USER_RST = '1') THEN
00464                       ppm_L1_thrtl          <= '0'   AFTER (TCQ)*1 ps;
00465                       cfg_pcie_link_state_d <= "000" AFTER (TCQ)*1 ps;
00466                       trn_rdllp_src_rdy_d   <= '0'   AFTER (TCQ)*1 ps;
00467               ELSE
00468                       IF (ppm_L1_trig = '1') THEN
00469                               ppm_L1_thrtl  <= '1'   AFTER (TCQ)*1 ps;
00470                       ELSIF (ppm_L1_exit = '1') THEN
00471                               ppm_L1_thrtl  <= '0'   AFTER (TCQ)*1 ps;
00472                       END IF;
00473                       cfg_pcie_link_state_d <= CFG_PCIE_LINK_STATE  AFTER (TCQ)*1 ps;
00474                       trn_rdllp_src_rdy_d <= TRN_RDLLP_SRC_RDY      AFTER (TCQ)*1 ps;
00475               END IF;
00476       END IF;
00477    END PROCESS;
00478 
00479     ------------------------------------------------------------------------------
00480     -- THROTTLE REASON: Block needs to transition to low power state PPM L2/3
00481     --   - When to throttle: appropriate PM signal indicates a transition to
00482     --     L2/3 is pending or in progress (family and role dependent)
00483     --   - When to stop: never (the only path out of L2/3 is a full reset)
00484     --
00485     -- If the block needs to transition to PM state PPM L2/3, we need to finish
00486     -- up what we're doing and throttle when the user gives permission.
00487     ------------------------------------------------------------------------------
00488     -- PPM L2/3 signals for 7 Series in RC mode
00489    xhdl11 : IF ((C_FAMILY = ("X7")) AND (C_ROOT_PORT)) GENERATE
00490            ppm_L23_trig <= '1' WHEN (cfg_pcie_link_state_d = "110") ELSE '0';
00491            wire_to_turnoff <= '0';
00492    END GENERATE;
00493 
00494    -- PPM L2/3 signals for V6 in RC mode
00495    xhdl12 : IF (NOT((C_FAMILY = ("X7")) AND (C_ROOT_PORT))) GENERATE
00496            xhdl13 : IF ((C_FAMILY = ("V6")) AND (C_ROOT_PORT)) GENERATE
00497                    ppm_L23_trig <= CFG_PM_SEND_PME_TO;
00498                    wire_to_turnoff <= '0';
00499            END GENERATE;
00500             -- PPM L2/3 signals in EP mode
00501            xhdl14 : IF (NOT((C_FAMILY = ("V6")) AND (C_ROOT_PORT))) GENERATE
00502                    ppm_L23_trig <= (wire_to_turnoff AND reg_turnoff_ok);
00503                     -- PPM L2/3 signals for 7 Series in EP mode
00504                     -- For 7 Series, cfg_to_turnoff pulses once when a turnoff request is
00505                     -- outstanding, so we need a "sticky" register that grabs the request.
00506                    xhdl15 : IF (C_FAMILY = ("X7")) GENERATE
00507                            PROCESS (USER_CLK)
00508                            BEGIN
00509                                    IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00510                                            IF (USER_RST = '1') THEN
00511                                                    reg_to_turnoff <= '0' AFTER (TCQ)*1 ps;
00512                                            ELSE
00513                                                    IF (CFG_TO_TURNOFF = '1') THEN
00514                                                            reg_to_turnoff <= '1' AFTER (TCQ)*1 ps;
00515                                                    END IF;
00516                                            END IF;
00517                                    END IF;
00518                            END PROCESS;
00519                            wire_to_turnoff <= reg_to_turnoff;
00520                    END GENERATE;
00521                     -- PPM L2/3 signals for V6/S6 in EP mode
00522                     -- In V6 and S6, the to_turnoff signal asserts and remains asserted until
00523                     -- turnoff_ok is asserted, so a sticky reg is not necessary.
00524                    xhdl16 : IF (NOT(C_FAMILY = ("X7"))) GENERATE
00525                            wire_to_turnoff <= CFG_TO_TURNOFF;
00526                    END GENERATE;
00527                    PROCESS (USER_CLK)
00528                    BEGIN
00529                            IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00530                                    IF (USER_RST = '1') THEN
00531                                            reg_turnoff_ok <= '0' AFTER (TCQ)*1 ps;
00532                                    ELSE
00533                                            reg_turnoff_ok <= USER_TURNOFF_OK AFTER (TCQ)*1 ps;
00534                                    END IF;
00535                            END IF;
00536                    END PROCESS;
00537            END GENERATE;
00538    END GENERATE;
00539 
00540    PROCESS (USER_CLK)
00541    BEGIN
00542            IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00543                    IF (USER_RST = '1') THEN
00544                            ppm_L23_thrtl <= '0' AFTER (TCQ)*1 ps;
00545                            cfg_turnoff_ok_pending <= '0' AFTER (TCQ)*1 ps;
00546                    ELSE
00547                    -- Make sure cfg_turnoff_ok pulses once for one clock cycle for every
00548                    -- turnoff request.
00549                            IF (ppm_L23_trig = '1') THEN
00550                                    ppm_L23_thrtl <= '1' AFTER (TCQ)*1 ps;
00551                            END IF;
00552                            IF (ppm_L23_trig = '1' AND (ppm_L23_thrtl = '0')) THEN
00553                                    cfg_turnoff_ok_pending <= '1' AFTER (TCQ)*1 ps;
00554                            ELSIF (cfg_turnoff_ok_xhdl0 = '1') THEN
00555                                    cfg_turnoff_ok_pending <= '0' AFTER (TCQ)*1 ps;
00556                            END IF;
00557                    END IF;
00558            END IF;
00559    END PROCESS;
00560 
00561    --------------------------------------------------------------------------------
00562    -- Create axi_thrtl_ok. This signal determines if it's OK to throttle the     --
00563    -- user design on the AXI interface. Since TREADY is registered, this signal  --
00564    -- needs to assert on the cycle ~before~ we actually intend to throttle.      --
00565    -- The only time it's OK to throttle when TVALID is asserted is on the first  --
00566    -- beat of a new packet. Therefore, assert axi_thrtl_ok if one of the         --
00567    -- is true:                                                                   --
00568    --    1) The user is not in a packet and is not starting one                  --
00569    --    2) The user is just finishing a packet                                  --
00570    --    3) We're already throttled, so it's OK to continue throttling           --
00571    --------------------------------------------------------------------------------
00572 
00573    PROCESS (USER_CLK)
00574    BEGIN
00575       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00576               IF (USER_RST = '1') THEN
00577                       reg_axi_in_pkt <= '0' AFTER (TCQ)*1 ps;
00578               ELSE
00579                       IF (S_AXIS_TX_TVALID = '1' AND S_AXIS_TX_TLAST  = '1') THEN
00580                               reg_axi_in_pkt <= '0' AFTER (TCQ)*1 ps;
00581                       ELSIF (tready_thrtl_xhdl1  = '1'  AND S_AXIS_TX_TVALID  = '1') THEN
00582                               reg_axi_in_pkt <= '1' AFTER (TCQ)*1 ps;
00583                       END IF;
00584               END IF;
00585       END IF;
00586    END PROCESS;
00587 
00588    axi_in_pkt     <= (S_AXIS_TX_TVALID OR reg_axi_in_pkt);
00589    axi_pkt_ending <= (S_AXIS_TX_TVALID AND S_AXIS_TX_TLAST);
00590    axi_throttled  <= NOT(tready_thrtl_xhdl1);
00591    axi_thrtl_ok   <= (NOT(axi_in_pkt) OR axi_pkt_ending OR axi_throttled);
00592    --------------------------------------------------------------------------------
00593    -- Throttle CTL State Machine:                                                --
00594    -- Throttle user design when a throttle trigger (or triggers) occur.          --
00595    -- Keep user throttled until all exit criteria have been met.                 --
00596    --------------------------------------------------------------------------------
00597 
00598    -- Immediate throttle signal. Used to "pounce" on a throttle opportunity when
00599    -- we're seeking one
00600    pre_throttle <= (tbuf_av_min_trig OR tbuf_av_gap_trig OR lnk_up_trig OR tcfg_req_trig OR ppm_L1_trig OR ppm_L23_trig);
00601 
00602    -- Registered throttle signals. Used to control throttle state machine
00603    reg_throttle <= (tbuf_av_min_thrtl OR tbuf_av_gap_thrtl OR lnk_up_thrtl OR tcfg_req_thrtl OR ppm_L1_thrtl OR ppm_L23_thrtl);
00604    exit_crit <= (NOT(tbuf_av_min_thrtl) AND NOT(tbuf_av_gap_thrtl) AND (NOT(lnk_up_thrtl)) AND (NOT(tcfg_req_thrtl)) AND (NOT(ppm_L1_thrtl)) AND (NOT(ppm_L23_thrtl)));
00605 
00606    PROCESS (CUR_STATE_A,reg_throttle, axi_thrtl_ok, tcfg_req_thrtl, tcfg_gnt_pending, cfg_turnoff_ok_pending, pre_throttle, exit_crit)
00607    BEGIN
00608       CASE CUR_STATE_A IS
00609          -- IDLE: in this state we're waiting for a trigger event to occur. As
00610          -- soon as an event occurs and the user isn't transmitting a packet, we
00611          -- throttle the PCIe block and the user and next state is THROTTLE.
00612               WHEN (IDLE) =>
00613                       IF(reg_throttle = '1' AND axi_thrtl_ok = '1') THEN
00614                               tready_thrtl_mux <= '0';
00615                               NEXT_STATE_A   <= (THROTTLE);
00616                               -- Assert appropriate grant signal depending on the throttle type.
00617                               IF (tcfg_req_thrtl  = '1') THEN
00618                                       trn_tcfg_gnt_xhdl2    <= '1';   -- For cfg request, grant the request
00619                                       cfg_turnoff_ok_xhdl0  <= '0'; --
00620                               ELSIF (ppm_L23_thrtl = '1') THEN
00621                                       trn_tcfg_gnt_xhdl2    <= '0';    --
00622                                       cfg_turnoff_ok_xhdl0  <= '1';  -- For PM request, permit transition
00623                               ELSE
00624                                       trn_tcfg_gnt_xhdl2    <= '0';  -- Otherwise do nothing
00625                                       cfg_turnoff_ok_xhdl0  <= '0';--
00626                               END IF;
00627                       ELSE
00628                              -- If there's not throttle event, do nothing
00629                              -- Throttle user as soon as possible
00630                               tready_thrtl_mux <= (NOT((axi_thrtl_ok AND pre_throttle)));
00631                               NEXT_STATE_A <= IDLE;
00632                               trn_tcfg_gnt_xhdl2 <= '0';
00633                               cfg_turnoff_ok_xhdl0 <= '0';
00634                       END IF;
00635               -- THROTTLE: in this state the user is throttle and we're waiting for
00636               -- exit criteria, which tells us that the throttle event is over. When
00637               -- the exit criteria is satisfied, de-throttle the user and next state
00638               WHEN (THROTTLE) =>
00639                       IF (exit_crit = '1') THEN
00640                               -- Dethrottle user
00641                               tready_thrtl_mux <= (NOT(pre_throttle));
00642                               NEXT_STATE_A   <= IDLE;
00643                       ELSE
00644                               -- Throttle user
00645                               tready_thrtl_mux <= '0';
00646                               NEXT_STATE_A   <= (THROTTLE);
00647                       END IF;
00648                        -- Assert appropriate grant signal depending on the throttle type.
00649                       IF (tcfg_req_thrtl = '1' AND tcfg_gnt_pending = '1') THEN
00650                               trn_tcfg_gnt_xhdl2     <= '1';   -- For cfg request, grant the request
00651                               cfg_turnoff_ok_xhdl0   <= '0'; --
00652                       ELSIF (cfg_turnoff_ok_pending = '1') THEN
00653                               trn_tcfg_gnt_xhdl2     <= '0';   --
00654                               cfg_turnoff_ok_xhdl0   <= '1'; -- For PM request, permit transition
00655                       ELSE
00656                               trn_tcfg_gnt_xhdl2     <= '0';   -- Otherwise do nothing
00657                               cfg_turnoff_ok_xhdl0   <= '0'; --
00658                       END IF;
00659               WHEN OTHERS =>
00660                       tready_thrtl_mux     <= '0';
00661                       NEXT_STATE_A         <= (IDLE);
00662                       trn_tcfg_gnt_xhdl2   <= '0' ;
00663                       cfg_turnoff_ok_xhdl0 <= '0';
00664       END CASE;
00665    END PROCESS;
00666 
00667 
00668 -- Synchronous logic
00669    PROCESS (USER_CLK)
00670    BEGIN
00671       IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00672               IF (USER_RST = '1') THEN
00673                       -- Throttle user by default until link comes up
00674                       CUR_STATE_A        <= (THROTTLE) AFTER (TCQ)*1 ps;
00675                       reg_tlast          <= '0' AFTER (TCQ)*1 ps;
00676                       tready_thrtl_xhdl1 <= '0' AFTER (TCQ)*1 ps;
00677               ELSE
00678                       CUR_STATE_A        <= NEXT_STATE_A AFTER (TCQ)*1 ps;
00679                       tready_thrtl_xhdl1 <= (tready_thrtl_mux AND NOT(tx_ecrc_pause)) AFTER (TCQ)*1 ps;
00680                       reg_tlast          <= S_AXIS_TX_TLAST AFTER (TCQ)*1 ps;
00681               END IF;
00682       END IF;
00683    END PROCESS;
00684 
00685 
00686    -- For X7, the PCIe block will generate the ECRC for a packet if trn_tecrc_gen
00687    -- is asserted at SOF. In this case, the Block needs an extra data beat to
00688    -- calculate the ECRC, but only if the following conditions are met:
00689    --  1) there is no empty DWORDS at the end of the packet
00690    --     (i.e. packet length % C_DATA_WIDTH == 0)
00691    --
00692    --  2) There isn't a ECRC in the TLP already, as indicated by the TD bit in the
00693    --     TLP header
00694    --
00695    -- If both conditions are met, the Block will stall the TRN interface for one
00696    -- data beat after EOF. We need to predict this stall and preemptively stall the
00697    -- User for one beat.
00698    xhdl17 : IF (C_FAMILY = ("X7")) GENERATE
00699 
00700       -- Grab necessary packet fields
00701       packet_fmt <= S_AXIS_TX_TDATA(30 DOWNTO 29);
00702       packet_td  <= S_AXIS_TX_TDATA(15);
00703 
00704       -- Calculate total packet length
00705       header_len <= "100" WHEN packet_fmt(0) = '1' ELSE "011";
00706       payload_len <= S_AXIS_TX_TDATA(9 DOWNTO 0) WHEN packet_fmt(1) = '1' ELSE "0000000000";
00707       packet_len  <= ("0000000000" & header_len) + ("0000" & payload_len);
00708 
00709       -- Determine if an ECRC pause is needed
00710       PACKET_LEN_CHECK_128 : IF (C_DATA_WIDTH = 128) GENERATE
00711               pause_needed <= '1' WHEN (packet_len(1 DOWNTO 0) = "00" AND packet_td = '0') ELSE '0';
00712       END GENERATE;
00713 
00714       PACKET_LEN_CHECK_64 : IF (C_DATA_WIDTH /= 128) GENERATE
00715               pause_needed <= '1' WHEN (packet_len(0) = '0' AND packet_td = '0') ELSE '0';
00716       END GENERATE;
00717 
00718       -- Create flag to alert TX pipeline to insert a stall
00719       tx_ecrc_pkt <= S_AXIS_TX_TUSER(0) AND pause_needed AND tready_thrtl_xhdl1 AND S_AXIS_TX_TVALID AND not(reg_axi_in_pkt);
00720 
00721       PROCESS (USER_CLK)
00722       BEGIN
00723               IF (USER_CLK'EVENT AND USER_CLK = '1') THEN
00724                       IF (USER_RST = '1') THEN
00725                               reg_tx_ecrc_pkt <= '0' AFTER (TCQ)*1 ps;
00726                       ELSE
00727                               IF (tx_ecrc_pkt  = '1' AND S_AXIS_TX_TLAST = '0') THEN
00728                                       reg_tx_ecrc_pkt <= '1' AFTER (TCQ)*1 ps;
00729                               ELSIF (tready_thrtl_xhdl1 = '1' AND S_AXIS_TX_TVALID = '1' AND S_AXIS_TX_TLAST = '1') THEN
00730                                       reg_tx_ecrc_pkt <= '0' AFTER (TCQ)*1 ps;
00731                               END IF;
00732                       END IF;
00733               END IF;
00734       END PROCESS;
00735 
00736 --      tx_ecrc_pkt <= (S_AXIS_TX_TUSER(0) AND tready_thrtl_xhdl1 AND S_AXIS_TX_TVALID AND (NOT(reg_axi_in_pkt)));
00737       tx_ecrc_pause <= (((tx_ecrc_pkt OR reg_tx_ecrc_pkt) AND S_AXIS_TX_TLAST AND S_AXIS_TX_TVALID AND tready_thrtl_xhdl1));
00738    END GENERATE;
00739 
00740    xhdl18 : IF (NOT(C_FAMILY = ("X7"))) GENERATE
00741            tx_ecrc_pause <= '0';
00742    END GENERATE;
00743 END trans;