new-sonar/gateware/eth.py
David Lenfesty 8d00e15835 gateware: fix dumb mistakes
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.
2023-03-05 11:43:59 -07:00

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")),
]