pass Ethernet config to LiteEth core generator

This commit is contained in:
Fischer Moseley 2024-02-10 00:48:53 -08:00
parent 63e912fb63
commit 5e642101ef
2 changed files with 114 additions and 26 deletions

View File

@ -192,38 +192,45 @@ class EthernetInterface(Elaboratable):
sock.sendto(bytes_out, (self.fpga_ip_addr, self.udp_port))
def generate_liteeth_core(self):
"""
Generate a LiteEth core by calling a slightly modified form of the LiteEth
standalone core generator. This passes the contents of the 'ethernet' section
of the Manta configuration file to LiteEth, after modifying it slightly to
include the UDP ports and set a MAC address if the user didn't specify one.
"""
liteeth_config = self.config.copy()
# Randomly assign a MAC address if one is not specified in the configuration.
# This will choose a MAC address in the Locally Administered, Administratively Assigned group.
# For more information, see:
# https://en.wikipedia.org/wiki/MAC_address#Ranges_of_group_and_locally_administered_addresses
if "mac_address" not in self.config:
mac_address = list(f"{randint(0, (2**48) - 1):012x}")
mac_address[1] = "2"
mac_address = int("".join(mac_address), 16)
if "mac_address" not in liteeth_config:
addr = list(f"{randint(0, (2**48) - 1):012x}")
addr[1] = "2"
liteeth_config["mac_address"] = int("".join(addr), 16)
else:
mac_address = self.config["mac_address"]
# Force use of DHCP
liteeth_config["dhcp"] = True
liteeth_config = {
"phy": self.config["phy"],
"vendor": self.config["vendor"],
"toolchain": self.config["toolchain"],
"refclk_freq": self.config["refclk_freq"],
"clk_freq": self.config["clk_freq"],
"mac_address": mac_address,
"dhcp": True,
"data_width": 32,
"udp_ports": {
"udp0": {
"udp_port": self.udp_port,
"data_width": 32,
"tx_fifo_depth": 64,
"rx_fifo_depth": 64,
}
},
# Use UDP
liteeth_config["core"] = "udp"
# Use 32-bit words. Might be redundant, as I think using DHCP forces
# LiteEth to use 32-bit words
liteeth_config["data_width"] = 32
# Add UDP port
liteeth_config["udp_ports"] = {
"udp0": {
"udp_port": self.udp_port,
"data_width": 32,
"tx_fifo_depth": 64,
"rx_fifo_depth": 64,
}
}
# Generate the core
from .liteeth_gen import main
return main(liteeth_config)

View File

@ -230,6 +230,8 @@ def get_udp_raw_port_ios(name, data_width):
# PHY Core -----------------------------------------------------------------------------------------
class PHYCore(SoCMini):
SoCMini.csr_map = {
"ctrl": 0,
@ -322,8 +324,14 @@ class PHYCore(SoCMini):
qpll_settings = QPLLSettings(
refclksel=0b001,
fbdiv=4,
fbdiv_45={125e6: 5, 156.25e6: 4}[refclk_freq],
fbdiv={
liteeth_phys.A7_1000BASEX: 4,
liteeth_phys.A7_2500BASEX: 5,
}[phy],
fbdiv_45={
125e6: 5,
156.25e6: 4,
}[refclk_freq],
refclk_div=1,
)
qpll = QPLL(ethphy_pads.refclk, qpll_settings)
@ -371,7 +379,73 @@ class PHYCore(SoCMini):
)
# MAC Core -----------------------------------------------------------------------------------------
class MACCore(PHYCore):
def __init__(self, platform, core_config):
# Parameters -------------------------------------------------------------------------------
nrxslots = core_config.get("nrxslots", 2)
ntxslots = core_config.get("ntxslots", 2)
bus_standard = core_config["core"]
tx_cdc_depth = core_config.get("tx_cdc_depth", 32)
tx_cdc_buffered = core_config.get("tx_cdc_buffered", False)
rx_cdc_depth = core_config.get("rx_cdc_depth", 32)
rx_cdc_buffered = core_config.get("rx_cdc_buffered", False)
assert bus_standard in ["wishbone", "axi-lite"]
# PHY --------------------------------------------------------------------------------------
PHYCore.__init__(self, platform, core_config)
# MAC --------------------------------------------------------------------------------------
self.ethmac = ethmac = LiteEthMAC(
phy=self.ethphy,
dw=32,
interface="wishbone",
endianness=core_config["endianness"],
nrxslots=nrxslots,
ntxslots=ntxslots,
full_memory_we=core_config.get("full_memory_we", False),
tx_cdc_depth=tx_cdc_depth,
tx_cdc_buffered=tx_cdc_buffered,
rx_cdc_depth=rx_cdc_depth,
rx_cdc_buffered=rx_cdc_buffered,
)
if bus_standard == "wishbone":
# Wishbone Interface -----------------------------------------------------------------------
wb_bus = wishbone.Interface()
platform.add_extension(wb_bus.get_ios("wishbone"))
self.comb += wb_bus.connect_to_pads(
self.platform.request("wishbone"), mode="slave"
)
self.bus.add_master(master=wb_bus)
if bus_standard == "axi-lite":
# AXI-Lite Interface -----------------------------------------------------------------------
axil_bus = axi.AXILiteInterface(address_width=32, data_width=32)
platform.add_extension(axil_bus.get_ios("bus"))
self.submodules += axi.Wishbone2AXILite(ethmac.bus, axil_bus)
self.comb += axil_bus.connect_to_pads(
self.platform.request("bus"), mode="slave"
)
self.bus.add_master(master=axil_bus)
ethmac_region_size = (nrxslots + ntxslots) * buffer_depth
ethmac_region = SoCRegion(
origin=self.mem_map.get("ethmac", None),
size=ethmac_region_size,
cached=False,
)
self.bus.add_slave(name="ethmac", slave=ethmac.bus, region=ethmac_region)
# Interrupt Interface ----------------------------------------------------------------------
self.comb += self.platform.request("interrupt").eq(self.ethmac.ev.irq)
# UDP Core -----------------------------------------------------------------------------------------
class UDPCore(PHYCore):
def add_streamer_port(self, platform, name, port_cfg):
# Use default Data-Width of 8-bit when not specified.
@ -571,6 +645,8 @@ class UDPCore(PHYCore):
# Build --------------------------------------------------------------------------------------------
def main(core_config):
# Convert YAML elements to Python/LiteX --------------------------------------------------------
for k, v in core_config.items():
@ -598,7 +674,12 @@ def main(core_config):
raise ValueError("Unsupported vendor: {}".format(core_config["vendor"]))
platform.add_extension(_io)
soc = UDPCore(platform, core_config)
if core_config["core"] in ["wishbone", "axi-lite"]:
soc = MACCore(platform, core_config)
elif core_config["core"] == "udp":
soc = UDPCore(platform, core_config)
else:
raise ValueError("Unknown core: {}".format(core_config["core"]))
with TemporaryDirectory() as path:
builder = Builder(soc, compile_gateware=False, output_dir=path)