DS_DMA
|
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;