Skip to content

Commit

Permalink
mac/core: Allow using core_dw smaller than phy_dw
Browse files Browse the repository at this point in the history
Especially for XGMII PHYs with 64 bit width, a 32 bit datapath uses much
less resources
  • Loading branch information
david-sawatzke committed Dec 11, 2024
1 parent 99d4073 commit d0608e6
Showing 1 changed file with 37 additions and 34 deletions.
71 changes: 37 additions & 34 deletions liteeth/mac/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

from liteeth.common import *
from liteeth.mac import gap, preamble, crc, padding, last_be
from liteeth.mac.common import *

from migen.genlib.cdc import PulseSynchronizer

Expand All @@ -37,8 +38,7 @@ def __init__(self, phy, dw,
# Parameters.
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))

if with_sys_datapath:
cd_tx = "sys"
cd_rx = "sys"
Expand All @@ -64,8 +64,8 @@ class TXDatapath(LiteXModule):
def __init__(self):
self.pipeline = []

def add_cdc(self):
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(core_dw),
def add_cdc(self, dw):
tx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
cd_from = "sys",
cd_to = "eth_tx",
depth = tx_cdc_depth,
Expand All @@ -74,11 +74,11 @@ def add_cdc(self):
self.submodules += tx_cdc
self.pipeline.append(tx_cdc)

def add_converter(self):
def add_converter(self, cd):
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)
tx_converter = ClockDomainsRenamer(cd)(tx_converter)
self.submodules += tx_converter
self.pipeline.append(tx_converter)

Expand Down Expand Up @@ -113,30 +113,30 @@ def add_gap(self):
self.submodules += tx_gap
self.pipeline.append(tx_gap)

def add_domain_switch(self):
dw = core_dw
if core_dw < phy_dw:
dw = phy_dw
self.add_converter("sys")
self.add_cdc(dw)
if core_dw > phy_dw:
self.add_converter("eth_tx")
self.add_last_be()

def do_finalize(self):
self.submodules += stream.Pipeline(*self.pipeline)

self.tx_datapath = tx_datapath = TXDatapath()
tx_datapath.pipeline.append(self.sink)
if not with_sys_datapath:
# CHECKME: Verify converter/cdc order for the different cases.
tx_datapath.add_cdc()
if core_dw != phy_dw:
tx_datapath.add_converter()
if core_dw != 8:
tx_datapath.add_last_be()
tx_datapath.add_domain_switch()
if with_padding:
tx_datapath.add_padding()
if with_preamble_crc:
tx_datapath.add_crc()
tx_datapath.add_preamble()
if with_sys_datapath:
# CHECKME: Verify converter/cdc order for the different cases.
tx_datapath.add_cdc()
if core_dw != phy_dw:
tx_datapath.add_converter()
if core_dw != 8:
tx_datapath.add_last_be()
tx_datapath.add_domain_switch()
# Gap insertion has to occurr in phy tx domain to ensure gap is correctly maintained.
if not getattr(phy, "integrated_ifg_inserter", False):
tx_datapath.add_gap()
Expand Down Expand Up @@ -186,16 +186,16 @@ def add_last_be(self):
self.submodules += rx_last_be
self.pipeline.append(rx_last_be)

def add_converter(self):
def add_converter(self, cd):
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)
rx_converter = ClockDomainsRenamer(cd)(rx_converter)
self.submodules += rx_converter
self.pipeline.append(rx_converter)

def add_cdc(self):
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(core_dw),
def add_cdc(self, dw):
rx_cdc = stream.ClockDomainCrossing(eth_phy_description(dw),
cd_from = "eth_rx",
cd_to = "sys",
depth = rx_cdc_depth,
Expand All @@ -204,28 +204,31 @@ def add_cdc(self):
self.submodules += rx_cdc
self.pipeline.append(rx_cdc)

def add_domain_switch(self):
dw = phy_dw
if phy_dw < core_dw:
dw = core_dw
self.add_last_be()
self.add_converter("eth_rx")
self.add_cdc(dw)
if phy_dw > core_dw:
self.add_converter("sys")
last_handler = LiteEthLastHandler(eth_phy_description(core_dw))
self.submodules += last_handler
self.pipeline.append(last_handler)

def do_finalize(self):
self.submodules += stream.Pipeline(*self.pipeline)

self.rx_datapath = rx_datapath = RXDatapath()
rx_datapath.pipeline.append(phy)
if with_sys_datapath:
if core_dw != 8:
rx_datapath.add_last_be()
# CHECKME: Verify converter/cdc order for the different cases.
if core_dw != phy_dw:
rx_datapath.add_converter()
rx_datapath.add_cdc()
rx_datapath.add_domain_switch()
if with_preamble_crc:
rx_datapath.add_preamble()
rx_datapath.add_crc()
if with_padding:
rx_datapath.add_padding()
if not with_sys_datapath:
if core_dw != 8:
rx_datapath.add_last_be()
# CHECKME: Verify converter/cdc order for the different cases.
if core_dw != phy_dw:
rx_datapath.add_converter()
rx_datapath.add_cdc()
rx_datapath.add_domain_switch()
rx_datapath.pipeline.append(self.source)

0 comments on commit d0608e6

Please sign in to comment.