From b42dc65796acca99f6d9ded0cf998aa85ad57b1b Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Wed, 30 Sep 2026 19:02:52 +0000 Subject: [PATCH] fix(w5100): wait 83ms after software reset, not 1ms The init does MR=0x80 (software reset) then waits reset_cycles before writing NETLCKR/SHAR/SIPR/socket registers. That wait was 24_000 cycles = 1 ms at 24 MHz, but the W5100S needs the datasheet's 60.3 ms -- our own bus self-test needed ~85 ms before the chip answered at all. 1 ms is marginal rather than simply wrong, which is why this presented as intermittent: an NCRA reset sometimes left the chip still resetting while the init writes landed on it and were silently dropped, leaving it misconfigured and the bus master blocked. Symptom was a W5100 that wedged after an NCRA reset -- TX never completing and the UART shell's own 'udp unicast' hanging -- recoverable only by a 12 V power cycle. Note RST_N is never asserted by the gateware; only the software reset is used, so this wait is the only settle time the chip gets. Default is now 2_000_000 = 83 ms. Testbenches pass small values explicitly and are unaffected. Co-Authored-By: Claude Opus 5 --- exi_bba/bba_top.py | 2 +- exi_bba/w5100_parallel_master.py | 14 +++++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/exi_bba/bba_top.py b/exi_bba/bba_top.py index d6f48a7..4f8d748 100644 --- a/exi_bba/bba_top.py +++ b/exi_bba/bba_top.py @@ -48,7 +48,7 @@ class BBATop(Elaboratable): w5500_rst_n : W5500 hardware reset (output, active low) """ - def __init__(self, eth="w5100", reset_cycles=24000, + def __init__(self, eth="w5100", reset_cycles=2_000_000, status_panel=False, uart_console=False, uart_shell=False, udp_socket=3, udp_src_ip="192.168.1.123", udp_subnet="255.255.255.0", udp_gateway="192.168.1.1", diff --git a/exi_bba/w5100_parallel_master.py b/exi_bba/w5100_parallel_master.py index 5c5ee3e..f47cd87 100644 --- a/exi_bba/w5100_parallel_master.py +++ b/exi_bba/w5100_parallel_master.py @@ -140,7 +140,7 @@ class W5100ParallelMaster(Elaboratable): Init / TX / RX interfaces are identical to W5500SPIMaster. """ - def __init__(self, strobe_cycles=3, reset_cycles=24000, + def __init__(self, strobe_cycles=3, reset_cycles=2_000_000, enable_udp_test=False, udp_socket=3, src_ip="192.168.1.123", subnet="255.255.255.0", gateway="192.168.1.1", dst_ip="192.168.1.100", @@ -583,6 +583,18 @@ class W5100ParallelMaster(Elaboratable): m.next = "IDLE" # MR = 0x80 software reset (direct A=00), then settle. + # + # reset_cycles MUST cover the W5100S's post-reset dead time (the + # datasheet's 60.3 ms; our own bus self-test needed ~85 ms before + # the chip answered). The default 2_000_000 = 83 ms at the 24 MHz + # sync clock. It was 24_000 = 1 ms, which is MARGINAL: the chip + # sometimes answered and sometimes did not, so every init write + # after this point (NETLCKR, SHAR, SIPR, socket regs) could land on + # a still-resetting chip and be silently dropped. The symptom was + # a W5100 that wedged after an NCRA reset -- TX never completing + # and the UART shell's own `udp unicast` hanging -- recoverable + # only by a 12 V power cycle. Do NOT shrink this for the synthesis + # build; the testbenches pass a small value explicitly. write_reg("MR_RST", _MR, [_MR_RST], "MR_WAIT", direct=True) with m.State("MR_WAIT"): with m.If(wait_ctr == self._reset_cycles):