diff --git a/exi_bba/w5100_parallel_master.py b/exi_bba/w5100_parallel_master.py index 567708b..224e3b9 100644 --- a/exi_bba/w5100_parallel_master.py +++ b/exi_bba/w5100_parallel_master.py @@ -751,10 +751,23 @@ class W5100ParallelMaster(Elaboratable): m.next = "RX_RSR_CHK" with m.State("RX_RSR_CHK"): with m.If(rx_rsr == 0): - m.next = "IDLE" # nothing received + # INT_N is asserted but there is no data. Something other + # than RECV set Sn_IR -- in practice SEND_OK (bit 4), which + # fires after every successful transmit. Returning to IDLE + # without clearing it leaves INT_N low forever, and since + # IDLE tests ~w5100_int_n BEFORE tx_valid, the FSM spins + # IDLE->RX_CHECK->here and TX is starved permanently. That + # showed up on hardware as: first frame transmits, every + # later one never sets TI, while RX keeps working. + m.next = "RX_IR_CLR" with m.Else(): m.next = "RX_RDPTR" + # Clear every Sn_IR bit EXCEPT RECV (0x04). Keeping RECV means a + # frame that lands between the RSR read and this write still raises + # INT_N and gets served on the next pass instead of being lost. + write_reg("RX_IR_CLR", _S0_IR, [0x1B], "IDLE") + with m.State("RX_RDPTR"): # read S0_RX_RD (2 bytes) m.d.sync += [xfer_addr.eq(_S0_RX_RD), xfer_rw.eq(0), xfer_stream.eq(0), xfer_sread.eq(0), xfer_wrap.eq(0),