Compare commits

...

4 Commits

Author SHA1 Message Date
474d444f59 udpprot: Fix end-of-packet detection in mux
The previous logic reset the mux before the end of the packet was
transmitted, effectively dropping almost all payload bytes for any
port other than the highest priority one.
2025-09-30 16:18:16 +02:00
a98a9cbf06 udpprot: Prioritize rx/tx mux sources the same way 2025-09-30 16:13:31 +02:00
6e616c5f35 ipv4: Only forward rx_ok/error strobes when addressed 2025-09-30 16:12:52 +02:00
f13e9bf907 ipv4: Fix header parsing
The current FSM locks up when receiving an IPv4 packet that is not
addressed to the design itself. It gets stuck in `HEADER` with
block_done asserted, which resets bytecount to the payload length
instead of `BYTECOUNT_HEADER`, even when `crc_ok` or `rx_crc_error` is
asserted.

This commit fixes this by moving the reset condition (now based on
`rx_header_rcv`) to the bottom, and by properly handling the "not for
us" case by jumping to `DONE` directly.
2025-09-25 19:59:04 +02:00
2 changed files with 17 additions and 9 deletions

View File

@ -59,6 +59,7 @@ begin
alias sr_destination_ip is sr(16 to 19);
signal header_ok : std_logic;
signal selected : std_logic;
signal bytecount : integer range 0 to 65535;
signal block_done : std_logic;
@ -77,24 +78,18 @@ begin
rx_fsm : process(clk, rst) is
begin
if rst then
state <= HEADER;
state <= DONE;
ipv4_out.rx_ok_stb <= '0';
ipv4_out.rx_error_stb <= '0';
ipv4_out.rx_header_rcv <= '0';
bytecount <= BYTECOUNT_HEADER;
selected <= '0';
elsif rising_edge(clk) then
ipv4_out.rx_ok_stb <= '0';
ipv4_out.rx_error_stb <= '0';
ipv4_out.rx_header_rcv <= '0';
if (ethernet_ii_out.rx_crc_ok or ethernet_ii_out.rx_crc_error) then
state <= HEADER;
bytecount <= BYTECOUNT_HEADER;
ipv4_out.rx_error_stb <= ethernet_ii_out.rx_crc_error or to_std_logic(state = PAYLOAD);
ipv4_out.rx_ok_stb <= ethernet_ii_out.rx_crc_ok and to_std_logic(state = DONE);
end if;
if (ethernet_ii_out.rx_data_valid = '1') and (bytecount > 0) then
if state = HEADER then
sr <= sr(sr'low + 1 to sr'high) & ethernet_ii_out.rx_data;
@ -108,7 +103,10 @@ begin
bytecount <= to_integer(unsigned(sr_ihl) - 5) * 4; -- five 32-bit words is the header itself
if header_ok then
state <= OPT;
selected <= '1';
ipv4_out.rx_header_rcv <= '1';
else
state <= DONE;
end if;
end if;
@ -126,6 +124,15 @@ begin
when DONE => -- @suppress "Dead state 'DONE'": Outgoing state transition is outside of case statement
null; -- We just wait here until the MAC gives us a CRC OK/error
end case;
if selected and (ethernet_ii_out.rx_crc_ok or ethernet_ii_out.rx_crc_error) then
ipv4_out.rx_error_stb <= ethernet_ii_out.rx_crc_error or to_std_logic(state = PAYLOAD);
ipv4_out.rx_ok_stb <= ethernet_ii_out.rx_crc_ok and to_std_logic(state = DONE);
end if;
if (ethernet_ii_out.rx_header_rcv) then
state <= HEADER;
bytecount <= BYTECOUNT_HEADER;
selected <= '0';
end if;
end if;
end process rx_fsm;

View File

@ -60,6 +60,7 @@ begin
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;
exit;
end if;
end loop;
end if;
@ -109,7 +110,7 @@ begin
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
if udp_out.tx_err_stb or udp_out.tx_ok_stb then
state <= IDLE;
tx_sel <= udpprot_tx_in'left; -- To avoid arbitration errors, always select the highest priority one by default
end if;