core/mac: apply changes from misoc: remove gap_checker in rx, add preamble errors, fix preamble checker

This commit is contained in:
Florent Kermarrec 2017-12-30 18:32:50 +01:00
parent ccdb85bcb7
commit c9ec30df2f
4 changed files with 58 additions and 79 deletions

View file

@ -16,12 +16,8 @@ class LiteEthMACCore(Module, AutoCSR):
# Interpacket gap # Interpacket gap
tx_gap_inserter = gap.LiteEthMACGap(phy.dw) tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
self.submodules += ClockDomainsRenamer("eth_tx")(tx_gap_inserter) self.submodules += ClockDomainsRenamer("eth_tx")(tx_gap_inserter)
self.submodules += ClockDomainsRenamer("eth_rx")(rx_gap_checker)
tx_pipeline += [tx_gap_inserter] tx_pipeline += [tx_gap_inserter]
rx_pipeline += [rx_gap_checker]
# Preamble / CRC # Preamble / CRC
if isinstance(phy, LiteEthPHYModel): if isinstance(phy, LiteEthPHYModel):
@ -30,6 +26,7 @@ class LiteEthMACCore(Module, AutoCSR):
self._preamble_crc = CSRStatus(reset=1) self._preamble_crc = CSRStatus(reset=1)
elif with_preamble_crc: elif with_preamble_crc:
self._preamble_crc = CSRStatus(reset=1) self._preamble_crc = CSRStatus(reset=1)
self.preamble_errors = CSRStatus(32)
self.crc_errors = CSRStatus(32) self.crc_errors = CSRStatus(32)
# Preamble insert/check # Preamble insert/check
@ -47,13 +44,20 @@ class LiteEthMACCore(Module, AutoCSR):
tx_pipeline += [preamble_inserter, crc32_inserter] tx_pipeline += [preamble_inserter, crc32_inserter]
rx_pipeline += [preamble_checker, crc32_checker] rx_pipeline += [preamble_checker, crc32_checker]
# CRC error counter # Error counters
self.submodules.ps_preamble_error = PulseSynchronizer("eth_rx", "sys")
self.submodules.ps_crc_error = PulseSynchronizer("eth_rx", "sys") self.submodules.ps_crc_error = PulseSynchronizer("eth_rx", "sys")
self.comb += self.ps_crc_error.i.eq(crc32_checker.crc_error) self.comb += [
self.ps_preamble_error.i.eq(preamble_checker.error),
self.ps_crc_error.i.eq(crc32_checker.error),
]
self.sync += [ self.sync += [
If(self.ps_preamble_error.o,
self.preamble_errors.status.eq(self.preamble_errors.status + 1)),
If(self.ps_crc_error.o, If(self.ps_crc_error.o,
self.crc_errors.status.eq(self.crc_errors.status + 1))] self.crc_errors.status.eq(self.crc_errors.status + 1)),
]
# Padding # Padding
if with_padding: if with_padding:

View file

@ -133,9 +133,9 @@ class LiteEthMACCRCInserter(Module):
Attributes Attributes
---------- ----------
sink : in sink : in
Packets input without CRC. Packets octets without CRC.
source : out source : out
Packets output with CRC. Packets octets with CRC.
""" """
def __init__(self, crc_class, description): def __init__(self, crc_class, description):
self.sink = sink = stream.Endpoint(description) self.sink = sink = stream.Endpoint(description)
@ -211,18 +211,18 @@ class LiteEthMACCRCChecker(Module):
Attributes Attributes
---------- ----------
sink : in sink : in
Packets input with CRC. Packet octets with CRC.
source : out source : out
Packets output without CRC and "error" set to 0 Packet octets without CRC and "error" set to 0
on last when CRC OK / set to 1 when CRC KO. on last when CRC OK / set to 1 when CRC KO.
crc_error : out error : out
Pulses every time a CRC error is detected. Pulses every time a CRC error is detected.
""" """
def __init__(self, crc_class, description): def __init__(self, crc_class, description):
self.sink = sink = stream.Endpoint(description) self.sink = sink = stream.Endpoint(description)
self.source = source = stream.Endpoint(description) self.source = source = stream.Endpoint(description)
self.crc_error = Signal() self.error = Signal()
# # # # # #
@ -256,7 +256,7 @@ class LiteEthMACCRCChecker(Module):
source.payload.eq(fifo.source.payload), source.payload.eq(fifo.source.payload),
source.error.eq(sink.error | crc.error), source.error.eq(sink.error | crc.error),
self.crc_error.eq(source.valid & source.last & crc.error), self.error.eq(source.valid & source.last & crc.error),
] ]
fsm.act("RESET", fsm.act("RESET",

View file

@ -4,7 +4,7 @@ from liteeth.common import *
class LiteEthMACGap(Module): class LiteEthMACGap(Module):
def __init__(self, dw, ack_on_gap=False): def __init__(self, dw):
self.sink = sink = stream.Endpoint(eth_phy_description(dw)) self.sink = sink = stream.Endpoint(eth_phy_description(dw))
self.source = source = stream.Endpoint(eth_phy_description(dw)) self.source = source = stream.Endpoint(eth_phy_description(dw))
@ -31,7 +31,6 @@ class LiteEthMACGap(Module):
) )
fsm.act("GAP", fsm.act("GAP",
counter_ce.eq(1), counter_ce.eq(1),
sink.ready.eq(int(ack_on_gap)),
If(counter == (gap-1), If(counter == (gap-1),
NextState("COPY") NextState("COPY")
) )

View file

@ -4,6 +4,17 @@ from litex.gen.genlib.misc import chooser
class LiteEthMACPreambleInserter(Module): class LiteEthMACPreambleInserter(Module):
"""Preamble inserter
Inserts preamble at the beginning of each packet.
Attributes
----------
sink : in
Packet octets.
source : out
Preamble, SFD, and packet octets.
"""
def __init__(self, dw): def __init__(self, dw):
self.sink = stream.Endpoint(eth_phy_description(dw)) self.sink = stream.Endpoint(eth_phy_description(dw))
self.source = stream.Endpoint(eth_phy_description(dw)) self.source = stream.Endpoint(eth_phy_description(dw))
@ -48,7 +59,7 @@ class LiteEthMACPreambleInserter(Module):
self.source.last_be.eq(self.sink.last_be) self.source.last_be.eq(self.sink.last_be)
] ]
fsm.act("COPY", fsm.act("COPY",
self.sink.connect(self.source, omit=set(["data", "last_be"])), self.sink.connect(self.source, omit={"data", "last_be"}),
If(self.sink.valid & self.sink.last & self.source.ready, If(self.sink.valid & self.sink.last & self.source.ready,
NextState("IDLE"), NextState("IDLE"),
@ -57,80 +68,45 @@ class LiteEthMACPreambleInserter(Module):
class LiteEthMACPreambleChecker(Module): class LiteEthMACPreambleChecker(Module):
"""Preamble detector
Detects preamble at the beginning of each packet.
Attributes
----------
sink : in
Bits input.
source : out
Packet octets starting immediately after SFD.
error : out
Pulses every time a preamble error is detected.
"""
def __init__(self, dw): def __init__(self, dw):
self.sink = stream.Endpoint(eth_phy_description(dw)) assert dw == 8
self.source = stream.Endpoint(eth_phy_description(dw)) self.sink = sink = stream.Endpoint(eth_phy_description(dw))
self.source = source = stream.Endpoint(eth_phy_description(dw))
self.error = Signal()
# # # # # #
preamble = Signal(64, reset=eth_preamble)
cnt_max = (64//dw) - 1
cnt = Signal(max=cnt_max+1, reset_less=True)
clr_cnt = Signal()
inc_cnt = Signal()
self.sync += \
If(clr_cnt,
cnt.eq(0)
).Elif(inc_cnt,
cnt.eq(cnt+1)
)
discard = Signal(reset_less=True)
clr_discard = Signal()
set_discard = Signal()
self.sync += \
If(clr_discard,
discard.eq(0)
).Elif(set_discard,
discard.eq(1)
)
ref = Signal(dw)
match = Signal()
self.comb += [
chooser(preamble, cnt, ref),
match.eq(self.sink.data == ref)
]
fsm = FSM(reset_state="IDLE") fsm = FSM(reset_state="IDLE")
self.submodules += fsm self.submodules += fsm
fsm.act("IDLE", fsm.act("IDLE",
self.sink.ready.eq(1), sink.ready.eq(1),
clr_cnt.eq(1), If(sink.valid & ~sink.last & (sink.data == eth_preamble >> 56),
clr_discard.eq(1), NextState("COPY")
If(self.sink.valid, ),
clr_cnt.eq(0), If(sink.valid & sink.last, self.error.eq(1))
inc_cnt.eq(1),
clr_discard.eq(0),
set_discard.eq(~match),
NextState("CHECK"),
)
)
fsm.act("CHECK",
self.sink.ready.eq(1),
If(self.sink.valid,
set_discard.eq(~match),
If(cnt == cnt_max,
If(discard | (~match),
NextState("IDLE")
).Else(
NextState("COPY")
)
).Else(
inc_cnt.eq(1)
)
)
) )
self.comb += [ self.comb += [
self.source.data.eq(self.sink.data), source.data.eq(sink.data),
self.source.last_be.eq(self.sink.last_be) source.last_be.eq(sink.last_be)
] ]
fsm.act("COPY", fsm.act("COPY",
self.sink.connect(self.source, omit=set(["data", "last_be"])), sink.connect(source, omit={"data", "last_be"}),
If(self.source.valid & self.source.last & self.source.ready, If(source.valid & source.last & source.ready,
NextState("IDLE"), NextState("IDLE"),
) )
) )