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
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_rx")(rx_gap_checker)
tx_pipeline += [tx_gap_inserter]
rx_pipeline += [rx_gap_checker]
# Preamble / CRC
if isinstance(phy, LiteEthPHYModel):
@ -30,6 +26,7 @@ class LiteEthMACCore(Module, AutoCSR):
self._preamble_crc = CSRStatus(reset=1)
elif with_preamble_crc:
self._preamble_crc = CSRStatus(reset=1)
self.preamble_errors = CSRStatus(32)
self.crc_errors = CSRStatus(32)
# Preamble insert/check
@ -47,13 +44,20 @@ class LiteEthMACCore(Module, AutoCSR):
tx_pipeline += [preamble_inserter, crc32_inserter]
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.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 += [
If(self.ps_preamble_error.o,
self.preamble_errors.status.eq(self.preamble_errors.status + 1)),
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
if with_padding:

View file

@ -133,9 +133,9 @@ class LiteEthMACCRCInserter(Module):
Attributes
----------
sink : in
Packets input without CRC.
Packets octets without CRC.
source : out
Packets output with CRC.
Packets octets with CRC.
"""
def __init__(self, crc_class, description):
self.sink = sink = stream.Endpoint(description)
@ -211,18 +211,18 @@ class LiteEthMACCRCChecker(Module):
Attributes
----------
sink : in
Packets input with CRC.
Packet octets with CRC.
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.
crc_error : out
error : out
Pulses every time a CRC error is detected.
"""
def __init__(self, crc_class, description):
self.sink = sink = 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.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",

View file

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

View file

@ -4,6 +4,17 @@ from litex.gen.genlib.misc import chooser
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):
self.sink = 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)
]
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,
NextState("IDLE"),
@ -57,80 +68,45 @@ class LiteEthMACPreambleInserter(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):
self.sink = stream.Endpoint(eth_phy_description(dw))
self.source = stream.Endpoint(eth_phy_description(dw))
assert dw == 8
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")
self.submodules += fsm
fsm.act("IDLE",
self.sink.ready.eq(1),
clr_cnt.eq(1),
clr_discard.eq(1),
If(self.sink.valid,
clr_cnt.eq(0),
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)
)
)
sink.ready.eq(1),
If(sink.valid & ~sink.last & (sink.data == eth_preamble >> 56),
NextState("COPY")
),
If(sink.valid & sink.last, self.error.eq(1))
)
self.comb += [
self.source.data.eq(self.sink.data),
self.source.last_be.eq(self.sink.last_be)
source.data.eq(sink.data),
source.last_be.eq(sink.last_be)
]
fsm.act("COPY",
self.sink.connect(self.source, omit=set(["data", "last_be"])),
If(self.source.valid & self.source.last & self.source.ready,
sink.connect(source, omit={"data", "last_be"}),
If(source.valid & source.last & source.ready,
NextState("IDLE"),
)
)