trashernet/trashernet/trashernet_udpprot.vhd

131 lines
4.7 KiB
VHDL

-- -------------------------------------------------------------------------- --
-- 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;