Merge pull request #161 from enjoy-digital/wishbone_tx_rx_buses
mac/wishbone/LiteEthMACWishboneInterface: Expose separate TX/RX Wishb…
This commit is contained in:
commit
e4f5385ef1
|
@ -3,7 +3,7 @@
|
||||||
#
|
#
|
||||||
# This file is part of LiteEth.
|
# 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 Xiretza <xiretza@xiretza.xyz>
|
||||||
# Copyright (c) 2020 Stefan Schrijvers <ximin@ximinity.net>
|
# Copyright (c) 2020 Stefan Schrijvers <ximin@ximinity.net>
|
||||||
# Copyright (c) 2022 Victor Suarez Rovere <suarezvictor@gmail.com>
|
# Copyright (c) 2022 Victor Suarez Rovere <suarezvictor@gmail.com>
|
||||||
|
@ -413,13 +413,32 @@ class MACCore(PHYCore):
|
||||||
# AXI-Lite Interface -----------------------------------------------------------------------
|
# AXI-Lite Interface -----------------------------------------------------------------------
|
||||||
axil_bus = axi.AXILiteInterface(address_width=32, data_width=32)
|
axil_bus = axi.AXILiteInterface(address_width=32, data_width=32)
|
||||||
platform.add_extension(axil_bus.get_ios("bus"))
|
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.comb += axil_bus.connect_to_pads(self.platform.request("bus"), mode="slave")
|
||||||
self.bus.add_master(master=axil_bus)
|
self.bus.add_master(master=axil_bus)
|
||||||
|
|
||||||
ethmac_region_size = (nrxslots + ntxslots)*buffer_depth
|
ethmac_rx_region_size = ethmac.rx_slots.constant*ethmac.slot_size.constant
|
||||||
ethmac_region = SoCRegion(origin=self.mem_map.get("ethmac", None), size=ethmac_region_size, cached=False)
|
ethmac_tx_region_size = ethmac.tx_slots.constant*ethmac.slot_size.constant
|
||||||
self.bus.add_slave(name="ethmac", slave=ethmac.bus, region=ethmac_region)
|
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 ----------------------------------------------------------------------
|
# Interrupt Interface ----------------------------------------------------------------------
|
||||||
self.comb += self.platform.request("interrupt").eq(self.ethmac.ev.irq)
|
self.comb += self.platform.request("interrupt").eq(self.ethmac.ev.irq)
|
||||||
|
|
|
@ -77,7 +77,7 @@ class LiteEthMAC(Module, AutoCSR):
|
||||||
if full_memory_we:
|
if full_memory_we:
|
||||||
wishbone_interface = FullMemoryWE()(wishbone_interface)
|
wishbone_interface = FullMemoryWE()(wishbone_interface)
|
||||||
self.submodules.interface = 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()
|
self.csrs = self.interface.get_csrs() + self.core.get_csrs()
|
||||||
if interface == "hybrid":
|
if interface == "hybrid":
|
||||||
# Hardware MAC
|
# Hardware MAC
|
||||||
|
|
|
@ -1,13 +1,15 @@
|
||||||
#
|
#
|
||||||
# This file is part of LiteEth.
|
# 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) 2015-2016 Sebastien Bourdeauducq <sb@m-labs.hk>
|
||||||
# Copyright (c) 2021 Leon Schuermann <leon@is.currently.online>
|
# Copyright (c) 2021 Leon Schuermann <leon@is.currently.online>
|
||||||
# SPDX-License-Identifier: BSD-2-Clause
|
# SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
from litex.gen import *
|
||||||
|
|
||||||
from liteeth.common import *
|
from liteeth.common import *
|
||||||
from liteeth.mac import sram
|
from liteeth.mac import sram
|
||||||
|
|
||||||
|
@ -15,53 +17,66 @@ from litex.soc.interconnect import wishbone
|
||||||
|
|
||||||
# MAC Wishbone Interface ---------------------------------------------------------------------------
|
# MAC Wishbone Interface ---------------------------------------------------------------------------
|
||||||
|
|
||||||
class LiteEthMACWishboneInterface(Module, AutoCSR):
|
class LiteEthMACWishboneInterface(LiteXModule):
|
||||||
def __init__(self, dw, nrxslots=2, ntxslots=2, endianness="big", timestamp=None,
|
def __init__(self, dw, nrxslots=2, ntxslots=2, endianness="big", timestamp=None,
|
||||||
rxslots_read_only = True,
|
rxslots_read_only = True,
|
||||||
txslots_write_only = False,
|
txslots_write_only = False,
|
||||||
):
|
):
|
||||||
self.sink = stream.Endpoint(eth_phy_description(dw))
|
self.sink = stream.Endpoint(eth_phy_description(dw))
|
||||||
self.source = 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.
|
# Storage in SRAM.
|
||||||
|
# ----------------
|
||||||
sram_depth = math.ceil(eth_mtu/(dw//8))
|
sram_depth = math.ceil(eth_mtu/(dw//8))
|
||||||
self.submodules.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots, endianness, timestamp)
|
self.sram = sram.LiteEthMACSRAM(dw, sram_depth, nrxslots, ntxslots, endianness, timestamp)
|
||||||
self.comb += self.sink.connect(self.sram.sink)
|
self.comb += [
|
||||||
self.comb += self.sram.source.connect(self.source)
|
self.sink.connect(self.sram.sink),
|
||||||
|
self.sram.source.connect(self.source),
|
||||||
|
]
|
||||||
|
|
||||||
# Wishbone SRAM interfaces for the writer SRAM (i.e. Ethernet RX).
|
# Ethernet Wishbone SRAM interfaces exposure.
|
||||||
wb_rx_sram_ifs = []
|
# -------------------------------------------
|
||||||
for n in range(nrxslots):
|
self._expose_wishbone_sram_interfaces(
|
||||||
wb_rx_sram_ifs.append(wishbone.SRAM(
|
bus = self.bus_rx,
|
||||||
mem_or_size = self.sram.writer.mems[n],
|
dw = dw,
|
||||||
read_only = rxslots_read_only,
|
mems = self.sram.writer.mems,
|
||||||
bus = wishbone.Interface(data_width = dw)
|
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).
|
# Expose SRAMs on Bus.
|
||||||
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.
|
|
||||||
wb_slaves = []
|
wb_slaves = []
|
||||||
|
sram_depth = math.ceil(eth_mtu/(dw//8))
|
||||||
decoderoffset = log2_int(sram_depth, need_pow2=False)
|
decoderoffset = log2_int(sram_depth, need_pow2=False)
|
||||||
rx_decoderbits = log2_int(len(wb_rx_sram_ifs))
|
decoderbits = log2_int(len(wb_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
|
|
||||||
for n, wb_sram_if in enumerate(wb_sram_ifs):
|
for n, wb_sram_if in enumerate(wb_sram_ifs):
|
||||||
def slave_filter(a, v=n):
|
def slave_filter(a, v=n):
|
||||||
return a[decoderoffset:decoderoffset+decoderbits] == v
|
return a[decoderoffset:decoderoffset+decoderbits] == v
|
||||||
wb_slaves.append((slave_filter, wb_sram_if.bus))
|
wb_slaves.append((slave_filter, wb_sram_if.bus))
|
||||||
self.submodules += wb_sram_if
|
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
|
self.submodules += wb_con
|
||||||
|
|
|
@ -102,12 +102,13 @@ class DUT(Module):
|
||||||
|
|
||||||
|
|
||||||
def main_generator(dut):
|
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_reader_driver = SRAMReaderDriver(dut.ethmac.interface.sram.reader)
|
||||||
sram_writer_driver = SRAMWriterDriver(dut.ethmac.interface.sram.writer)
|
sram_writer_driver = SRAMWriterDriver(dut.ethmac.interface.sram.writer)
|
||||||
|
|
||||||
sram_writer_slots_offset = [0x000, 0x200]
|
sram_writer_slots_offset = [0x000, 0x200]
|
||||||
sram_reader_slots_offset = [0x400, 0x600]
|
sram_reader_slots_offset = [0x000, 0x200]
|
||||||
|
|
||||||
length = 150+2
|
length = 150+2
|
||||||
|
|
||||||
|
@ -121,7 +122,7 @@ def main_generator(dut):
|
||||||
# fill tx memory
|
# fill tx memory
|
||||||
for i in range(length//4+1):
|
for i in range(length//4+1):
|
||||||
dat = int.from_bytes(tx_payload[4*i:4*(i+1)], "big")
|
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
|
# send tx payload & wait
|
||||||
yield from sram_reader_driver.start(slot, length)
|
yield from sram_reader_driver.start(slot, length)
|
||||||
|
@ -135,8 +136,8 @@ def main_generator(dut):
|
||||||
# get rx payload (loopback on PHY Model)
|
# get rx payload (loopback on PHY Model)
|
||||||
rx_payload = []
|
rx_payload = []
|
||||||
for i in range(length//4+1):
|
for i in range(length//4+1):
|
||||||
yield from wishbone_master.read(sram_writer_slots_offset[slot]+i)
|
yield from wishbone_tx_master.read(sram_writer_slots_offset[slot]+i)
|
||||||
dat = wishbone_master.dat
|
dat = wishbone_tx_master.dat
|
||||||
rx_payload += list(dat.to_bytes(4, byteorder='big'))
|
rx_payload += list(dat.to_bytes(4, byteorder='big'))
|
||||||
|
|
||||||
# check results
|
# check results
|
||||||
|
|
Loading…
Reference in New Issue