-- -------------------------------------------------------------------------- -- -- TRASHERNET - A Trashy Ethernet Stack for FPGAs -- -- -------------------------------------------------------------------------- -- -- trashernet_eth.vhd : Ethernet OSI Layer 3, Network, Protocol Muxing -- Implements arbitration of different IP protocols. -- -------------------------------------------------------------------------- -- -- Author : Markus Koch -- 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_ipv4prot is generic( IPV4_PROTOCOLS : ipv4_protocol_vector ); port( -- Global clk : in std_logic; -- Global clock rst : in std_logic; -- Asynchronous reset -- IPv4 application interface ipv4_out : in ipv4_out_t; -- IPv4 IF (out from IP) ipv4_in : out ipv4_in_t; -- IPv4 IF (into IP) -- IPv4 protocol interface ipv4_protocol_out : out ipv4_protocol_out_vector(IPV4_PROTOCOLS'range); -- IPv4 Protocol IF (out from IP Mux) ipv4_protocol_in : in ipv4_protocol_in_vector(IPV4_PROTOCOLS'range) -- IPv4 Protocol IF (into IP Mux) ); end entity trashernet_ipv4prot; architecture rtl of trashernet_ipv4prot is constant SEL_PROTOCOL_NONE : integer := ipv4_protocol_out'low - 1; signal rx_sel : integer range SEL_PROTOCOL_NONE to ipv4_protocol_out'high; signal tx_sel : integer range ipv4_protocol_in'low to ipv4_protocol_in'high; begin rx : block signal rx_header_rcv_delayed : std_logic; begin arb : process(clk, rst) is begin if rst then rx_sel <= SEL_PROTOCOL_NONE; rx_header_rcv_delayed <= '0'; elsif rising_edge(clk) then rx_header_rcv_delayed <= ipv4_out.rx_header_rcv; if ipv4_out.rx_header_rcv then rx_sel <= SEL_PROTOCOL_NONE; for i in IPV4_PROTOCOLS'range loop if (ipv4_out.rx_protocol = IPV4_PROTOCOLS(i)) then rx_sel <= i; end if; end loop; end if; end if; end process arb; mux : for i in ipv4_protocol_out'range generate ipv4_protocol_out(i).rx_data <= ipv4_out.rx_data; ipv4_protocol_out(i).rx_ip_address <= ipv4_out.rx_ip_address; ipv4_protocol_out(i).rx_length <= ipv4_out.rx_length; ipv4_protocol_out(i).rx_data_valid <= ipv4_out.rx_data_valid when rx_sel = i else '0'; ipv4_protocol_out(i).rx_error_stb <= ipv4_out.rx_error_stb when rx_sel = i else '0'; ipv4_protocol_out(i).rx_ok_stb <= ipv4_out.rx_ok_stb when rx_sel = i else '0'; ipv4_protocol_out(i).rx_header_rcv <= rx_header_rcv_delayed when rx_sel = i else '0'; end generate mux; tx_mux : for i in ipv4_protocol_out'range generate ipv4_protocol_out(i).tx_data_ack <= ipv4_out.tx_data_ack when tx_sel = i else '0'; ipv4_protocol_out(i).tx_err_stb <= ipv4_out.tx_err_stb when tx_sel = i else '0'; ipv4_protocol_out(i).tx_ok_stb <= ipv4_out.tx_ok_stb when tx_sel = i else '0'; end generate; end block rx; tx : block type state_t is (IDLE, TXD); signal state : state_t; begin arb : process(clk, rst) is begin if rst then state <= IDLE; tx_sel <= ipv4_protocol_in'left; elsif rising_edge(clk) then case state is when IDLE => for i in ipv4_protocol_in'range loop if ipv4_protocol_in(i).tx_en then tx_sel <= i; state <= TXD; exit; -- Prioritize according to vector end if; end loop; when TXD => state <= IDLE when (not ipv4_in.tx_en); end case; end if; end process arb; demux : block begin ipv4_in.tx_data <= ipv4_protocol_in(tx_sel).tx_data; ipv4_in.tx_en <= ipv4_protocol_in(tx_sel).tx_en; ipv4_in.tx_ip_address <= ipv4_protocol_in(tx_sel).tx_ip_address; ipv4_in.tx_length <= ipv4_protocol_in(tx_sel).tx_length; ipv4_in.tx_protocol <= IPV4_PROTOCOLS(tx_sel); end block demux; end block tx; end architecture rtl;