pcs: Add false_carrier signal

This adds an explicit false carrier signal. Trying to determine this
condition the MDIO signals is tricky because BAD_SSD can last over
several cycles of CE. To make things easier, add a signal which is high
only once per event.

Signed-off-by: Sean Anderson <seanga2@gmail.com>
This commit is contained in:
Sean Anderson 2022-11-05 11:57:54 -04:00
parent ece7d6c619
commit 02069bceee
4 changed files with 34 additions and 19 deletions

View File

@ -90,8 +90,7 @@ module mdio_regs (
localparam VCR_LTEST = 14;
integer i;
reg duplex, false_carrier_last, false_carrier_event;
reg link_status_latched, link_status_latched_next, link_status_last, disconnect;
reg duplex, link_status_latched, link_status_latched_next, link_status_last, disconnect;
reg loopback_next, pdown_next, isolate_next, duplex_next, coltest_next;
reg descrambler_test_next, link_monitor_test_next;
reg [15:0] data_read_next;
@ -126,7 +125,6 @@ module mdio_regs (
coltest_next = coltest;
link_status_latched_next = link_status_latched && link_status;
disconnect = link_status_last && !link_status;
false_carrier_event = false_carrier && !false_carrier_last;
descrambler_test_next = descrambler_test;
link_monitor_test_next = link_monitor_test;
@ -140,7 +138,7 @@ module mdio_regs (
if (!(&nwc)) nwc_next = nwc + negative_wraparound;
if (!(&pwc)) pwc_next = pwc + positive_wraparound;
if (!(&dc)) dc_next = dc + disconnect;
if (!(&fcc)) fcc_next = fcc + false_carrier_event;
if (!(&fcc)) fcc_next = fcc + false_carrier;
if (!(&sec)) sec_next = sec + symbol_error;
end
@ -174,7 +172,7 @@ module mdio_regs (
nwc_next = negative_wraparound;
pwc_next = positive_wraparound;
dc_next = disconnect;
fcc_next = false_carrier_event;
fcc_next = false_carrier;
sec_next = symbol_error;
end
descrambler_test_next = 0;
@ -223,7 +221,7 @@ module mdio_regs (
data_read_next = fcc;
if (cyc && stb)
fcc_next = we ? data_write : false_carrier_event;
fcc_next = we ? data_write : false_carrier;
end
SECR: if (ENABLE_COUNTERS) begin
data_read_next = sec;
@ -260,7 +258,6 @@ module mdio_regs (
coltest <= coltest_next;
link_status_latched <= link_status_latched_next;
link_status_last <= link_status;
false_carrier_last <= false_carrier;
data_read <= data_read_next;
if (ENABLE_COUNTERS) begin
nwc <= nwc_next;

View File

@ -190,7 +190,8 @@ module pcs_rx (
input link_status,
/* Internal */
output reg rx
output reg rx,
output reg false_carrier
);
localparam IDLE = 0;
@ -210,7 +211,7 @@ module pcs_rx (
reg [2:0] state, state_next;
initial state = IDLE;
/* Whether we are aligned and receiving */
reg rx_next;
reg rx_next, false_carrier_next;
pcs_rx_bits rx_bits (
.clk(clk),
@ -261,6 +262,7 @@ module pcs_rx (
state_next = state;
valid_next = valid;
err_next = 0;
false_carrier_next = 0;
`define BAD_SSD begin \
state_next = BAD_SSD; \
@ -279,8 +281,10 @@ end
ce_next = 0;
if (unaligned == { `CODE_I, `CODE_J })
state_next = START_J;
else
else begin
`BAD_SSD;
false_carrier_next = 1;
end
end
end
BAD_SSD: begin
@ -293,8 +297,10 @@ end
if (aligned[4:0] == `CODE_K) begin
state_next = START_K;
valid_next = 1;
end else
end else begin
`BAD_SSD;
false_carrier_next = indicate;
end
if (!indicate)
state_next = START_J;
@ -371,6 +377,7 @@ end
rx <= rx_next;
state <= state_next;
ce <= ce_next;
false_carrier <= false_carrier_next;
if (ce_next) begin
data <= data_next;
valid <= valid_next;

View File

@ -128,7 +128,7 @@ async def test_mdio(regs):
await counter_test(PWCR, regs.positive_wraparound)
await xfer(DCR) # Clear DCR from the BMSR testing
await counter_test(DCR, regs.link_status, True, False)
await counter_test(FCCR, regs.false_carrier, True)
await counter_test(FCCR, regs.false_carrier)
await counter_test(SECR, regs.symbol_error)
await reg_toggle(VCR, VCR_DTEST, regs.descrambler_test)

View File

@ -22,20 +22,28 @@ def frame(data):
return itertools.chain(
(Code('J'), Code('K')),
# Chop off the SSD
as_codes(data[2:]),
as_codes(itertools.islice(data, 2, None)),
(Code('T'), Code('R')),
)
async def mii_recv_packet(pcs):
while not (pcs.ce.value and pcs.valid.value):
async def mii_recv_packet(pcs, signals=None):
if signals is None:
signals = {
'ce': pcs.ce,
'err': pcs.err,
'data': pcs.data,
'valid': pcs.valid,
}
while not (signals['ce'].value and signals['valid'].value):
await RisingEdge(pcs.clk)
while pcs.valid.value:
if pcs.ce.value:
if pcs.err.value:
while signals['valid'].value:
if signals['ce'].value:
if signals['err'].value:
yield None
else:
yield pcs.data.value
yield signals['data'].value
await RisingEdge(pcs.clk)
async def pcs_send_codes(pcs, codes, valids):
@ -68,11 +76,14 @@ async def test_rx(pcs, valids):
assert packet == await alist(mii_recv_packet(pcs))
false_carriers = 0
for _ in range(3):
while not (pcs.rx.value and pcs.err.value and pcs.ce.value):
await RisingEdge(pcs.clk)
false_carriers += pcs.false_carrier.value
assert pcs.data.value == 0xE
await FallingEdge(pcs.rx)
assert false_carriers == 3
assert [0x5, 0x5, None] == await alist(mii_recv_packet(pcs))