From 47ce15b431a3aaead36b2501bbd0c8aa2fe2ecae Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 21 Jul 2020 19:35:14 +0200 Subject: [PATCH] interconnect/wishbone: add minimal UpConverter. --- litex/soc/interconnect/wishbone.py | 26 ++++++++++++-- test/test_wishbone.py | 55 ++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 test/test_wishbone.py diff --git a/litex/soc/interconnect/wishbone.py b/litex/soc/interconnect/wishbone.py index 6b36e1b90..5a451d508 100644 --- a/litex/soc/interconnect/wishbone.py +++ b/litex/soc/interconnect/wishbone.py @@ -3,6 +3,8 @@ # This file is Copyright (c) 2018 Tim 'mithro' Ansell # License: BSD +from math import log2 + from functools import reduce from operator import or_ @@ -229,7 +231,7 @@ class DownConverter(Module): """ def __init__(self, master, slave): - dw_from = len(master.dat_r) + dw_from = len(master.dat_w) dw_to = len(slave.dat_w) ratio = dw_from//dw_to @@ -275,6 +277,25 @@ class DownConverter(Module): self.comb += master.dat_r.eq(Cat(dat_r[dw_to:], slave.dat_r)) self.sync += If(slave.ack | skip, dat_r.eq(master.dat_r)) +class UpConverter(Module): + """UpConverter""" + def __init__(self, master, slave): + dw_from = len(master.dat_w) + dw_to = len(slave.dat_w) + ratio = dw_to//dw_from + + # # # + + self.comb += master.connect(slave, omit={"adr", "sel", "dat_w", "dat_r"}) + cases = {} + for i in range(ratio): + cases[i] = [ + slave.adr.eq(master.adr[int(log2(ratio)):]), + slave.sel[i*dw_from//8:(i+1)*dw_from//8].eq(2**(dw_from//8) - 1), + slave.dat_w[i*dw_from:(i+1)*dw_from].eq(master.dat_w), + master.dat_r.eq(slave.dat_r[i*dw_from:(i+1)*dw_from]), + ] + self.comb += Case(master.adr[:int(log2(ratio))], cases) class Converter(Module): """Converter @@ -295,7 +316,8 @@ class Converter(Module): downconverter = DownConverter(master, slave) self.submodules += downconverter elif dw_from < dw_to: - raise NotImplementedError + upconverter = UpConverter(master, slave) + self.submodules += upconverter else: self.comb += master.connect(slave) diff --git a/test/test_wishbone.py b/test/test_wishbone.py new file mode 100644 index 000000000..fa8e6f2f4 --- /dev/null +++ b/test/test_wishbone.py @@ -0,0 +1,55 @@ +# This file is Copyright (c) 2019 Florent Kermarrec +# License: BSD + +import unittest + +from migen import * + +from litex.soc.interconnect import wishbone + +# TestWishbone ------------------------------------------------------------------------------------- + +class TestWishbone(unittest.TestCase): + def test_upconverter_16_32(self): + def generator(dut): + yield from dut.wb16.write(0x0000, 0x1234) + yield from dut.wb16.write(0x0001, 0x5678) + yield from dut.wb16.write(0x0002, 0xdead) + yield from dut.wb16.write(0x0003, 0xbeef) + self.assertEqual((yield from dut.wb16.read(0x0000)), 0x1234) + self.assertEqual((yield from dut.wb16.read(0x0001)), 0x5678) + self.assertEqual((yield from dut.wb16.read(0x0002)), 0xdead) + self.assertEqual((yield from dut.wb16.read(0x0003)), 0xbeef) + + class DUT(Module): + def __init__(self): + self.wb16 = wishbone.Interface(data_width=16) + wb32 = wishbone.Interface(data_width=32) + up_converter = wishbone.UpConverter(self.wb16, wb32) + self.submodules += up_converter + wishbone_mem = wishbone.SRAM(32, bus=wb32) + self.submodules += wishbone_mem + + dut = DUT() + run_simulation(dut, generator(dut)) + + def test_converter_32_64_32(self): + def generator(dut): + yield from dut.wb32.write(0x0000, 0x12345678) + yield from dut.wb32.write(0x0001, 0xdeadbeef) + self.assertEqual((yield from dut.wb32.read(0x0000)), 0x12345678) + self.assertEqual((yield from dut.wb32.read(0x0001)), 0xdeadbeef) + + class DUT(Module): + def __init__(self): + self.wb32 = wishbone.Interface(data_width=32) + wb64 = wishbone.Interface(data_width=64) + wb32 = wishbone.Interface(data_width=32) + up_converter = wishbone.UpConverter(self.wb32, wb64) + down_converter = wishbone.DownConverter(wb64, wb32) + self.submodules += up_converter, down_converter + wishbone_mem = wishbone.SRAM(32, bus=wb32) + self.submodules += wishbone_mem + + dut = DUT() + run_simulation(dut, generator(dut))