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