mac/core: Split TX/RX parts and cleanup to improve readability/maintenance.
This commit is contained in:
parent
7ed1c61237
commit
6901d418b3
|
@ -22,16 +22,17 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
with_sys_datapath = False,
|
with_sys_datapath = False,
|
||||||
with_preamble_crc = True,
|
with_preamble_crc = True,
|
||||||
with_padding = True):
|
with_padding = True):
|
||||||
core_dw = dw
|
|
||||||
|
|
||||||
|
# Endpoints.
|
||||||
|
self.sink = stream.Endpoint(eth_phy_description(dw))
|
||||||
|
self.source = stream.Endpoint(eth_phy_description(dw))
|
||||||
|
|
||||||
|
# Parameters.
|
||||||
|
core_dw = dw
|
||||||
if core_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))
|
raise ValueError("Core data width({}) must be larger than PHY data width({})".format(core_dw, phy.dw))
|
||||||
|
|
||||||
rx_pipeline = [phy]
|
|
||||||
tx_pipeline = [phy]
|
|
||||||
|
|
||||||
if with_sys_datapath:
|
if with_sys_datapath:
|
||||||
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw)
|
|
||||||
cd_tx = "sys"
|
cd_tx = "sys"
|
||||||
cd_rx = "sys"
|
cd_rx = "sys"
|
||||||
dw = core_dw
|
dw = core_dw
|
||||||
|
@ -40,30 +41,73 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
cd_rx = "eth_rx"
|
cd_rx = "eth_rx"
|
||||||
dw = phy.dw
|
dw = phy.dw
|
||||||
|
|
||||||
|
# TX Data-Path (Core --> PHY).
|
||||||
|
# ------------------------------------------------------------------------------------------
|
||||||
|
self.tx_datapath = tx_datapath = [phy]
|
||||||
|
|
||||||
|
# Early sys conversion.
|
||||||
|
if with_sys_datapath:
|
||||||
|
self.add_tx_converter(core_dw, phy.dw)
|
||||||
|
|
||||||
# Interpacket gap
|
# Interpacket gap
|
||||||
tx_gap_inserter = gap.LiteEthMACGap(dw)
|
tx_gap_inserter = gap.LiteEthMACGap(dw)
|
||||||
self.submodules += ClockDomainsRenamer(cd_tx)(tx_gap_inserter)
|
tx_gap_inserter = ClockDomainsRenamer(cd_tx)(tx_gap_inserter)
|
||||||
tx_pipeline.append(tx_gap_inserter)
|
self.submodules += tx_gap_inserter
|
||||||
|
tx_datapath.append(tx_gap_inserter)
|
||||||
|
|
||||||
# Preamble / CRC
|
# Preamble / CRC
|
||||||
if isinstance(phy, LiteEthPHYModel):
|
if isinstance(phy, LiteEthPHYModel):
|
||||||
# In simulation, avoid CRC/Preamble to enable direct connection
|
# In simulation, avoid CRC/Preamble to enable direct connection to the Ethernet tap.
|
||||||
# to the Ethernet tap.
|
|
||||||
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)
|
||||||
|
|
||||||
# Preamble insert/check
|
# Preamble insert.
|
||||||
preamble_inserter = preamble.LiteEthMACPreambleInserter(dw)
|
preamble_inserter = preamble.LiteEthMACPreambleInserter(dw)
|
||||||
|
preamble_inserter = ClockDomainsRenamer(cd_tx)(preamble_inserter)
|
||||||
|
self.submodules += preamble_inserter
|
||||||
|
tx_datapath.append(preamble_inserter)
|
||||||
|
|
||||||
|
# CRC insert.
|
||||||
|
crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(dw))
|
||||||
|
crc32_inserter = BufferizeEndpoints({"sink": DIR_SINK})(crc32_inserter)
|
||||||
|
crc32_inserter = ClockDomainsRenamer(cd_tx)(crc32_inserter)
|
||||||
|
self.submodules += crc32_inserter
|
||||||
|
tx_datapath.append(crc32_inserter)
|
||||||
|
|
||||||
|
# Padding
|
||||||
|
if with_padding:
|
||||||
|
padding_inserter = padding.LiteEthMACPaddingInserter(dw, 60)
|
||||||
|
padding_inserter = ClockDomainsRenamer(cd_tx)(padding_inserter)
|
||||||
|
self.submodules += padding_inserter
|
||||||
|
tx_datapath.append(padding_inserter)
|
||||||
|
|
||||||
|
# Late sys conversion.
|
||||||
|
if not with_sys_datapath:
|
||||||
|
self.add_tx_converter(core_dw, phy.dw)
|
||||||
|
|
||||||
|
# Data-Path.
|
||||||
|
self.submodules.tx_pipeline = stream.Pipeline(*reversed(tx_datapath))
|
||||||
|
self.comb += self.sink.connect(self.tx_pipeline.sink)
|
||||||
|
|
||||||
|
# RX Data-Path (PHY --> Core).
|
||||||
|
# ------------------------------------------------------------------------------------------
|
||||||
|
self.rx_datapath = rx_datapath = [phy]
|
||||||
|
|
||||||
|
# Early sys conversion.
|
||||||
|
if with_sys_datapath:
|
||||||
|
self.add_rx_converter(core_dw, phy.dw)
|
||||||
|
|
||||||
|
# Preamble / CRC
|
||||||
|
if with_preamble_crc:
|
||||||
|
# Preamble check.
|
||||||
preamble_checker = preamble.LiteEthMACPreambleChecker(dw)
|
preamble_checker = preamble.LiteEthMACPreambleChecker(dw)
|
||||||
self.submodules += ClockDomainsRenamer(cd_tx)(preamble_inserter)
|
preamble_checker = ClockDomainsRenamer(cd_rx)(preamble_checker)
|
||||||
self.submodules += ClockDomainsRenamer(cd_rx)(preamble_checker)
|
self.submodules += preamble_checker
|
||||||
tx_pipeline.append(preamble_inserter)
|
rx_datapath.append(preamble_checker)
|
||||||
rx_pipeline.append(preamble_checker)
|
|
||||||
|
# Preamble error counter.
|
||||||
self.submodules.ps_preamble_error = PulseSynchronizer(cd_rx, "sys")
|
self.submodules.ps_preamble_error = PulseSynchronizer(cd_rx, "sys")
|
||||||
|
|
||||||
|
|
||||||
# Preamble error counter
|
|
||||||
self.preamble_errors = CSRStatus(32)
|
self.preamble_errors = CSRStatus(32)
|
||||||
self.comb += self.ps_preamble_error.i.eq(preamble_checker.error)
|
self.comb += self.ps_preamble_error.i.eq(preamble_checker.error)
|
||||||
self.sync += [
|
self.sync += [
|
||||||
|
@ -71,16 +115,14 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
self.preamble_errors.status.eq(self.preamble_errors.status + 1))
|
self.preamble_errors.status.eq(self.preamble_errors.status + 1))
|
||||||
]
|
]
|
||||||
|
|
||||||
# CRC insert/check
|
# CRC check.
|
||||||
crc32_inserter = BufferizeEndpoints({"sink": DIR_SINK})(crc.LiteEthMACCRC32Inserter(eth_phy_description(dw)))
|
crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(dw))
|
||||||
crc32_checker = BufferizeEndpoints({"sink": DIR_SINK})(crc.LiteEthMACCRC32Checker(eth_phy_description(dw)))
|
crc32_checker = BufferizeEndpoints({"sink": DIR_SINK})(crc32_checker)
|
||||||
self.submodules += ClockDomainsRenamer(cd_tx)(crc32_inserter)
|
crc32_checker = ClockDomainsRenamer(cd_rx)(crc32_checker)
|
||||||
self.submodules += ClockDomainsRenamer(cd_rx)(crc32_checker)
|
self.submodules += crc32_checker
|
||||||
|
rx_datapath.append(crc32_checker)
|
||||||
|
|
||||||
tx_pipeline.append(crc32_inserter)
|
# CRC error counter.
|
||||||
rx_pipeline.append(crc32_checker)
|
|
||||||
|
|
||||||
# CRC error counter
|
|
||||||
self.crc_errors = CSRStatus(32)
|
self.crc_errors = CSRStatus(32)
|
||||||
self.submodules.ps_crc_error = PulseSynchronizer(cd_rx, "sys")
|
self.submodules.ps_crc_error = PulseSynchronizer(cd_rx, "sys")
|
||||||
self.comb += self.ps_crc_error.i.eq(crc32_checker.error),
|
self.comb += self.ps_crc_error.i.eq(crc32_checker.error),
|
||||||
|
@ -90,50 +132,67 @@ class LiteEthMACCore(Module, AutoCSR):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
# Padding
|
# Padding.
|
||||||
if with_padding:
|
if with_padding:
|
||||||
padding_inserter = padding.LiteEthMACPaddingInserter(dw, 60)
|
|
||||||
padding_checker = padding.LiteEthMACPaddingChecker(dw, 60)
|
padding_checker = padding.LiteEthMACPaddingChecker(dw, 60)
|
||||||
self.submodules += ClockDomainsRenamer(cd_tx)(padding_inserter)
|
padding_checker = ClockDomainsRenamer(cd_rx)(padding_checker)
|
||||||
self.submodules += ClockDomainsRenamer(cd_rx)(padding_checker)
|
self.submodules += padding_checker
|
||||||
tx_pipeline.append(padding_inserter)
|
rx_datapath.append(padding_checker)
|
||||||
rx_pipeline.append(padding_checker)
|
|
||||||
|
|
||||||
|
# Late sys conversion.
|
||||||
if not with_sys_datapath:
|
if not with_sys_datapath:
|
||||||
self.data_path_converter(tx_pipeline, rx_pipeline, core_dw, phy.dw)
|
self.add_rx_converter(core_dw, phy.dw)
|
||||||
|
|
||||||
# Graph
|
# Data-Path.
|
||||||
self.submodules.tx_pipeline = stream.Pipeline(*reversed(tx_pipeline))
|
self.submodules.rx_pipeline = stream.Pipeline(*rx_datapath)
|
||||||
self.submodules.rx_pipeline = stream.Pipeline(*rx_pipeline)
|
self.comb += self.rx_pipeline.source.connect(self.source)
|
||||||
|
|
||||||
self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
|
def add_tx_converter(self, dw, phy_dw):
|
||||||
|
# Delimiters.
|
||||||
def data_path_converter(self, tx_pipeline, rx_pipeline, dw, phy_dw):
|
|
||||||
# Delimiters
|
|
||||||
if dw != 8:
|
if dw != 8:
|
||||||
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
|
tx_last_be = last_be.LiteEthMACTXLastBE(phy_dw)
|
||||||
rx_last_be = last_be.LiteEthMACRXLastBE(phy_dw)
|
tx_last_be = ClockDomainsRenamer("eth_tx")(tx_last_be)
|
||||||
self.submodules += ClockDomainsRenamer("eth_tx")(tx_last_be)
|
self.submodules += tx_last_be
|
||||||
self.submodules += ClockDomainsRenamer("eth_rx")(rx_last_be)
|
self.tx_datapath.append(tx_last_be)
|
||||||
tx_pipeline.append(tx_last_be)
|
|
||||||
rx_pipeline.append(rx_last_be)
|
|
||||||
|
|
||||||
# Converters
|
# Converters.
|
||||||
if dw != phy_dw:
|
if dw != phy_dw:
|
||||||
tx_converter = stream.StrideConverter(
|
tx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(dw),
|
description_from = eth_phy_description(dw),
|
||||||
description_to = eth_phy_description(phy_dw))
|
description_to = eth_phy_description(phy_dw))
|
||||||
|
tx_converter = ClockDomainsRenamer("eth_tx")(tx_converter)
|
||||||
|
self.submodules += tx_converter
|
||||||
|
self.tx_datapath.append(tx_converter)
|
||||||
|
|
||||||
|
# Cross Domain Crossing.
|
||||||
|
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
|
||||||
|
cd_from = "sys",
|
||||||
|
cd_to = "eth_tx",
|
||||||
|
depth = 32)
|
||||||
|
self.submodules += tx_cdc
|
||||||
|
self.tx_datapath.append(tx_cdc)
|
||||||
|
|
||||||
|
def add_rx_converter(self, dw, phy_dw):
|
||||||
|
# Delimiters.
|
||||||
|
if 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.rx_datapath.append(rx_last_be)
|
||||||
|
|
||||||
|
# Converters.
|
||||||
|
if dw != phy_dw:
|
||||||
rx_converter = stream.StrideConverter(
|
rx_converter = stream.StrideConverter(
|
||||||
description_from = eth_phy_description(phy_dw),
|
description_from = eth_phy_description(phy_dw),
|
||||||
description_to = eth_phy_description(dw))
|
description_to = eth_phy_description(dw))
|
||||||
self.submodules += ClockDomainsRenamer("eth_tx")(tx_converter)
|
rx_converter = ClockDomainsRenamer("eth_rx")(rx_converter)
|
||||||
self.submodules += ClockDomainsRenamer("eth_rx")(rx_converter)
|
self.submodules += rx_converter
|
||||||
tx_pipeline.append(tx_converter)
|
self.rx_datapath.append(rx_converter)
|
||||||
rx_pipeline.append(rx_converter)
|
|
||||||
|
|
||||||
# Cross Domain Crossing
|
# Cross Domain Crossing
|
||||||
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw), cd_from="sys", cd_to="eth_tx", depth=32)
|
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
|
||||||
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw), cd_from="eth_rx", cd_to="sys", depth=32)
|
cd_from = "eth_rx",
|
||||||
self.submodules += tx_cdc, rx_cdc
|
cd_to = "sys",
|
||||||
tx_pipeline.append(tx_cdc)
|
depth = 32)
|
||||||
rx_pipeline.append(rx_cdc)
|
self.submodules += rx_cdc
|
||||||
|
self.rx_datapath.append(rx_cdc)
|
||||||
|
|
Loading…
Reference in New Issue