From 62855e14f60a53476bd75714888c0256822cb6ca Mon Sep 17 00:00:00 2001 From: Leon Schuermann Date: Sat, 14 Aug 2021 13:28:46 +0200 Subject: [PATCH] mac/wishbone: support smaller Wishbone data width than SRAM dw Adds a wishbone.Converter between the SRAM Wishbone slave and the wishbone.Decoder connected to the SoC bus, to support SRAM data widths larger than the system bus Wishbone data width. This is important to be able to run a 32-bit SoC with a 64-bit MAC data path and SRAM storage. Signed-off-by: Leon Schuermann --- liteeth/mac/wishbone.py | 64 +++++++++++++++++++++++++++++++++-------- 1 file changed, 52 insertions(+), 12 deletions(-) diff --git a/liteeth/mac/wishbone.py b/liteeth/mac/wishbone.py index 6622053..09f5471 100644 --- a/liteeth/mac/wishbone.py +++ b/liteeth/mac/wishbone.py @@ -1,10 +1,13 @@ # # This file is part of LiteEth. # +# Copyright (c) 2021 Leon Schuermann # Copyright (c) 2015-2020 Florent Kermarrec # Copyright (c) 2015-2016 Sebastien Bourdeauducq # SPDX-License-Identifier: BSD-2-Clause +import math + from liteeth.common import * from liteeth.mac import sram @@ -13,35 +16,72 @@ from litex.soc.interconnect import wishbone # MAC Wishbone Interface --------------------------------------------------------------------------- class LiteEthMACWishboneInterface(Module, AutoCSR): - def __init__(self, dw, nrxslots=2, ntxslots=2, endianness="big", timestamp=None): + def __init__(self, + dw, + nrxslots=2, + ntxslots=2, + endianness="big", + timestamp=None, + wishbone_data_width=32): self.sink = stream.Endpoint(eth_phy_description(dw)) self.source = stream.Endpoint(eth_phy_description(dw)) self.bus = wishbone.Interface() # # # + # Ratio between Wishbone data width and SRAM data width, + # required for calculating the proper address space length and + # address decoding bits. Example: 64bit SRAM data width, 32bit + # Wishbone data data width -> bus_ratio = 2 + bus_ratio = max(1, dw // wishbone_data_width) + # Storage in SRAM - sram_depth = 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.comb += self.sink.connect(self.sram.sink) self.comb += self.sram.source.connect(self.source) - # Wishbone interface - wb_rx_sram_ifs = [wishbone.SRAM(self.sram.writer.mems[n], read_only=True) - for n in range(nrxslots)] - wb_tx_sram_ifs = [wishbone.SRAM(self.sram.reader.mems[n], read_only=False) - for n in range(ntxslots)] - wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs + # Wishbone SRAM interfaces and Wishbone data width converters + # for the writer SRAM (i.e. Ethernet RX) + wb_rx_sram_ifs = [] + for n in range(nrxslots): + writer_sram_native_width = wishbone.SRAM( + self.sram.writer.mems[n], + read_only=True, + bus = wishbone.Interface(data_width = dw) + ) + self.submodules += writer_sram_native_width + writer_sram_converted_width = wishbone.Interface(data_width = wishbone_data_width) + writer_sram_converter = wishbone.Converter(writer_sram_converted_width, writer_sram_native_width.bus) + self.submodules += writer_sram_converter + wb_rx_sram_ifs += [writer_sram_converted_width] - wb_slaves = [] - decoderoffset = log2_int(sram_depth, need_pow2=False) + # Wishbone SRAM interfaces and Wishbone data width converters + # for the reader SRAM (i.e. Ethernet TX) + wb_tx_sram_ifs = [] + for n in range(nrxslots): + reader_sram_native_width = wishbone.SRAM( + self.sram.reader.mems[n], + read_only=False, + bus = wishbone.Interface(data_width = dw) + ) + self.submodules += reader_sram_native_width + reader_sram_converted_width = wishbone.Interface(data_width = wishbone_data_width) + reader_sram_converter = wishbone.Converter(reader_sram_converted_width, reader_sram_native_width.bus) + self.submodules += reader_sram_converter + wb_tx_sram_ifs += [reader_sram_converted_width] + + self.wb_sram_ifs = wb_sram_ifs = wb_rx_sram_ifs + wb_tx_sram_ifs + + wb_slaves = [] + decoderoffset = log2_int(sram_depth * bus_ratio, 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 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_slaves.append((slave_filter, wb_sram_if)) + wb_con = wishbone.Decoder(self.bus, wb_slaves, register=True) self.submodules += wb_con