The UDP loopback just reads from the input FIFO, reverses src and destination addresses, and writes back to the output FIFO. This can be used to measure the throughput of the HPS-FPGA communication
173 lines
6.6 KiB
VHDL
173 lines
6.6 KiB
VHDL
-- 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;
|