diff --git a/liteeth/gen.py b/liteeth/gen.py index 21dd72f..fc1ca1d 100755 --- a/liteeth/gen.py +++ b/liteeth/gen.py @@ -3,7 +3,7 @@ # # This file is part of LiteEth. # -# Copyright (c) 2015-2023 Florent Kermarrec +# Copyright (c) 2015-2024 Florent Kermarrec # Copyright (c) 2020 Xiretza # Copyright (c) 2020 Stefan Schrijvers # Copyright (c) 2022 Victor Suarez Rovere @@ -413,13 +413,32 @@ class MACCore(PHYCore): # 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) + ethmac_rx_region_size = ethmac.rx_slots.constant*ethmac.slot_size.constant + ethmac_tx_region_size = ethmac.tx_slots.constant*ethmac.slot_size.constant + ethmac_region_size = ethmac_rx_region_size + ethmac_tx_region_size + self.bus.add_region("ethmac", SoCRegion( + origin = self.mem_map.get("ethmac", None), + size = ethmac_region_size, + linker = True, + cached = False, + )) + ethmac_rx_region = SoCRegion( + origin = self.bus.regions["ethmac"].origin + 0, + size = ethmac_rx_region_size, + linker = True, + cached = False, + ) + self.bus.add_slave(name="ethmac_rx", slave=ethmac.bus_rx, region=ethmac_rx_region) + ethmac_tx_region = SoCRegion( + origin = self.bus.regions["ethmac"].origin + ethmac_rx_region_size, + size = ethmac_tx_region_size, + linker = True, + cached = False, + ) + self.bus.add_slave(name="ethmac_tx", slave=ethmac.bus_tx, region=ethmac_tx_region) # Interrupt Interface ---------------------------------------------------------------------- self.comb += self.platform.request("interrupt").eq(self.ethmac.ev.irq) diff --git a/liteeth/mac/__init__.py b/liteeth/mac/__init__.py index e451904..bfb94b4 100644 --- a/liteeth/mac/__init__.py +++ b/liteeth/mac/__init__.py @@ -77,7 +77,7 @@ class LiteEthMAC(Module, AutoCSR): if full_memory_we: wishbone_interface = FullMemoryWE()(wishbone_interface) self.submodules.interface = wishbone_interface - self.ev, self.bus = self.interface.sram.ev, self.interface.bus + self.ev, self.bus_rx, self.bus_tx = self.interface.sram.ev, self.interface.bus_rx, self.interface.bus_tx self.csrs = self.interface.get_csrs() + self.core.get_csrs() if interface == "hybrid": # Hardware MAC diff --git a/liteeth/mac/wishbone.py b/liteeth/mac/wishbone.py index 1eeffbf..1be58de 100644 --- a/liteeth/mac/wishbone.py +++ b/liteeth/mac/wishbone.py @@ -1,13 +1,15 @@ # # This file is part of LiteEth. # -# Copyright (c) 2015-2021 Florent Kermarrec +# Copyright (c) 2015-2024 Florent Kermarrec # Copyright (c) 2015-2016 Sebastien Bourdeauducq # Copyright (c) 2021 Leon Schuermann # SPDX-License-Identifier: BSD-2-Clause import math +from litex.gen import * + from liteeth.common import * from liteeth.mac import sram @@ -15,53 +17,66 @@ from litex.soc.interconnect import wishbone # MAC Wishbone Interface --------------------------------------------------------------------------- -class LiteEthMACWishboneInterface(Module, AutoCSR): +class LiteEthMACWishboneInterface(LiteXModule): def __init__(self, dw, nrxslots=2, ntxslots=2, endianness="big", timestamp=None, rxslots_read_only = True, txslots_write_only = False, ): self.sink = stream.Endpoint(eth_phy_description(dw)) self.source = stream.Endpoint(eth_phy_description(dw)) - self.bus = wishbone.Interface(data_width=dw) + self.bus_rx = wishbone.Interface(data_width=dw) + self.bus_tx = wishbone.Interface(data_width=dw) # # # # Storage in SRAM. + # ---------------- sram_depth = math.ceil(eth_mtu/(dw//8)) - self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots, endianness, timestamp) - self.comb += self.sink.connect(self.sram.sink) - self.comb += self.sram.source.connect(self.source) + self.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots, endianness, timestamp) + self.comb += [ + self.sink.connect(self.sram.sink), + self.sram.source.connect(self.source), + ] - # Wishbone SRAM interfaces for the writer SRAM (i.e. Ethernet RX). - wb_rx_sram_ifs = [] - for n in range(nrxslots): - wb_rx_sram_ifs.append(wishbone.SRAM( - mem_or_size = self.sram.writer.mems[n], - read_only = rxslots_read_only, - bus = wishbone.Interface(data_width = dw) + # Ethernet Wishbone SRAM interfaces exposure. + # ------------------------------------------- + self._expose_wishbone_sram_interfaces( + bus = self.bus_rx, + dw = dw, + mems = self.sram.writer.mems, + nslots = nrxslots, + read_only = rxslots_read_only, + write_only = False, + ) + self._expose_wishbone_sram_interfaces( + bus = self.bus_tx, + dw = dw, + mems = self.sram.reader.mems, + nslots = ntxslots, + read_only = False, + write_only = txslots_write_only, + ) + + def _expose_wishbone_sram_interfaces(self, bus, dw, mems, nslots, read_only, write_only): + # SRAMs. + wb_sram_ifs = [] + for n in range(nslots): + wb_sram_ifs.append(wishbone.SRAM( + mem_or_size = mems[n], + read_only = read_only, + write_only = write_only, + bus = wishbone.Interface(data_width=dw) )) - # Wishbone SRAM interfaces for the reader SRAM (i.e. Ethernet TX). - wb_tx_sram_ifs = [] - for n in range(ntxslots): - wb_tx_sram_ifs.append(wishbone.SRAM( - mem_or_size = self.sram.reader.mems[n], - write_only = txslots_write_only, - bus = wishbone.Interface(data_width = dw) - )) - - # Expose Wishbone SRAMs on a single Wishbone bus. - # CHECKME: Check Decoder width for 64-bit. + # Expose SRAMs on Bus. wb_slaves = [] + sram_depth = math.ceil(eth_mtu/(dw//8)) decoderoffset = log2_int(sram_depth, need_pow2=False) - rx_decoderbits = log2_int(len(wb_rx_sram_ifs)) - tx_decoderbits = log2_int(len(wb_tx_sram_ifs)) - decoderbits = max(rx_decoderbits, tx_decoderbits) + 1 - wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs + decoderbits = log2_int(len(wb_sram_ifs)) for n, wb_sram_if in enumerate(wb_sram_ifs): def slave_filter(a, v=n): return a[decoderoffset:decoderoffset+decoderbits] == v wb_slaves.append((slave_filter, wb_sram_if.bus)) self.submodules += wb_sram_if - wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True) + wb_con = wishbone.Decoder(bus, wb_slaves, register=True) self.submodules += wb_con diff --git a/test/test_mac_wishbone.py b/test/test_mac_wishbone.py index d05c6b7..a3e4abf 100644 --- a/test/test_mac_wishbone.py +++ b/test/test_mac_wishbone.py @@ -102,12 +102,13 @@ class DUT(Module): def main_generator(dut): - wishbone_master = WishboneMaster(dut.ethmac.bus) + wishbone_tx_master = WishboneMaster(dut.ethmac.bus_tx) + wishbone_rx_master = WishboneMaster(dut.ethmac.bus_rx) sram_reader_driver = SRAMReaderDriver(dut.ethmac.interface.sram.reader) sram_writer_driver = SRAMWriterDriver(dut.ethmac.interface.sram.writer) sram_writer_slots_offset = [0x000, 0x200] - sram_reader_slots_offset = [0x400, 0x600] + sram_reader_slots_offset = [0x000, 0x200] length = 150+2 @@ -121,7 +122,7 @@ def main_generator(dut): # fill tx memory for i in range(length//4+1): dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big") - yield from wishbone_master.write(sram_reader_slots_offset[slot]+i, dat) + yield from wishbone_tx_master.write(sram_reader_slots_offset[slot]+i, dat) # send tx payload & wait yield from sram_reader_driver.start(slot, length) @@ -135,8 +136,8 @@ def main_generator(dut): # get rx payload (loopback on PHY Model) rx_payload = [] for i in range(length//4+1): - yield from wishbone_master.read(sram_writer_slots_offset[slot]+i) - dat = wishbone_master.dat + yield from wishbone_tx_master.read(sram_writer_slots_offset[slot]+i) + dat = wishbone_tx_master.dat rx_payload += list(dat.to_bytes(4, byteorder='big')) # check results