mirror of
https://github.com/enjoy-digital/liteeth.git
synced 2025-01-03 03:43:37 -05:00
core/mac: apply changes from misoc: remove gap_checker in rx, add preamble errors, fix preamble checker
This commit is contained in:
parent
ccdb85bcb7
commit
c9ec30df2f
4 changed files with 58 additions and 79 deletions
|
@ -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:
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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")
|
||||||
)
|
)
|
||||||
|
|
|
@ -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"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in a new issue