mac/core: Introduce TX/RXDatapath modules to simplify code.
This commit is contained in:
parent
11555d43cb
commit
a4a070af4d
|
@ -28,8 +28,8 @@ class LiteEthMACCore(Module, AutoCSR):
|
|||
self.source = stream.Endpoint(eth_phy_description(dw))
|
||||
|
||||
# Parameters.
|
||||
self.core_dw = core_dw = dw
|
||||
self.phy_dw = phy_dw = phy.dw
|
||||
core_dw = dw
|
||||
phy_dw = phy.dw
|
||||
if core_dw < phy_dw:
|
||||
raise ValueError("Core data width({}) must be larger than PHY data width({})".format(core_dw, phy_dw))
|
||||
|
||||
|
@ -44,165 +44,160 @@ class LiteEthMACCore(Module, AutoCSR):
|
|||
|
||||
# CSRs.
|
||||
if with_preamble_crc:
|
||||
self.preamble_crc = CSRStatus(reset=1)
|
||||
self.preamble_errors = CSRStatus(32)
|
||||
self.crc_errors = CSRStatus(32)
|
||||
self.preamble_crc = CSRStatus(reset=1)
|
||||
|
||||
# TX Data-Path (Core --> PHY).
|
||||
# ------------------------------------------------------------------------------------------
|
||||
self.tx_datapath = tx_datapath = []
|
||||
class TXDatapath(Module, AutoCSR):
|
||||
def __init__(self):
|
||||
self.pipeline = []
|
||||
|
||||
# Sink.
|
||||
tx_datapath.append(self.sink)
|
||||
def add_converter(self):
|
||||
# CHECKME: Order probably needs to be adapted based on core_dw/phy_dw ratio.
|
||||
# Cross Domain Crossing.
|
||||
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(core_dw),
|
||||
cd_from = "sys",
|
||||
cd_to = "eth_tx",
|
||||
depth = 32)
|
||||
self.submodules += tx_cdc
|
||||
self.pipeline.append(tx_cdc)
|
||||
|
||||
# Late sys conversion.
|
||||
# Converters.
|
||||
if core_dw != phy_dw:
|
||||
tx_converter = stream.StrideConverter(
|
||||
description_from = eth_phy_description(core_dw),
|
||||
description_to = eth_phy_description(phy_dw))
|
||||
tx_converter = ClockDomainsRenamer("eth_tx")(tx_converter)
|
||||
self.submodules += tx_converter
|
||||
self.pipeline.append(tx_converter)
|
||||
|
||||
# Delimiters.
|
||||
if core_dw != 8:
|
||||
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
|
||||
tx_last_be = ClockDomainsRenamer("eth_tx")(tx_last_be)
|
||||
self.submodules += tx_last_be
|
||||
self.pipeline.append(tx_last_be)
|
||||
|
||||
def add_padding(self):
|
||||
tx_padding = padding.LiteEthMACPaddingInserter(datapath_dw, (eth_min_frame_length - eth_fcs_length))
|
||||
tx_padding = ClockDomainsRenamer(cd_tx)(tx_padding)
|
||||
self.submodules += tx_padding
|
||||
self.pipeline.append(tx_padding)
|
||||
|
||||
def add_crc(self):
|
||||
tx_crc = crc.LiteEthMACCRC32Inserter(eth_phy_description(datapath_dw))
|
||||
tx_crc = BufferizeEndpoints({"sink": DIR_SINK})(tx_crc) # FIXME: Still required?
|
||||
tx_crc = ClockDomainsRenamer(cd_tx)(tx_crc)
|
||||
self.submodules += tx_crc
|
||||
self.pipeline.append(tx_crc)
|
||||
|
||||
def add_preamble(self):
|
||||
tx_preamble = preamble.LiteEthMACPreambleInserter(datapath_dw)
|
||||
tx_preamble = ClockDomainsRenamer(cd_tx)(tx_preamble)
|
||||
self.submodules += tx_preamble
|
||||
self.pipeline.append(tx_preamble)
|
||||
|
||||
def add_gap(self):
|
||||
tx_gap = gap.LiteEthMACGap(datapath_dw)
|
||||
tx_gap = ClockDomainsRenamer(cd_tx)(tx_gap)
|
||||
self.submodules += tx_gap
|
||||
self.pipeline.append(tx_gap)
|
||||
|
||||
def do_finalize(self):
|
||||
self.submodules += stream.Pipeline(*self.pipeline)
|
||||
|
||||
tx_datapath = TXDatapath()
|
||||
tx_datapath.pipeline.append(self.sink)
|
||||
if not with_sys_datapath:
|
||||
self.add_tx_converter()
|
||||
|
||||
# Padding.
|
||||
tx_datapath.add_converter()
|
||||
if with_padding:
|
||||
tx_padding = padding.LiteEthMACPaddingInserter(datapath_dw, (eth_min_frame_length - eth_fcs_length))
|
||||
tx_padding = ClockDomainsRenamer(cd_tx)(tx_padding)
|
||||
self.submodules += tx_padding
|
||||
tx_datapath.append(tx_padding)
|
||||
|
||||
# Preamble / CRC.
|
||||
tx_datapath.add_padding()
|
||||
if with_preamble_crc:
|
||||
# CRC insert.
|
||||
tx_crc = crc.LiteEthMACCRC32Inserter(eth_phy_description(datapath_dw))
|
||||
tx_crc = BufferizeEndpoints({"sink": DIR_SINK})(tx_crc) # FIXME: Still required?
|
||||
tx_crc = ClockDomainsRenamer(cd_tx)(tx_crc)
|
||||
self.submodules += tx_crc
|
||||
tx_datapath.append(tx_crc)
|
||||
|
||||
# Preamble insert.
|
||||
tx_preamble = preamble.LiteEthMACPreambleInserter(datapath_dw)
|
||||
tx_preamble = ClockDomainsRenamer(cd_tx)(tx_preamble)
|
||||
self.submodules += tx_preamble
|
||||
tx_datapath.append(tx_preamble)
|
||||
|
||||
# Interpacket gap.
|
||||
tx_gap = gap.LiteEthMACGap(datapath_dw)
|
||||
tx_gap = ClockDomainsRenamer(cd_tx)(tx_gap)
|
||||
self.submodules += tx_gap
|
||||
tx_datapath.append(tx_gap)
|
||||
|
||||
# Early sys conversion.
|
||||
tx_datapath.add_crc()
|
||||
tx_datapath.add_preamble()
|
||||
tx_datapath.add_gap()
|
||||
if with_sys_datapath:
|
||||
self.add_tx_converter(core_dw, phy_dw)
|
||||
|
||||
# PHY.
|
||||
tx_datapath.append(phy)
|
||||
|
||||
# Data-Path.
|
||||
self.submodules.tx_pipeline = stream.Pipeline(*tx_datapath)
|
||||
tx_datapath.add_converter()
|
||||
tx_datapath.pipeline.append(phy)
|
||||
self.submodules.tx_datapath = tx_datapath
|
||||
|
||||
# RX Data-Path (PHY --> Core).
|
||||
# ------------------------------------------------------------------------------------------
|
||||
self.rx_datapath = rx_datapath = []
|
||||
class RXDatapath(Module, AutoCSR):
|
||||
def __init__(self):
|
||||
self.pipeline = []
|
||||
if with_preamble_crc:
|
||||
self.preamble_errors = CSRStatus(32)
|
||||
self.crc_errors = CSRStatus(32)
|
||||
|
||||
# PHY.
|
||||
rx_datapath.append(phy)
|
||||
def add_preamble(self):
|
||||
rx_preamble = preamble.LiteEthMACPreambleChecker(datapath_dw)
|
||||
rx_preamble = ClockDomainsRenamer(cd_rx)(rx_preamble)
|
||||
self.submodules += rx_preamble
|
||||
self.pipeline.append(rx_preamble)
|
||||
|
||||
# Early sys conversion.
|
||||
ps = PulseSynchronizer(cd_rx, "sys")
|
||||
self.submodules += ps
|
||||
self.comb += ps.i.eq(rx_preamble.error)
|
||||
self.sync += If(ps.o, self.preamble_errors.status.eq(self.preamble_errors.status + 1))
|
||||
|
||||
def add_crc(self):
|
||||
rx_crc = crc.LiteEthMACCRC32Checker(eth_phy_description(datapath_dw))
|
||||
rx_crc = BufferizeEndpoints({"sink": DIR_SINK})(rx_crc) # FIXME: Still required?
|
||||
rx_crc = ClockDomainsRenamer(cd_rx)(rx_crc)
|
||||
self.submodules += rx_crc
|
||||
self.pipeline.append(rx_crc)
|
||||
|
||||
ps = PulseSynchronizer(cd_rx, "sys")
|
||||
self.submodules += ps
|
||||
self.comb += ps.i.eq(rx_crc.error),
|
||||
self.sync += If(ps.o, self.crc_errors.status.eq(self.crc_errors.status + 1))
|
||||
|
||||
def add_padding(self):
|
||||
rx_padding = padding.LiteEthMACPaddingChecker(datapath_dw, (eth_min_frame_length - eth_fcs_length))
|
||||
rx_padding = ClockDomainsRenamer(cd_rx)(rx_padding)
|
||||
self.submodules += rx_padding
|
||||
self.pipeline.append(rx_padding)
|
||||
|
||||
def add_converter(self):
|
||||
# CHECKME: Order probably needs to be adapted based on core_dw/phy_dw ratio.
|
||||
# Delimiters.
|
||||
if core_dw != 8:
|
||||
rx_last_be = last_be.LiteEthMACRXLastBE(phy_dw)
|
||||
rx_last_be = ClockDomainsRenamer("eth_rx")(rx_last_be)
|
||||
self.submodules += rx_last_be
|
||||
self.pipeline.append(rx_last_be)
|
||||
|
||||
# Converters.
|
||||
if core_dw != phy_dw:
|
||||
rx_converter = stream.StrideConverter(
|
||||
description_from = eth_phy_description(phy_dw),
|
||||
description_to = eth_phy_description(core_dw))
|
||||
rx_converter = ClockDomainsRenamer("eth_rx")(rx_converter)
|
||||
self.submodules += rx_converter
|
||||
self.pipeline.append(rx_converter)
|
||||
|
||||
# Cross Domain Crossing
|
||||
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(core_dw),
|
||||
cd_from = "eth_rx",
|
||||
cd_to = "sys",
|
||||
depth = 32)
|
||||
self.submodules += rx_cdc
|
||||
self.pipeline.append(rx_cdc)
|
||||
|
||||
def do_finalize(self):
|
||||
self.submodules += stream.Pipeline(*self.pipeline)
|
||||
|
||||
rx_datapath = RXDatapath()
|
||||
rx_datapath.pipeline.append(phy)
|
||||
if with_sys_datapath:
|
||||
self.add_rx_converter()
|
||||
|
||||
# Preamble / CRC.
|
||||
rx_datapath.add_converter()
|
||||
if with_preamble_crc:
|
||||
# Preamble check.
|
||||
rx_preamble = preamble.LiteEthMACPreambleChecker(datapath_dw)
|
||||
rx_preamble = ClockDomainsRenamer(cd_rx)(rx_preamble)
|
||||
self.submodules += rx_preamble
|
||||
rx_datapath.append(rx_preamble)
|
||||
|
||||
# Preamble error counter.
|
||||
self.submodules.ps_preamble_error = PulseSynchronizer(cd_rx, "sys")
|
||||
self.comb += self.ps_preamble_error.i.eq(rx_preamble.error)
|
||||
self.sync += [
|
||||
If(self.ps_preamble_error.o,
|
||||
self.preamble_errors.status.eq(self.preamble_errors.status + 1))
|
||||
]
|
||||
|
||||
# CRC check.
|
||||
rx_crc = crc.LiteEthMACCRC32Checker(eth_phy_description(datapath_dw))
|
||||
rx_crc = BufferizeEndpoints({"sink": DIR_SINK})(rx_crc) # FIXME: Still required?
|
||||
rx_crc = ClockDomainsRenamer(cd_rx)(rx_crc)
|
||||
self.submodules += rx_crc
|
||||
rx_datapath.append(rx_crc)
|
||||
|
||||
# CRC error counter.
|
||||
self.submodules.ps_crc_error = PulseSynchronizer(cd_rx, "sys")
|
||||
self.comb += self.ps_crc_error.i.eq(rx_crc.error),
|
||||
self.sync += [
|
||||
If(self.ps_crc_error.o,
|
||||
self.crc_errors.status.eq(self.crc_errors.status + 1)
|
||||
)
|
||||
]
|
||||
|
||||
# Padding.
|
||||
rx_datapath.add_preamble()
|
||||
rx_datapath.add_crc()
|
||||
if with_padding:
|
||||
rx_padding = padding.LiteEthMACPaddingChecker(datapath_dw, (eth_min_frame_length - eth_fcs_length))
|
||||
rx_padding = ClockDomainsRenamer(cd_rx)(rx_padding)
|
||||
self.submodules += rx_padding
|
||||
rx_datapath.append(rx_padding)
|
||||
|
||||
# Late sys conversion.
|
||||
rx_datapath.add_padding()
|
||||
if not with_sys_datapath:
|
||||
self.add_rx_converter()
|
||||
|
||||
# Source.
|
||||
rx_datapath.append(self.source)
|
||||
|
||||
# Data-Path.
|
||||
self.submodules.rx_pipeline = stream.Pipeline(*rx_datapath)
|
||||
|
||||
def add_tx_converter(self):
|
||||
# Cross Domain Crossing.
|
||||
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(self.core_dw),
|
||||
cd_from = "sys",
|
||||
cd_to = "eth_tx",
|
||||
depth = 32)
|
||||
self.submodules += tx_cdc
|
||||
self.tx_datapath.append(tx_cdc)
|
||||
|
||||
# Converters.
|
||||
if self.core_dw != self.phy_dw:
|
||||
tx_converter = stream.StrideConverter(
|
||||
description_from = eth_phy_description(self.core_dw),
|
||||
description_to = eth_phy_description(self.phy_dw))
|
||||
tx_converter = ClockDomainsRenamer("eth_tx")(tx_converter)
|
||||
self.submodules += tx_converter
|
||||
self.tx_datapath.append(tx_converter)
|
||||
|
||||
# Delimiters.
|
||||
if self.core_dw != 8:
|
||||
tx_last_be = last_be.LiteEthMACTXLastBE(self.phy_dw)
|
||||
tx_last_be = ClockDomainsRenamer("eth_tx")(tx_last_be)
|
||||
self.submodules += tx_last_be
|
||||
self.tx_datapath.append(tx_last_be)
|
||||
|
||||
def add_rx_converter(self):
|
||||
# Delimiters.
|
||||
if self.core_dw != 8:
|
||||
rx_last_be = last_be.LiteEthMACRXLastBE(self.phy_dw)
|
||||
rx_last_be = ClockDomainsRenamer("eth_rx")(rx_last_be)
|
||||
self.submodules += rx_last_be
|
||||
self.rx_datapath.append(rx_last_be)
|
||||
|
||||
# Converters.
|
||||
if self.core_dw != self.phy_dw:
|
||||
rx_converter = stream.StrideConverter(
|
||||
description_from = eth_phy_description(self.phy_dw),
|
||||
description_to = eth_phy_description(self.core_dw))
|
||||
rx_converter = ClockDomainsRenamer("eth_rx")(rx_converter)
|
||||
self.submodules += rx_converter
|
||||
self.rx_datapath.append(rx_converter)
|
||||
|
||||
# Cross Domain Crossing
|
||||
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(self.core_dw),
|
||||
cd_from = "eth_rx",
|
||||
cd_to = "sys",
|
||||
depth = 32)
|
||||
self.submodules += rx_cdc
|
||||
self.rx_datapath.append(rx_cdc)
|
||||
rx_datapath.add_converter()
|
||||
rx_datapath.pipeline.append(self.source)
|
||||
self.submodules.rx_datapath = rx_datapath
|
||||
|
|
Loading…
Reference in New Issue