diff --git a/design/top_hwitl.vhd b/design/top_hwitl.vhd index f1a5f86..1241f35 100644 --- a/design/top_hwitl.vhd +++ b/design/top_hwitl.vhd @@ -216,7 +216,29 @@ architecture eth of top_hwitl is signal ipv4_out : ipv4_out_t; signal ipv4_in : ipv4_in_t; + + constant IPROT_ICMP : integer := 0; + constant IPROT_UDP : integer := 1; + constant IPV4_PROTOCOLS : ipv4_protocol_vector := ( + IPROT_ICMP => IPV4_PROTOCOL_ICMP, + IPROT_UDP => IPV4_PROTOCOL_UDP + ); + signal ipv4_protocol_out : ipv4_protocol_out_vector(IPV4_PROTOCOLS'range); + signal ipv4_protocol_in : ipv4_protocol_in_vector(IPV4_PROTOCOLS'range); begin + trashernet_ipv4prot_inst : entity trashernet.trashernet_ipv4prot + generic map( + IPV4_PROTOCOLS => IPV4_PROTOCOLS + ) + port map( + clk => clk, + rst => rst, + ipv4_out => ipv4_out, + ipv4_in => ipv4_in, + ipv4_protocol_out => ipv4_protocol_out, + ipv4_protocol_in => ipv4_protocol_in + ); + trashernet_ipv4_inst : entity trashernet.trashernet_ipv4 port map( clk => clk, @@ -341,6 +363,24 @@ begin end if; end process receiver; + udp : process(clk) is + begin + if rising_edge(clk) then + if ipv4_protocol_out(IPROT_UDP).rx_header_rcv then + report "Receive UDP"; + end if; + end if; + end process udp; + + icmp : process(clk) is + begin + if rising_edge(clk) then + if ipv4_protocol_out(IPROT_ICMP).rx_header_rcv then + report "Receive ICMP"; + end if; + end if; + end process icmp; + arp_request_test : process(clk, rst) is begin if rst then diff --git a/trashernet/trashernet_ipv4prot.vhd b/trashernet/trashernet_ipv4prot.vhd new file mode 100644 index 0000000..8adf30c --- /dev/null +++ b/trashernet/trashernet_ipv4prot.vhd @@ -0,0 +1,122 @@ +-- -------------------------------------------------------------------------- -- +-- 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 tx_to_rx : ipv4_protocol_out_vector(ipv4_protocol_out'range); -- Only using `tx_` signals + + 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_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_protocol <= IPV4_PROTOCOLS(tx_sel); + end block demux; + end block tx; +end architecture rtl; diff --git a/trashernet/trashernet_pkg.vhd b/trashernet/trashernet_pkg.vhd index 75228a0..a370797 100644 --- a/trashernet/trashernet_pkg.vhd +++ b/trashernet/trashernet_pkg.vhd @@ -169,9 +169,9 @@ package trashernet_pkg is rx_data : byte; -- RX data rx_data_valid : std_logic; -- RX data valid strobe - rx_ok : std_logic; -- End of packet, checksum OK + rx_ok_stb : std_logic; -- End of packet, checksum OK rx_error_stb : std_logic; -- End of packet, checksum invalid - rx_start_stb : std_logic; -- Start of reception + rx_header_rcv : std_logic; -- Start of reception tx_data_ack : std_logic; -- Give next data byte of disable `tx_en` tx_ok_stb : std_logic; -- Transmission successful