pass Ethernet config to LiteEth core generator
This commit is contained in:
parent
63e912fb63
commit
5e642101ef
|
|
@ -192,38 +192,45 @@ class EthernetInterface(Elaboratable):
|
||||||
sock.sendto(bytes_out, (self.fpga_ip_addr, self.udp_port))
|
sock.sendto(bytes_out, (self.fpga_ip_addr, self.udp_port))
|
||||||
|
|
||||||
def generate_liteeth_core(self):
|
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.
|
# 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.
|
# This will choose a MAC address in the Locally Administered, Administratively Assigned group.
|
||||||
# For more information, see:
|
# For more information, see:
|
||||||
# https://en.wikipedia.org/wiki/MAC_address#Ranges_of_group_and_locally_administered_addresses
|
# https://en.wikipedia.org/wiki/MAC_address#Ranges_of_group_and_locally_administered_addresses
|
||||||
|
|
||||||
if "mac_address" not in self.config:
|
if "mac_address" not in liteeth_config:
|
||||||
mac_address = list(f"{randint(0, (2**48) - 1):012x}")
|
addr = list(f"{randint(0, (2**48) - 1):012x}")
|
||||||
mac_address[1] = "2"
|
addr[1] = "2"
|
||||||
mac_address = int("".join(mac_address), 16)
|
liteeth_config["mac_address"] = int("".join(addr), 16)
|
||||||
|
|
||||||
else:
|
# Force use of DHCP
|
||||||
mac_address = self.config["mac_address"]
|
liteeth_config["dhcp"] = True
|
||||||
|
|
||||||
liteeth_config = {
|
# Use UDP
|
||||||
"phy": self.config["phy"],
|
liteeth_config["core"] = "udp"
|
||||||
"vendor": self.config["vendor"],
|
|
||||||
"toolchain": self.config["toolchain"],
|
# Use 32-bit words. Might be redundant, as I think using DHCP forces
|
||||||
"refclk_freq": self.config["refclk_freq"],
|
# LiteEth to use 32-bit words
|
||||||
"clk_freq": self.config["clk_freq"],
|
liteeth_config["data_width"] = 32
|
||||||
"mac_address": mac_address,
|
|
||||||
"dhcp": True,
|
# Add UDP port
|
||||||
"data_width": 32,
|
liteeth_config["udp_ports"] = {
|
||||||
"udp_ports": {
|
"udp0": {
|
||||||
"udp0": {
|
"udp_port": self.udp_port,
|
||||||
"udp_port": self.udp_port,
|
"data_width": 32,
|
||||||
"data_width": 32,
|
"tx_fifo_depth": 64,
|
||||||
"tx_fifo_depth": 64,
|
"rx_fifo_depth": 64,
|
||||||
"rx_fifo_depth": 64,
|
}
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Generate the core
|
# Generate the core
|
||||||
from .liteeth_gen import main
|
from .liteeth_gen import main
|
||||||
|
|
||||||
return main(liteeth_config)
|
return main(liteeth_config)
|
||||||
|
|
|
||||||
|
|
@ -230,6 +230,8 @@ def get_udp_raw_port_ios(name, data_width):
|
||||||
|
|
||||||
|
|
||||||
# PHY Core -----------------------------------------------------------------------------------------
|
# PHY Core -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class PHYCore(SoCMini):
|
class PHYCore(SoCMini):
|
||||||
SoCMini.csr_map = {
|
SoCMini.csr_map = {
|
||||||
"ctrl": 0,
|
"ctrl": 0,
|
||||||
|
|
@ -322,8 +324,14 @@ class PHYCore(SoCMini):
|
||||||
|
|
||||||
qpll_settings = QPLLSettings(
|
qpll_settings = QPLLSettings(
|
||||||
refclksel=0b001,
|
refclksel=0b001,
|
||||||
fbdiv=4,
|
fbdiv={
|
||||||
fbdiv_45={125e6: 5, 156.25e6: 4}[refclk_freq],
|
liteeth_phys.A7_1000BASEX: 4,
|
||||||
|
liteeth_phys.A7_2500BASEX: 5,
|
||||||
|
}[phy],
|
||||||
|
fbdiv_45={
|
||||||
|
125e6: 5,
|
||||||
|
156.25e6: 4,
|
||||||
|
}[refclk_freq],
|
||||||
refclk_div=1,
|
refclk_div=1,
|
||||||
)
|
)
|
||||||
qpll = QPLL(ethphy_pads.refclk, qpll_settings)
|
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 -----------------------------------------------------------------------------------------
|
# UDP Core -----------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
class UDPCore(PHYCore):
|
class UDPCore(PHYCore):
|
||||||
def add_streamer_port(self, platform, name, port_cfg):
|
def add_streamer_port(self, platform, name, port_cfg):
|
||||||
# Use default Data-Width of 8-bit when not specified.
|
# Use default Data-Width of 8-bit when not specified.
|
||||||
|
|
@ -571,6 +645,8 @@ class UDPCore(PHYCore):
|
||||||
|
|
||||||
|
|
||||||
# Build --------------------------------------------------------------------------------------------
|
# Build --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
def main(core_config):
|
def main(core_config):
|
||||||
# Convert YAML elements to Python/LiteX --------------------------------------------------------
|
# Convert YAML elements to Python/LiteX --------------------------------------------------------
|
||||||
for k, v in core_config.items():
|
for k, v in core_config.items():
|
||||||
|
|
@ -598,7 +674,12 @@ def main(core_config):
|
||||||
raise ValueError("Unsupported vendor: {}".format(core_config["vendor"]))
|
raise ValueError("Unsupported vendor: {}".format(core_config["vendor"]))
|
||||||
platform.add_extension(_io)
|
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:
|
with TemporaryDirectory() as path:
|
||||||
builder = Builder(soc, compile_gateware=False, output_dir=path)
|
builder = Builder(soc, compile_gateware=False, output_dir=path)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue