2015-01-28 03:14:01 -05:00
|
|
|
from liteeth.common import *
|
2015-02-09 06:57:05 -05:00
|
|
|
from liteeth.mac.core import gap, preamble, crc, last_be
|
2015-01-28 03:14:01 -05:00
|
|
|
|
|
|
|
class LiteEthMACCore(Module, AutoCSR):
|
2015-02-05 17:30:50 -05:00
|
|
|
def __init__(self, phy, dw, endianness="big", with_hw_preamble_crc=True):
|
2015-01-28 05:45:19 -05:00
|
|
|
if dw < phy.dw:
|
|
|
|
raise ValueError("Core data width({}) must be larger than PHY data width({})".format(dw, phy.dw))
|
2015-01-29 18:03:16 -05:00
|
|
|
|
|
|
|
rx_pipeline = [phy]
|
|
|
|
tx_pipeline = [phy]
|
|
|
|
|
2015-02-09 06:57:05 -05:00
|
|
|
# Interpacket gap
|
|
|
|
tx_gap_inserter = gap.LiteEthMACGap(phy.dw)
|
|
|
|
rx_gap_checker = gap.LiteEthMACGap(phy.dw, ack_on_gap=True)
|
|
|
|
self.submodules += tx_gap_inserter, rx_gap_checker
|
|
|
|
|
|
|
|
tx_pipeline += [tx_gap_inserter]
|
|
|
|
rx_pipeline += [rx_gap_checker]
|
|
|
|
|
2015-02-05 17:30:50 -05:00
|
|
|
# Preamble / CRC
|
2015-01-27 18:33:26 -05:00
|
|
|
if with_hw_preamble_crc:
|
|
|
|
self._hw_preamble_crc = CSRStatus(reset=1)
|
|
|
|
# Preamble insert/check
|
2015-01-28 03:14:01 -05:00
|
|
|
preamble_inserter = preamble.LiteEthMACPreambleInserter(phy.dw)
|
|
|
|
preamble_checker = preamble.LiteEthMACPreambleChecker(phy.dw)
|
2015-01-27 18:33:26 -05:00
|
|
|
self.submodules += RenameClockDomains(preamble_inserter, "eth_tx")
|
|
|
|
self.submodules += RenameClockDomains(preamble_checker, "eth_rx")
|
|
|
|
|
|
|
|
# CRC insert/check
|
2015-01-28 13:07:59 -05:00
|
|
|
crc32_inserter = crc.LiteEthMACCRC32Inserter(eth_phy_description(phy.dw))
|
|
|
|
crc32_checker = crc.LiteEthMACCRC32Checker(eth_phy_description(phy.dw))
|
2015-01-27 18:33:26 -05:00
|
|
|
self.submodules += RenameClockDomains(crc32_inserter, "eth_tx")
|
|
|
|
self.submodules += RenameClockDomains(crc32_checker, "eth_rx")
|
|
|
|
|
2015-01-29 18:03:16 -05:00
|
|
|
tx_pipeline += [preamble_inserter, crc32_inserter]
|
|
|
|
rx_pipeline += [preamble_checker, crc32_checker]
|
|
|
|
|
2015-02-05 17:30:50 -05:00
|
|
|
# Delimiters
|
2015-02-05 05:46:02 -05:00
|
|
|
if dw != 8:
|
2015-01-29 18:03:16 -05:00
|
|
|
tx_last_be = last_be.LiteEthMACTXLastBE(phy.dw)
|
|
|
|
rx_last_be = last_be.LiteEthMACRXLastBE(phy.dw)
|
|
|
|
self.submodules += RenameClockDomains(tx_last_be, "eth_tx")
|
|
|
|
self.submodules += RenameClockDomains(rx_last_be, "eth_rx")
|
2015-01-27 18:33:26 -05:00
|
|
|
|
2015-02-05 05:46:02 -05:00
|
|
|
tx_pipeline += [tx_last_be]
|
|
|
|
rx_pipeline += [rx_last_be]
|
|
|
|
|
2015-02-05 17:30:50 -05:00
|
|
|
# Converters
|
2015-02-05 05:46:02 -05:00
|
|
|
if dw != phy.dw:
|
2015-02-05 17:30:50 -05:00
|
|
|
reverse = endianness == "big"
|
2015-01-29 18:03:16 -05:00
|
|
|
tx_converter = Converter(eth_phy_description(dw), eth_phy_description(phy.dw), reverse=reverse)
|
|
|
|
rx_converter = Converter(eth_phy_description(phy.dw), eth_phy_description(dw), reverse=reverse)
|
|
|
|
self.submodules += RenameClockDomains(tx_converter, "eth_tx")
|
|
|
|
self.submodules += RenameClockDomains(rx_converter, "eth_rx")
|
|
|
|
|
2015-02-05 05:46:02 -05:00
|
|
|
tx_pipeline += [tx_converter]
|
|
|
|
rx_pipeline += [rx_converter]
|
2015-01-27 18:33:26 -05:00
|
|
|
|
|
|
|
# Cross Domain Crossing
|
2015-02-05 12:59:58 -05:00
|
|
|
tx_cdc = AsyncFIFO(eth_phy_description(dw), 8)
|
|
|
|
rx_cdc = AsyncFIFO(eth_phy_description(dw), 8)
|
2015-01-27 18:33:26 -05:00
|
|
|
self.submodules += RenameClockDomains(tx_cdc, {"write": "sys", "read": "eth_tx"})
|
|
|
|
self.submodules += RenameClockDomains(rx_cdc, {"write": "eth_rx", "read": "sys"})
|
|
|
|
|
2015-01-29 18:03:16 -05:00
|
|
|
tx_pipeline += [tx_cdc]
|
|
|
|
rx_pipeline += [rx_cdc]
|
|
|
|
|
2015-01-27 18:33:26 -05:00
|
|
|
# Graph
|
2015-01-29 18:03:16 -05:00
|
|
|
self.submodules.tx_pipeline = Pipeline(*reversed(tx_pipeline))
|
2015-01-27 18:33:26 -05:00
|
|
|
self.submodules.rx_pipeline = Pipeline(*rx_pipeline)
|
|
|
|
|
|
|
|
self.sink, self.source = self.tx_pipeline.sink, self.rx_pipeline.source
|