Bus widths should now all be correct. (addresses and sizes in amaranth take into account the granularity selection, so granularity acts like two extra bits on the bus address line) Also don't ignore a warning about undriven resets. Turns out that can gate *everything* off in your design.
92 lines
3.1 KiB
Python
92 lines
3.1 KiB
Python
from amaranth import *
|
|
from amaranth.lib.io import pin_layout
|
|
from amaranth_soc.wishbone.bus import Interface
|
|
from amaranth_soc.memory import MemoryMap
|
|
|
|
|
|
__all__ = ["LiteEth", "rgmii_layout"]
|
|
|
|
|
|
# TODO maybe this should just call liteeth_gen to close the loop?
|
|
class LiteEth(Elaboratable, Interface):
|
|
def __init__(self, eth_interface):
|
|
self.eth_interface = eth_interface
|
|
|
|
# Addr width is 13 bits to accomodate 0x1FFF, which is well past what we care about
|
|
Interface.__init__(self, addr_width=15, data_width=32, granularity=8, features=["cti", "bte", "err"])
|
|
# TODO I need to understand the semantics here better
|
|
memory_map = MemoryMap(addr_width=17, data_width=8)
|
|
#memory_map.add_resource(self, name="LiteETH", size=0x2000)
|
|
self.memory_map = memory_map
|
|
|
|
self.interrupt = Signal()
|
|
|
|
|
|
# TODO this really shouldn't technically happen here, because we can elaborate one module multiple times,
|
|
# but since I use it once it isn't actually a problem.
|
|
def elaborate(self, platform):
|
|
if platform is not None:
|
|
platform.add_file("liteeth_core.v", open("liteeth/gateware/liteeth_core.v", 'r').read())
|
|
|
|
m = Module()
|
|
|
|
|
|
# TODO I have to provide TX/RX clocks myself
|
|
core = Instance(
|
|
"liteeth_core",
|
|
i_sys_clock=ClockSignal(),
|
|
i_sys_reset=Const(0),
|
|
|
|
# RGMII signals
|
|
o_rgmii_eth_clocks_tx=self.eth_interface.tx_clk,
|
|
i_rgmii_eth_clocks_rx=self.eth_interface.rx_clk,
|
|
o_rgmii_eth_rst_n=self.eth_interface.rst,
|
|
i_rgmii_eth_int_n=Const(1),
|
|
# TODO actually fix the platform to support this problem.
|
|
#i_rgmii_eth_mdio=self.eth_interface.mdio,
|
|
o_rgmii_eth_mdc=self.eth_interface.mdc,
|
|
i_rgmii_eth_rx_ctl=self.eth_interface.rx_ctl,
|
|
i_rgmii_eth_rx_data=self.eth_interface.rx_data,
|
|
o_rgmii_eth_tx_ctl=self.eth_interface.tx_ctl,
|
|
o_rgmii_eth_tx_data=self.eth_interface.tx_data,
|
|
|
|
# Wishbone all the things
|
|
i_wishbone_adr=self.adr,
|
|
i_wishbone_dat_w=self.dat_w,
|
|
o_wishbone_dat_r=self.dat_r,
|
|
i_wishbone_sel=self.sel,
|
|
i_wishbone_cyc=self.cyc,
|
|
i_wishbone_stb=self.stb,
|
|
o_wishbone_ack=self.ack,
|
|
i_wishbone_we=self.we,
|
|
i_wishbone_cti=self.cti,
|
|
i_wishbone_bte=self.bte,
|
|
o_wishbone_err=self.err,
|
|
|
|
o_interrupt=self.interrupt,
|
|
)
|
|
|
|
# TODO connect ethernet interface
|
|
|
|
m.submodules.core = core
|
|
|
|
return m
|
|
|
|
|
|
rgmii_layout = [
|
|
("tx_clk", pin_layout(1, "o")),
|
|
("rx_clk", pin_layout(1, "i")),
|
|
("rst", pin_layout(1, "o")),
|
|
("int_n", pin_layout(1, "i")),
|
|
|
|
# TODO is this not IO? why does LiteEth say input?
|
|
# I think the answer is it uses a primitive, not 100% right now
|
|
("mdio", pin_layout(1, "i")),
|
|
("mdc", pin_layout(1, "o")),
|
|
("rx_ctl", pin_layout(1, "i")),
|
|
("rx_data", pin_layout(4, "i")),
|
|
("tx_ctl", pin_layout(1, "o")),
|
|
("tx_data", pin_layout(4, "o")),
|
|
]
|
|
|