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.
This commit is contained in:
Markus Koch 2025-09-02 14:11:21 +02:00
parent f5b691fae5
commit 7a0da0f91d
2 changed files with 12 additions and 3 deletions

View File

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

View File

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