-------------------------------------------------------------------------------- -- File : axi_pat_check.v -- Author : Xilinx Inc. -- Project : Xilinx LogiCORE Virtex-6 Embedded Tri-Mode Ethernet MAC -- File : axi_pat_check.vhd -- Version : 2.3 ------------------------------------------------------------------------------- -- -- (c) Copyright 2010 Xilinx, Inc. All rights reserved. -- -- This file contains confidential and proprietary information -- of Xilinx, Inc. and is protected under U.S. and -- international copyright and other intellectual property -- laws. -- -- DISCLAIMER -- This disclaimer is not a license and does not grant any -- rights to the materials distributed herewith. Except as -- otherwise provided in a valid license issued to you by -- Xilinx, and to the maximum extent permitted by applicable -- law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND -- WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES -- AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING -- BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- -- INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and -- (2) Xilinx shall not be liable (whether in contract or tort, -- including negligence, or under any other theory of -- liability) for any loss or damage of any kind or nature -- related to, arising under or in connection with these -- materials, including for any direct, or any indirect, -- special, incidental, or consequential loss or damage -- (including loss of data, profits, goodwill, or any type of -- loss or damage suffered as a result of any action brought -- by a third party) even if such damage or loss was -- reasonably foreseeable or Xilinx had been advised of the -- possibility of the same. -- -- CRITICAL APPLICATIONS -- Xilinx products are not designed or intended to be fail- -- safe, or for use in any application requiring fail-safe -- performance, such as life-support or safety devices or -- systems, Class III medical devices, nuclear facilities, -- applications related to the deployment of airbags, or any -- other applications that could lead to death, personal -- injury, or severe property or environmental damage -- (individually and collectively, "Critical -- Applications"). Customer assumes the sole risk and -- liability of any use of Xilinx products in Critical -- Applications, subject only to applicable laws and -- regulations governing limitations on product liability. -- -- THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS -- PART OF THIS FILE AT ALL TIMES. -- -- Description: A simple pattern checker - expects the same data pattern as generated by the pat_gen -- with the same DA/SA order (it is expected that the frames will pass through -- two address swap blocks). the checker will first sync to the data and then -- identify any errors (this is a sticky output but the internal signal is -- per byte) -- -------------------------------------------------------------------------------- library unisim; use unisim.vcomponents.all; library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.numeric_std.all; entity axi_pat_check is generic ( DEST_ADDR : bit_vector(47 downto 0) := X"da0102030405"; SRC_ADDR : bit_vector(47 downto 0) := X"5a0102030405"; MAX_SIZE : unsigned(11 downto 0) := X"1f4"; MIN_SIZE : unsigned(11 downto 0) := X"040" ); port ( axi_tclk : in std_logic; axi_tresetn : in std_logic; enable_pat_chk : in std_logic; tdata : in std_logic_vector(7 downto 0); tvalid : in std_logic; tlast : in std_logic; tready : in std_logic; frame_error : out std_logic ); end axi_pat_check; architecture rtl of axi_pat_check is -- State machine type state_typ is (IDLE, INFO, LOOK, PKT); signal errored_data : std_logic; signal lut_data : std_logic_vector(7 downto 0); signal expected_data : unsigned(7 downto 0); signal packet_size : unsigned(15 downto 0); signal packet_count : unsigned(4 downto 0); signal next_rx_state : state_typ; signal rx_state : state_typ; constant dummy : bit_vector(51 downto 0) := (others => '0'); begin -- the pattern checker is a slave in all respects so has to look for ackowledged data -- the first and 6 bytes of data are compared against the first byte of DEST_ADDR and SCR_ADDR -- to allow for address swaps being removed -- a simple state machine will keep track of the packet position next_s : process(rx_state, tlast, tvalid, tready, enable_pat_chk, errored_data) begin next_rx_state <= rx_state; case rx_state is -- cannot simply look for a rise on valid have to see a last first so -- we know the next asserted valid is new data when IDLE => if tlast = '1' and tvalid = '1' and tready = '1' and enable_pat_chk = '1' then next_rx_state <= INFO; end if; -- since we don't know where the packet gen will be rx a frame to enable -- packet size to be initialised when INFO => if tlast = '1' and tvalid = '1' and tready = '1' then next_rx_state <= LOOK; end if; -- have seen a last so now look for a start when LOOK => if tlast = '0' and tvalid = '1' and tready = '1' then next_rx_state <= PKT; end if; -- rxd first byte of packet - now stay in this state until we see a last when PKT => if enable_pat_chk = '0' or errored_data = '1' then next_rx_state <= IDLE; elsif tlast = '1' and tvalid = '1' and tready = '1' then next_rx_state <= LOOK; end if; end case; end process; state_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then if axi_tresetn = '0' then rx_state <= IDLE; else rx_state <= next_rx_state; end if; end if; end process state_p; -- now need a counter for packet size and packet position AND data pkt_count_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then if axi_tresetn = '0' then packet_count <= (others => '0'); else if (next_rx_state = PKT or rx_state = PKT or rx_state = INFO) and tvalid = '1' and tready = '1' and packet_count(4) = '0' then packet_count <= packet_count + "00001"; elsif next_rx_state = LOOK or rx_state = IDLE then packet_count <= (others => '0'); end if; end if; end if; end process pkt_count_p; -- need to get packet size info -- this is first initialised during the info state (the assumption being that -- the generate sends incrementing packet sizes (wrapping at MAX_SIZE) pkt_size_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then if rx_state = INFO and packet_count = "01100" and tvalid = '1' and tready = '1' then packet_size(15 downto 8) <= unsigned(tdata); elsif rx_state = INFO and packet_count = "01101" and tvalid = '1' and tready = '1' then packet_size(7 downto 0) <= unsigned(tdata); -- when in the LOOK state we want to update the packet size to the next expected elsif rx_state /= LOOK and next_rx_state = LOOK then if packet_size(15 downto 12) = X"0" and packet_size(11 downto 0) = MAX_SIZE - X"012" then packet_size(11 downto 0) <= MIN_SIZE - X"012"; else packet_size <= packet_size + X"0001"; end if; end if; end if; end process pkt_size_p; exp_data_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then if rx_state = LOOK and next_rx_state = PKT then expected_data <= packet_size(7 downto 0); elsif rx_state = PKT and packet_count >= "01110" and tvalid = '1' and tready = '1' then expected_data <= expected_data - X"01"; end if; end if; end process exp_data_p; -- store the parametised values in a lut (64 deep) -- this should mean the values could be adjusted in fpga_editor etc.. LUT6_gen : for I in 0 to 7 generate begin LUT6_inst : LUT6 generic map ( INIT => dummy & SRC_ADDR(I) & SRC_ADDR(I+8) & SRC_ADDR(I+16) & SRC_ADDR(I+24) & SRC_ADDR(I+32) & SRC_ADDR(I+40) & DEST_ADDR(I) & DEST_ADDR(I+8) & DEST_ADDR(I+16) & DEST_ADDR(I+24) & DEST_ADDR(I+32) & DEST_ADDR(I+40) ) port map ( O => lut_data(I), I0 => packet_count(0), I1 => packet_count(1), I2 => packet_count(2), I3 => packet_count(3), I4 => '0', I5 => '0' ); end generate; -- finally the check states - errored_data is only high on the cycle after a mismatch chk_data_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then errored_data <= '0'; if packet_count < "01100" and tvalid = '1' and tready = '1' then if lut_data /= tdata then errored_data <= '1'; end if; elsif packet_count = "01100" and tvalid = '1' and tready = '1' then if packet_size(15 downto 8) /= unsigned(tdata) then errored_data <= '1'; end if; elsif packet_count = "01101" and tvalid = '1' and tready = '1' then if packet_size(7 downto 0) /= unsigned(tdata) then errored_data <= '1'; end if; elsif packet_count >= "01110" and tvalid = '1' and tready = '1' and rx_state = PKT then if expected_data /= unsigned(tdata) then errored_data <= '1'; end if; end if; end if; end process chk_data_p; -- capture the error and hold until reset error_p : process (axi_tclk) begin if axi_tclk'event and axi_tclk = '1' then if axi_tresetn = '0' then frame_error <= '0'; elsif rx_state /= IDLE and rx_state /= INFO and errored_data = '1' then frame_error <= '1'; end if; end if; end process error_p; end rtl;