bench: hw_itl: Use UDPprot
This commit is contained in:
parent
e7db2df389
commit
ba0cbed9bf
@ -228,7 +228,24 @@ architecture eth of top_hwitl is
|
||||
|
||||
signal udp_out : udp_out_t;
|
||||
signal udp_in : udp_in_t;
|
||||
|
||||
signal udpprot_rx_out : udpprot_rx_out_vector(0 to 0);
|
||||
signal udpprot_rx_in : udpprot_rx_in_vector(0 to 0);
|
||||
signal udpprot_tx_out : udpprot_tx_out_vector(0 to 0);
|
||||
signal udpprot_tx_in : udpprot_tx_in_vector(0 to 0);
|
||||
begin
|
||||
trashernet_udpprot_inst : entity trashernet.trashernet_udpprot
|
||||
port map(
|
||||
clk => clk,
|
||||
rst => rst,
|
||||
udp_out => udp_out,
|
||||
udp_in => udp_in,
|
||||
udpprot_rx_out => udpprot_rx_out,
|
||||
udpprot_rx_in => udpprot_rx_in,
|
||||
udpprot_tx_out => udpprot_tx_out,
|
||||
udpprot_tx_in => udpprot_tx_in
|
||||
);
|
||||
|
||||
trashernet_udp_inst : entity trashernet.trashernet_udp
|
||||
port map(
|
||||
clk => clk,
|
||||
@ -398,12 +415,12 @@ begin
|
||||
signal cnt : integer range 0 to sr'length - 1;
|
||||
|
||||
begin
|
||||
udp_in.tx_en <= '1' when state = TX else '0';
|
||||
udp_in.tx_ip_address <= (x"C0", x"A8", x"02", x"01");
|
||||
udp_in.tx_source_port <= x"ABCD";
|
||||
udp_in.tx_destination_port <= x"00FF";
|
||||
udp_in.tx_length <= to_unsigned(sr'length, 16);
|
||||
udp_in.tx_data <= sr(0);
|
||||
udpprot_tx_in(0).tx_ip_address <= (x"C0", x"A8", x"02", x"01");
|
||||
udpprot_tx_in(0).tx_destination_port <= x"00FF";
|
||||
udpprot_tx_in(0).tx_source_port <= x"ABCD";
|
||||
udpprot_tx_in(0).tx_length <= to_unsigned(sr'length, 16);
|
||||
udpprot_tx_in(0).tx_data <= sr(0);
|
||||
udpprot_tx_in(0).tx_en <= '1' when state = TX else '0';
|
||||
|
||||
tx_udp : process(clk, rst) is
|
||||
begin
|
||||
@ -417,12 +434,12 @@ begin
|
||||
state <= TX;
|
||||
sr <= PACKET;
|
||||
cnt <= sr'length - 1;
|
||||
report "UDP: Start TX";
|
||||
report "UDP(0): Start TX";
|
||||
end if;
|
||||
|
||||
when TX =>
|
||||
if udp_out.tx_data_ack then
|
||||
report "UDP: byte ack";
|
||||
if udpprot_tx_out(0).tx_data_ack then
|
||||
report "UDP(0): byte ack";
|
||||
sr <= sr(sr'low + 1 to sr'high) & x"00";
|
||||
if cnt = 0 then
|
||||
state <= DONE;
|
||||
@ -430,12 +447,12 @@ begin
|
||||
cnt <= cnt - 1;
|
||||
end if;
|
||||
end if;
|
||||
if udp_out.tx_err_stb then
|
||||
report "UDP: TX ERROR";
|
||||
if udpprot_tx_out(0).tx_err_stb then
|
||||
report "UDP(0): TX ERROR";
|
||||
state <= DONE;
|
||||
end if;
|
||||
if udp_out.tx_ok_stb then
|
||||
report "UDP: TX OK stb in TX state -- that shouldn't happen, right?";
|
||||
if udpprot_tx_out(0).tx_ok_stb then
|
||||
report "UDP(0): TX OK stb in TX state -- that shouldn't happen, right?";
|
||||
end if;
|
||||
|
||||
when DONE =>
|
||||
@ -446,6 +463,8 @@ begin
|
||||
end process tx_udp;
|
||||
end block tx_udp_p;
|
||||
|
||||
udpprot_rx_in(0).port_bind <= x"0400";
|
||||
|
||||
rx_udp_p : block
|
||||
begin
|
||||
rx_udp : process(clk, rst) is
|
||||
@ -453,13 +472,13 @@ begin
|
||||
if rst then
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
if udp_out.rx_header_rcv then
|
||||
report "UDP: RX on port " & --
|
||||
to_string(to_integer(udp_out.rx_header.destination_port)) & " from port " & --
|
||||
to_string(to_integer(udp_out.rx_header.source_port));
|
||||
if udpprot_rx_out(0).rx_header_rcv then
|
||||
report "UDP(0): RX on port " & --
|
||||
to_string(to_integer(udpprot_rx_out(0).rx_header.destination_port)) & " from port " & --
|
||||
to_string(to_integer(udpprot_rx_out(0).rx_header.source_port));
|
||||
end if;
|
||||
if udp_out.rx_data_valid then
|
||||
report "UDP: RX: " & to_hstring(udp_out.rx_data);
|
||||
if udpprot_rx_out(0).rx_data_valid then
|
||||
report "UDP(0): RX: " & to_hstring(udpprot_rx_out(0).rx_data);
|
||||
end if;
|
||||
end if;
|
||||
end process rx_udp;
|
||||
|
@ -261,20 +261,37 @@ package trashernet_pkg is
|
||||
tx_data : byte;
|
||||
end record udp_in_t;
|
||||
|
||||
type udpprot_rx_out_t is record
|
||||
temp : std_logic;
|
||||
type udpprot_rx_out_t is record
|
||||
rx_data : byte; -- RX Data
|
||||
rx_data_valid : std_logic; -- RX data valid strobe
|
||||
|
||||
rx_header : udp_header_t; -- UDP header
|
||||
rx_header_rcv : std_logic; -- Start of reception, `rx_header` valid
|
||||
|
||||
rx_ok_stb : std_logic; -- End of packet, checksum OK
|
||||
rx_error_stb : std_logic; -- End of packet, checksum invalid
|
||||
end record udpprot_rx_out_t;
|
||||
type udpprot_rx_in_t is record
|
||||
temp : std_logic;
|
||||
type udpprot_rx_in_t is record
|
||||
port_bind : udp_port_t;
|
||||
end record udpprot_rx_in_t;
|
||||
type udpprot_tx_out_t is record
|
||||
temp : std_logic;
|
||||
type udpprot_tx_out_t is record
|
||||
tx_data_ack : std_logic; -- Give next data byte or disable `tx_en`
|
||||
tx_ok_stb : std_logic; -- Transmission successful
|
||||
tx_err_stb : std_logic; -- Transmission failed
|
||||
end record udpprot_tx_out_t;
|
||||
type udpprot_tx_in_t is record
|
||||
temp : std_logic;
|
||||
type udpprot_tx_in_t is record
|
||||
tx_ip_address : ip_addr_t; -- Destination IP address
|
||||
tx_source_port : udp_port_t; -- UDP source port
|
||||
tx_destination_port : udp_port_t; -- UDP destination port
|
||||
tx_length : udp_length_t; -- UDP length
|
||||
|
||||
tx_en : std_logic; -- Start and continue transmitting
|
||||
tx_data : byte;
|
||||
end record udpprot_tx_in_t;
|
||||
subtype portnum is integer range 0 to 65535;
|
||||
type udp_port_vector is array (natural range <>) of portnum;
|
||||
type udpprot_tx_out_vector is array (natural range <>) of udpprot_tx_out_t;
|
||||
type udpprot_tx_in_vector is array (natural range <>) of udpprot_tx_in_t;
|
||||
type udpprot_rx_out_vector is array (natural range <>) of udpprot_rx_out_t;
|
||||
type udpprot_rx_in_vector is array (natural range <>) of udpprot_rx_in_t;
|
||||
|
||||
-- ------------------------
|
||||
-- General helper functions
|
||||
|
@ -1,8 +1,8 @@
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- trashernet_ipv4.vhd : Ethernet OSI Layer 3, Network (IPv4)
|
||||
-- Implements packet handling and IP-Layer en-/decoding.
|
||||
-- trashernet_udp.vhd : Ethernet OSI Layer 4, Transport (UDP)
|
||||
-- Implements UDP frame encoding and decoding.
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- Author : Markus Koch <markus@notsyncing.net>
|
||||
-- Contributors : None
|
||||
@ -16,10 +16,6 @@ use ieee.numeric_std.all;
|
||||
use work.trashernet_pkg.all;
|
||||
|
||||
entity trashernet_udp is
|
||||
-- generic(
|
||||
-- UDP_PORTS_RX : udp_port_vector; -- Ports to receive on
|
||||
-- UDP_PORTS_TX : udp_port_vector -- Ports to transmit on
|
||||
-- );
|
||||
port(
|
||||
-- Global
|
||||
clk : in std_logic; -- Global clock
|
||||
@ -30,12 +26,8 @@ entity trashernet_udp is
|
||||
ipv4_protocol_out : in ipv4_protocol_out_t; -- IPv4 IF (into IP Protocol)
|
||||
|
||||
-- UDP application interface
|
||||
udp_out : out udp_out_t;
|
||||
udp_in : in udp_in_t
|
||||
-- udpprot_rx_out : out udpprot_rx_out_t; -- UDP Application IF for receiving data (out from UDP)
|
||||
-- udpprot_rx_in : in udpprot_rx_in_t; -- UDP Application IF for receiving data (into UDP)
|
||||
-- udpprot_tx_out : out udpprot_tx_out_t; -- UDP Application IF for transmitting data (out from UDP)
|
||||
-- udpprot_tx_in : in udpprot_tx_in_t -- UDP Application IF for transmitting data (in from UDP)
|
||||
udp_out : out udp_out_t; -- UDP application IF (out from UDP)
|
||||
udp_in : in udp_in_t -- UDP application IF (into UDP)
|
||||
);
|
||||
end entity trashernet_udp;
|
||||
|
||||
|
130
trashernet/trashernet_udpprot.vhd
Normal file
130
trashernet/trashernet_udpprot.vhd
Normal file
@ -0,0 +1,130 @@
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- TRASHERNET - A Trashy Ethernet Stack for FPGAs --
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- trashernet_udpprot.vhd : Ethernet OSI Layer 4, Transport (UDP)
|
||||
-- Provides a convenient port-based muxed interface for UDP connections.
|
||||
-- -------------------------------------------------------------------------- --
|
||||
-- Author : Markus Koch <markus@notsyncing.net>
|
||||
-- Contributors : None
|
||||
-- License : Mozilla Public License (MPL) Version 2
|
||||
-- -------------------------------------------------------------------------- --
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
use work.trashernet_pkg.all;
|
||||
|
||||
entity trashernet_udpprot is
|
||||
port(
|
||||
-- Global
|
||||
clk : in std_logic; -- Global clock
|
||||
rst : in std_logic; -- Asynchronous reset
|
||||
|
||||
-- UDP application interface
|
||||
udp_out : in udp_out_t; -- UDP application IF (out from UDP)
|
||||
udp_in : out udp_in_t; -- UDP application IF (into UDP)
|
||||
|
||||
-- UDP protocols interface
|
||||
udpprot_rx_out : out udpprot_rx_out_vector; -- UDP Application IF for receiving data (out from UDP)
|
||||
udpprot_rx_in : in udpprot_rx_in_vector; -- UDP Application IF for receiving data (into UDP)
|
||||
udpprot_tx_out : out udpprot_tx_out_vector; -- UDP Application IF for transmitting data (out from UDP)
|
||||
udpprot_tx_in : in udpprot_tx_in_vector -- UDP Application IF for transmitting data (in from UDP)
|
||||
);
|
||||
end entity trashernet_udpprot;
|
||||
|
||||
architecture rtl of trashernet_udpprot is
|
||||
constant RX_SEL_PROTOCOL_NONE : integer := udpprot_rx_out'low - 1;
|
||||
|
||||
signal rx_sel : integer range RX_SEL_PROTOCOL_NONE to udpprot_rx_out'high;
|
||||
signal tx_sel : integer range udpprot_tx_out'low to udpprot_tx_out'high;
|
||||
begin
|
||||
assert udpprot_tx_out'length = udpprot_tx_in'length report "UDP in and out ports must have the same length" severity FAILURE;
|
||||
assert udpprot_rx_out'length = udpprot_rx_in'length report "UDP in and out ports must have the same length" severity FAILURE;
|
||||
|
||||
rx : block
|
||||
signal rx_header_rcv_delayed : std_logic;
|
||||
|
||||
begin
|
||||
arb : process(clk, rst) is
|
||||
begin
|
||||
if rst then
|
||||
rx_sel <= RX_SEL_PROTOCOL_NONE;
|
||||
rx_header_rcv_delayed <= '0';
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
rx_header_rcv_delayed <= udp_out.rx_header_rcv;
|
||||
|
||||
if udp_out.rx_header_rcv then
|
||||
rx_sel <= RX_SEL_PROTOCOL_NONE;
|
||||
for i in udpprot_rx_out'range loop
|
||||
if (udp_out.rx_header.destination_port = udpprot_rx_in(i).port_bind) then
|
||||
rx_sel <= i;
|
||||
end if;
|
||||
end loop;
|
||||
end if;
|
||||
end if;
|
||||
end process arb;
|
||||
|
||||
mux : for i in udpprot_rx_out'range generate
|
||||
udpprot_rx_out(i).rx_data <= udp_out.rx_data;
|
||||
udpprot_rx_out(i).rx_header <= udp_out.rx_header;
|
||||
|
||||
udpprot_rx_out(i).rx_data_valid <= udp_out.rx_data_valid when rx_sel = i else '0';
|
||||
udpprot_rx_out(i).rx_error_stb <= udp_out.rx_error_stb when rx_sel = i else '0';
|
||||
udpprot_rx_out(i).rx_ok_stb <= udp_out.rx_ok_stb when rx_sel = i else '0';
|
||||
udpprot_rx_out(i).rx_header_rcv <= rx_header_rcv_delayed when rx_sel = i else '0';
|
||||
end generate mux;
|
||||
|
||||
tx_mux : for i in udpprot_tx_out'range generate
|
||||
udpprot_tx_out(i).tx_data_ack <= udp_out.tx_data_ack when tx_sel = i else '0';
|
||||
udpprot_tx_out(i).tx_err_stb <= udp_out.tx_err_stb when tx_sel = i else '0';
|
||||
udpprot_tx_out(i).tx_ok_stb <= udp_out.tx_ok_stb when tx_sel = i else '0';
|
||||
end generate;
|
||||
end block rx;
|
||||
|
||||
tx : block
|
||||
type state_t is (IDLE, TXD, WAITDONE);
|
||||
signal state : state_t;
|
||||
|
||||
begin
|
||||
arb : process(clk, rst) is
|
||||
begin
|
||||
if rst then
|
||||
state <= IDLE;
|
||||
tx_sel <= udpprot_tx_in'left;
|
||||
|
||||
elsif rising_edge(clk) then
|
||||
case state is
|
||||
when IDLE =>
|
||||
for i in udpprot_tx_in'range loop
|
||||
if udpprot_tx_in(i).tx_en then
|
||||
tx_sel <= i;
|
||||
state <= TXD;
|
||||
exit; -- Prioritize according to vector
|
||||
end if;
|
||||
end loop;
|
||||
|
||||
when TXD =>
|
||||
state <= WAITDONE when (not udp_in.tx_en);
|
||||
|
||||
when WAITDONE =>
|
||||
if udp_out.tx_err_stb or udp_out.tx_ok_stb or udp_out.tx_data_ack then
|
||||
state <= IDLE;
|
||||
tx_sel <= udpprot_tx_in'left; -- To avoid arbitration errors, always select the highest priority one by default
|
||||
end if;
|
||||
end case;
|
||||
end if;
|
||||
end process arb;
|
||||
|
||||
demux : block
|
||||
begin
|
||||
udp_in.tx_data <= udpprot_tx_in(tx_sel).tx_data;
|
||||
udp_in.tx_en <= udpprot_tx_in(tx_sel).tx_en;
|
||||
udp_in.tx_ip_address <= udpprot_tx_in(tx_sel).tx_ip_address;
|
||||
udp_in.tx_length <= udpprot_tx_in(tx_sel).tx_length;
|
||||
udp_in.tx_source_port <= udpprot_tx_in(tx_sel).tx_source_port;
|
||||
udp_in.tx_destination_port <= udpprot_tx_in(tx_sel).tx_destination_port;
|
||||
end block demux;
|
||||
end block tx;
|
||||
end architecture rtl;
|
Loading…
x
Reference in New Issue
Block a user