From 7a0da0f91de4a872bec288082739745a3e2787d5 Mon Sep 17 00:00:00 2001 From: Markus Koch Date: Tue, 2 Sep 2025 14:11:21 +0200 Subject: [PATCH] eth+ipv4prot: Fix protocol arbitration for real The problem arises in the following scenario. There are two sources: HIGH-prio and LOW-prio. Current selection (from last transaction) is LOW-prio. This one completes. Next, both request at the same time. Data and tx_en from LOW-prio is latched -> first word is taken from there. Now, arbitration does its job and switches to high prio. All acks and data go here. Result: First byte is from LOW-prio source, rest is from HIGH-prio. This commit fixes this behavior by resetting the selected channel to the highest priority one, preventing the switch from pulling it away from the selected one as the high priority is the one that will get selected by the switching logic anyways. Fixes #13. --- trashernet/trashernet_eth.vhd | 5 ++++- trashernet/trashernet_ipv4prot.vhd | 10 ++++++++-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/trashernet/trashernet_eth.vhd b/trashernet/trashernet_eth.vhd index 0827b90..539cae9 100644 --- a/trashernet/trashernet_eth.vhd +++ b/trashernet/trashernet_eth.vhd @@ -141,7 +141,10 @@ begin end if; when TXD => - state <= IDLE when (not mac_in.tx_mac_data_en or not mac_out.tx_active); + if not mac_in.tx_mac_data_en then + state <= IDLE; + sel <= SEL_ETH_I; -- To avoid arbitration errors, always select the highest priority one by default + end if; end case; end if; end process arb; diff --git a/trashernet/trashernet_ipv4prot.vhd b/trashernet/trashernet_ipv4prot.vhd index 77c2a30..adf2b8a 100644 --- a/trashernet/trashernet_ipv4prot.vhd +++ b/trashernet/trashernet_ipv4prot.vhd @@ -83,7 +83,7 @@ begin end block rx; tx : block - type state_t is (IDLE, TXD); + type state_t is (IDLE, TXD, WAITDONE); signal state : state_t; begin @@ -105,7 +105,13 @@ begin end loop; when TXD => - state <= IDLE when (not ipv4_in.tx_en); + state <= WAITDONE when (not ipv4_in.tx_en); + + when WAITDONE => + if ipv4_out.tx_err_stb or ipv4_out.tx_ok_stb or ipv4_out.tx_data_ack then + state <= IDLE; + tx_sel <= ipv4_protocol_in'left; -- To avoid arbitration errors, always select the highest priority one by default + end if; end case; end if; end process arb;