108 lines
3.2 KiB
Python
108 lines
3.2 KiB
Python
import pytest
|
|
import time
|
|
from random import getrandbits
|
|
from amaranth import *
|
|
from amaranth.lib import io
|
|
from amaranth_boards.nexys4ddr import Nexys4DDRPlatform
|
|
|
|
from manta import *
|
|
from manta.utils import *
|
|
|
|
class EthernetMemoryCoreTest(Elaboratable):
|
|
def __init__(self, platform):
|
|
self.platform = platform
|
|
self.width = 28
|
|
self.depth = 612
|
|
|
|
# Create Manta instance
|
|
self.manta = Manta()
|
|
|
|
# Configure it to communicate over Ethernet
|
|
self.manta.interface = EthernetInterface(
|
|
phy="LiteEthPHYRMII",
|
|
device="xc7a",
|
|
vendor="xilinx",
|
|
toolchain="vivado",
|
|
refclk_freq=50e6,
|
|
clk_freq=50e6,
|
|
fpga_ip_addr="10.0.0.2",
|
|
host_ip_addr="10.0.0.1",
|
|
udp_port=2000,
|
|
)
|
|
|
|
self.manta.cores.mem = MemoryCore("bidirectional", self.width, self.depth)
|
|
|
|
def elaborate(self, platform):
|
|
m = Module()
|
|
|
|
# Create 50MHz clock domain
|
|
m.domains.ethclk = ethclk = ClockDomain()
|
|
m.submodules.divider = Instance(
|
|
"divider",
|
|
("i", "clk", ClockSignal()),
|
|
("o", "ethclk", ethclk.clk),
|
|
)
|
|
platform.add_file("../examples/common/divider.sv", open("divider.sv"))
|
|
|
|
# Add Manta as a submodule
|
|
m.submodules.manta = DomainRenamer("ethclk")(self.manta)
|
|
|
|
# This is only required for Amaranth < 0.5.2
|
|
eth_pin_names = [
|
|
"mdio",
|
|
"mdc",
|
|
"reset",
|
|
"rxd",
|
|
"rxerr",
|
|
"txd",
|
|
"txen",
|
|
"crs_dv",
|
|
"int",
|
|
"clk",
|
|
]
|
|
eth_pin_dirs = {name: "-" for name in eth_pin_names}
|
|
eth_pins = platform.request("eth", dir=eth_pin_dirs)
|
|
|
|
# For Amaranth > 0.5.2, this simpler syntax may be used:
|
|
# eth_pins = platform.request("eth")
|
|
|
|
# Run the PHY's ethclk from the 50MHz divider
|
|
m.submodules.eth_clk_io_buf = eth_clk_io_buf = io.Buffer("o", eth_pins.clk)
|
|
m.d.comb += eth_clk_io_buf.o.eq(ethclk.clk)
|
|
|
|
# Wire Ethernet pins to the Manta instance
|
|
self.manta.interface.set_phy_io(
|
|
rmii_clocks_ref_clk=ethclk.clk,
|
|
rmii_rst_n=eth_pins.reset.io,
|
|
rmii_rx_data=eth_pins.rxd.io,
|
|
rmii_crs_dv=eth_pins.crs_dv.io,
|
|
rmii_tx_en=eth_pins.txen.io,
|
|
rmii_tx_data=eth_pins.txd.io,
|
|
rmii_mdc=eth_pins.mdc.io,
|
|
rmii_mdio=eth_pins.mdio.io,
|
|
)
|
|
|
|
return m
|
|
|
|
def verify(self):
|
|
self.platform.build(self, do_program=True)
|
|
|
|
# Wait for the FPGA to acquire IP address
|
|
time.sleep(5)
|
|
|
|
for addr in jumble(range(self.depth)):
|
|
data = getrandbits(self.width)
|
|
self.manta.cores.mem.write(addr, data)
|
|
|
|
# Verify the same number is returned when reading
|
|
readback = self.manta.cores.mem.read(addr)
|
|
if readback != data:
|
|
raise ValueError(
|
|
f"Memory read from {hex(addr)} returned {hex(readback)} instead of {hex(data)}"
|
|
)
|
|
|
|
|
|
|
|
@pytest.mark.skipif(not xilinx_tools_installed(), reason="no toolchain installed")
|
|
def test_mem_core_xilinx():
|
|
EthernetMemoryCoreTest(Nexys4DDRPlatform()).verify() |