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 <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2022-08-29 21:25:25 -04:00
parent fb751eb7fb
commit ebcb8cc056
2 changed files with 32 additions and 14 deletions

View File

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

View File

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