Skip to content

Commit

Permalink
Merge pull request #161 from enjoy-digital/wishbone_tx_rx_buses
Browse files Browse the repository at this point in the history
mac/wishbone/LiteEthMACWishboneInterface: Expose separate TX/RX Wishb…
  • Loading branch information
enjoy-digital committed Jun 25, 2024
2 parents 7d24ac3 + a118dd1 commit e4f5385
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 39 deletions.
29 changes: 24 additions & 5 deletions liteeth/gen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
# This file is part of LiteEth.
#
# Copyright (c) 2015-2023 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2015-2024 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2020 Xiretza <xiretza@xiretza.xyz>
# Copyright (c) 2020 Stefan Schrijvers <ximin@ximinity.net>
# Copyright (c) 2022 Victor Suarez Rovere <suarezvictor@gmail.com>
Expand Down Expand Up @@ -413,13 +413,32 @@ def __init__(self, platform, core_config):
# 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)
Expand Down
2 changes: 1 addition & 1 deletion liteeth/mac/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ def __init__(self, phy, dw,
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
Expand Down
71 changes: 43 additions & 28 deletions liteeth/mac/wishbone.py
Original file line number Diff line number Diff line change
@@ -1,67 +1,82 @@
#
# This file is part of LiteEth.
#
# Copyright (c) 2015-2021 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2015-2024 Florent Kermarrec <florent@enjoy-digital.fr>
# Copyright (c) 2015-2016 Sebastien Bourdeauducq <sb@m-labs.hk>
# Copyright (c) 2021 Leon Schuermann <leon@is.currently.online>
# SPDX-License-Identifier: BSD-2-Clause

import math

from litex.gen import *

from liteeth.common import *
from liteeth.mac import sram

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

# 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)
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)
))

# 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
11 changes: 6 additions & 5 deletions test/test_mac_wishbone.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,13 @@ def __init__(self):


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

Expand All @@ -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)
Expand All @@ -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
Expand Down

0 comments on commit e4f5385

Please sign in to comment.