-- altera vhdl_input_version vhdl_2008 -- XXX: QSYS Fix (https://www.intel.com/content/www/us/en/support/programmable/articles/000079458.html) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use work.rtps_package.all; -- LOOPBACK -- This entity reads packets form the input FIFO, flips the src/dest address and ports, and writes the packet back to -- the output FIFO. -- This loopback entity can be used to measure maximum throughput through the FIFO interfaces. -- Packets have following structure: -- 31............24..............16..............8...............0 -- | | | | | -- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ -- +---------------------------------------------------------------+ -- 01| SRC_IPv4_ADDR | -- +---------------------------------------------------------------+ -- 02| DEST_IPv4_ADDR | -- +-------------------------------+-------------------------------+ -- 03| SRC_UDP_PORT | DEST_UDP_PORT | -- +-------------------------------+-------------------------------+ -- 04| PACKET_LENGTH | -- +---------------------------------------------------------------+ -- 05| | -- ~ PACKET ~ -- **| | -- +---------------------------------------------------------------+ entity loopback is port ( -- SYSTEM clk : in std_logic; reset : in std_logic; -- INPUT empty : in std_logic; rd : out std_logic; data_in : in std_logic_vector(WORD_WIDTH-1 downto 0); -- OUTPUT full : in std_logic; wr : out std_logic; data_out : out std_logic_vector(WORD_WIDTH-1 downto 0) ); end entity; architecture arch of loopback is -- *TYPE DECLARATION* type STAGE_TYPE is (READ_SRC_ADDR, READ_DEST_ADDR, READ_PORTS, READ_LENGTH, WRITE_SRC_ADDR, WRITE_DEST_ADDR, WRITE_PORTS, WRITE_LENGTH, PASSTHROUGH); -- *SIGNAL DECLARATION* signal stage, stage_next : STAGE_TYPE; signal src_addr, src_addr_next : std_logic_vector(WORD_WIDTH-1 downto 0); signal dest_addr, dest_addr_next : std_logic_vector(WORD_WIDTH-1 downto 0); signal ports, ports_next : std_logic_vector(WORD_WIDTH-1 downto 0); signal length, length_next : unsigned(WORD_WIDTH-1 downto 0); signal cnt, cnt_next : unsigned(WORD_WIDTH-1 downto 0); begin main_prc : process (all) begin -- DEFAULT stage_next <= stage; src_addr_next <= src_addr; dest_addr_next <= dest_addr; ports_next <= ports; length_next <= length; cnt_next <= cnt; -- DEFAULT Unregistered rd <= '0'; wr <= '0'; data_out <= (others => '0'); case (stage) is when READ_SRC_ADDR => -- Input FIFO Guard if (empty = '0') then src_addr_next <= data_in; rd <= '1'; stage_next <= READ_DEST_ADDR; end if; when READ_DEST_ADDR => -- Input FIFO Guard if (empty = '0') then dest_addr_next <= data_in; rd <= '1'; stage_next <= READ_PORTS; end if; when READ_PORTS => -- Input FIFO Guard if (empty = '0') then ports_next <= data_in; rd <= '1'; stage_next <= READ_LENGTH; end if; when READ_LENGTH => -- Input FIFO Guard if (empty = '0') then length_next <= unsigned(data_in); rd <= '1'; stage_next <= WRITE_SRC_ADDR; end if; when WRITE_SRC_ADDR => -- Output FIFO Guard if (full = '0') then data_out <= dest_addr; wr <= '1'; stage_next <= WRITE_DEST_ADDR; end if; when WRITE_DEST_ADDR => -- Output FIFO Guard if (full = '0') then data_out <= src_addr; wr <= '1'; stage_next <= WRITE_PORTS; end if; when WRITE_PORTS => -- Output FIFO Guard if (full = '0') then data_out <= ports(UDP_PORT_WIDTH-1 downto 0) & ports(WORD_WIDTH-1 downto UDP_PORT_WIDTH); wr <= '1'; stage_next <= WRITE_LENGTH; end if; when WRITE_LENGTH => -- Output FIFO Guard if (full = '0') then data_out <= std_logic_vector(length); wr <= '1'; stage_next <= PASSTHROUGH; cnt_next <= to_unsigned(1,WORD_WIDTH); end if; when PASSTHROUGH => -- Input & Output FIFO Guard if (empty = '0' and full = '0') then data_out <= data_in; rd <= '1'; wr <= '1'; cnt_next <= cnt + 1; -- Reached End of Packet if (cnt = length) then stage_next <= READ_SRC_ADDR; end if; end if; end case; end process; sync_prc : process(all) begin if rising_edge(clk) then if (reset = '1') then stage <= READ_SRC_ADDR; src_addr <= (others => '0'); dest_addr <= (others => '0'); ports <= (others => '0'); length <= (others => '0'); cnt <= (others => '0'); else stage <= stage_next; src_addr <= src_addr_next; dest_addr <= dest_addr_next; ports <= ports_next; length <= length_next; cnt <= cnt_next; end if; end if; end process; end architecture;