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