From c9ec30df2f52192346bc448778bfe03c849371b7 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Sat, 30 Dec 2017 18:32:50 +0100 Subject: [PATCH] core/mac: apply changes from misoc: remove gap_checker in rx, add preamble errors, fix preamble checker --- liteeth/core/mac/core.py | 18 ++++--- liteeth/core/mac/crc.py | 14 ++--- liteeth/core/mac/gap.py | 3 +- liteeth/core/mac/preamble.py | 102 ++++++++++++++--------------------- 4 files changed, 58 insertions(+), 79 deletions(-) diff --git a/liteeth/core/mac/core.py b/liteeth/core/mac/core.py index 3c0bf0f..2ec5870 100644 --- a/liteeth/core/mac/core.py +++ b/liteeth/core/mac/core.py @@ -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: diff --git a/liteeth/core/mac/crc.py b/liteeth/core/mac/crc.py index 6a49ea3..33ca9c9 100644 --- a/liteeth/core/mac/crc.py +++ b/liteeth/core/mac/crc.py @@ -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", diff --git a/liteeth/core/mac/gap.py b/liteeth/core/mac/gap.py index dcdbacb..948efe1 100644 --- a/liteeth/core/mac/gap.py +++ b/liteeth/core/mac/gap.py @@ -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") ) diff --git a/liteeth/core/mac/preamble.py b/liteeth/core/mac/preamble.py index cee9e66..3f17805 100644 --- a/liteeth/core/mac/preamble.py +++ b/liteeth/core/mac/preamble.py @@ -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"), ) )