From ebcb8cc05678507e5a7d57edfa6e90401546ceaf Mon Sep 17 00:00:00 2001 From: Sean Anderson Date: Mon, 29 Aug 2022 21:25:25 -0400 Subject: [PATCH] mdio: Support The 802.3.22.2.4.3 requires that the phy not respond to reads of and ignore writes to unimplemented extended registers. When writing the mdio module, I expected that such read/writes would not be acked by the registers. However, that behavior is not especially nice for wishbone masters which don't expect it. Instead, allow the slave to return an error instead. We need an extra saved_err variable, since we might not be able to set bad immediately (when ce is low). Signed-off-by: Sean Anderson --- rtl/mdio.v | 24 +++++++++++++++--------- tb/mdio.py | 22 +++++++++++++++++----- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/rtl/mdio.v b/rtl/mdio.v index bb7282d..7cd6bb9 100644 --- a/rtl/mdio.v +++ b/rtl/mdio.v @@ -12,7 +12,7 @@ module mdio ( output reg mdo, output reg mdo_valid, - input ack, + input ack, err, output cyc, output reg stb, we, output reg [4:0] addr, @@ -47,7 +47,7 @@ module mdio ( reg [4:0] addr_next; reg [15:0] data_next; - reg bad, bad_next; + reg bad, bad_next, saved_err, saved_err_next; reg [2:0] state = IDLE, state_next; reg [4:0] state_counter, state_counter_next; @@ -67,9 +67,13 @@ module mdio ( we_next = we; addr_next = addr; data_next = data_write; - if (stb && ack) begin + saved_err_next = saved_err; + if (stb && (ack || err)) begin stb_next = 0; - data_next = data_read; + if (err) + saved_err_next = 1; + else + data_next = data_read; end state_next = state; @@ -102,6 +106,9 @@ module mdio ( OP: begin /* This is a bit of an abuse of we :) */ we_next = mdi; + /* Accordingly, cancel any outstanding transactions */ + stb_next = 0; + saved_err_next = 0; if (!state_counter) begin case ({ we, mdi }) OP_READ: we_next = 0; @@ -118,9 +125,6 @@ module mdio ( bad_next = 1; if (!state_counter) begin - /* Cancel any outstanding transaction */ - if (ce) - stb_next = 0; state_next = REGAD; state_counter_next = REGAD_BITS - 1; end @@ -141,9 +145,10 @@ module mdio ( if (!we && !bad) begin mdo_next = 0; mdo_valid_next = 1; - if (stb) begin + if (stb || saved_err) begin /* No response */ - stb_next = !ce; + if (ce) + stb_next = 0; bad_next = 1; mdo_valid_next = 0; end @@ -178,6 +183,7 @@ module mdio ( always @(posedge clk) begin stb <= stb_next; data_write <= data_next; + saved_err <= saved_err_next; if (ce) begin mdo <= mdo_next; mdo_valid <= mdo_valid_next; diff --git a/tb/mdio.py b/tb/mdio.py index 793427b..b7a2a12 100644 --- a/tb/mdio.py +++ b/tb/mdio.py @@ -108,6 +108,7 @@ async def wb_write(mdio, addr, data): async def setup(mdio): mdio.mdi.value = 0 mdio.ack.value = 0 + mdio.err.value = 0 mdio.data_read.value = LogicArray('X' * 16) await cocotb.start(ClockEnable(mdio.clk, mdio.ce, MDIO_RATIO)) await Timer(1) @@ -160,10 +161,21 @@ async def test_badmdio(mdio): async def test_badwb(mdio): await setup(mdio) - async def try_mdio(): + async def bad_resp(): + # No ack + await ClockCycles(mdio.stb, 2, False) + # Error response + for _ in range(2): + while not (mdio.cyc.value and mdio.stb.value): + await FallingEdge(mdio.clk) + + mdio.err.value = 1 + await RisingEdge(mdio.clk) + mdio.err.value = 0 + await FallingEdge(mdio.clk) + assert not mdio.stb.value + await cocotb.start(bad_resp()) + + for _ in range(2): assert await mdio_read(mdio, 0, 0) is None await mdio_write(mdio, 0, 0, 0) - assert await mdio_read(mdio, 0, 0) is None - await cocotb.start(try_mdio()) - - await ClockCycles(mdio.stb, 3, False)