From 6216bd4e992d6594cd51eef1946bc6e335e56a56 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Mon, 15 Apr 2024 10:32:13 +0200 Subject: [PATCH] cores/hyperbus: Add latency_mode parameter and test different latencies/modes in simulation. --- litex/soc/cores/hyperbus.py | 8 +- test/test_hyperbus.py | 169 +++++++++++++++++++++++++++++++++++- 2 files changed, 171 insertions(+), 6 deletions(-) diff --git a/litex/soc/cores/hyperbus.py b/litex/soc/cores/hyperbus.py index 45286fc6a..dc3c7e25c 100644 --- a/litex/soc/cores/hyperbus.py +++ b/litex/soc/cores/hyperbus.py @@ -30,10 +30,14 @@ class HyperRAM(LiteXModule): This core favors portability and ease of use over performance. """ - def __init__(self, pads, latency=6, sys_clk_freq=None, with_csr=True): + def __init__(self, pads, latency=6, latency_mode="fixed", sys_clk_freq=None, with_csr=True): self.pads = pads self.bus = bus = wishbone.Interface(data_width=32, address_width=32, addressing="word") + # Parameters. + # ----------- + assert latency_mode in ["fixed", "variable"] + # Reg Interface. # -------------- self.reg_write = Signal() @@ -218,7 +222,7 @@ class HyperRAM(LiteXModule): NextValue(sr, Cat(Signal(40), self.reg_write_data[8:])), NextState("REG-WRITE-0") ).Else( - If(rwds.i, + If((latency_mode in ["fixed"]) | rwds.i, NextState("WAIT-LATENCY-0") ).Else( NextState("WAIT-LATENCY-1") diff --git a/test/test_hyperbus.py b/test/test_hyperbus.py index 922b4fc9e..9a4bf5cfc 100644 --- a/test/test_hyperbus.py +++ b/test/test_hyperbus.py @@ -33,7 +33,33 @@ class TestHyperBus(unittest.TestCase): pads = Record([("clk_p", 1), ("clk_n", 1), ("cs_n", 1), ("dq", 8), ("rwds", 1)]) hyperram = HyperRAM(pads) - def test_hyperram_write(self): + def test_hyperram_write_latency_5_2x(self): + def fpga_gen(dut): + yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001) + yield + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--_______" + cs_n = "--________________________________________________________------" + dq_oe = "__------------____________________________________--------______" + dq_o = "002000048d0000000000000000000000000000000000000000deadbeef000000" + rwds_oe = "__________________________________________________--------______" + rwds_o = "____________________________________________________----________" + for i in range(3): + yield + for i in range(len(clk)): + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) + yield + + dut = HyperRAM(HyperRamPads(), latency=5) + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + + def test_hyperram_write_latency_6_2x(self): def fpga_gen(dut): yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001) yield @@ -56,10 +82,90 @@ class TestHyperBus(unittest.TestCase): self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) yield - dut = HyperRAM(HyperRamPads()) + dut = HyperRAM(HyperRamPads(), latency=6) run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") - def test_hyperram_read(self): + def test_hyperram_write_latency_7_2x(self): + def fpga_gen(dut): + yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001) + yield + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_______" + cs_n = "--________________________________________________________________________------" + dq_oe = "__------------____________________________________________________--------______" + dq_o = "002000048d00000000000000000000000000000000000000000000000000000000deadbeef000000" + rwds_oe = "__________________________________________________________________--------______" + rwds_o = "____________________________________________________________________----________" + for i in range(3): + yield + for i in range(len(clk)): + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) + yield + + dut = HyperRAM(HyperRamPads(), latency=7) + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + + def test_hyperram_write_latency_7_1x(self): + def fpga_gen(dut): + yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001) + yield + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--_______" + cs_n = "--____________________________________________------" + dq_oe = "__------------________________________--------______" + dq_o = "002000048d0000000000000000000000000000deadbeef000000" + rwds_oe = "______________________________________--------______" + rwds_o = "________________________________________----________" + for i in range(3): + yield + for i in range(len(clk)): + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) + yield + + dut = HyperRAM(HyperRamPads(), latency=7, latency_mode="variable") + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + + def test_hyperram_read_latency_5_2x(self): + def fpga_gen(dut): + dat = yield from dut.bus.read(0x1234) + self.assertEqual(dat, 0xdeadbeef) + dat = yield from dut.bus.read(0x1235) + self.assertEqual(dat, 0xcafefade) + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_" + cs_n = "--________________________________________________________________________" + dq_oe = "__------------____________________________________________________________" + dq_o = "00a000048d0000000000000000000000000000000000000000000000000000000000000000" + dq_i = "00000000000000000000000000000000000000000000000000deadbeefcafefade00000000" + rwds_oe = "__________________________________________________________________________" + for i in range(3): + yield + for i in range(len(clk)): + yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + yield + + dut = HyperRAM(HyperRamPads(), latency=5) + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + + def test_hyperram_read_latency_6_2x(self): def fpga_gen(dut): dat = yield from dut.bus.read(0x1234) self.assertEqual(dat, 0xdeadbeef) @@ -84,9 +190,64 @@ class TestHyperBus(unittest.TestCase): self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) yield - dut = HyperRAM(HyperRamPads()) + dut = HyperRAM(HyperRamPads(), latency=6) run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + def test_hyperram_read_latency_7_2x(self): + def fpga_gen(dut): + dat = yield from dut.bus.read(0x1234) + self.assertEqual(dat, 0xdeadbeef) + dat = yield from dut.bus.read(0x1235) + self.assertEqual(dat, 0xcafefade) + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_" + cs_n = "--________________________________________________________________________________________" + dq_oe = "__------------____________________________________________________________________________" + dq_o = "00a000048d00000000000000000000000000000000000000000000000000000000000000000000000000000000" + dq_i = "000000000000000000000000000000000000000000000000000000000000000000deadbeefcafefade00000000" + rwds_oe = "__________________________________________________________________________________________" + for i in range(3): + yield + for i in range(len(clk)): + yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + yield + + dut = HyperRAM(HyperRamPads(), latency=7) + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") + + def test_hyperram_read_latency_7_1x(self): + def fpga_gen(dut): + dat = yield from dut.bus.read(0x1234) + self.assertEqual(dat, 0xdeadbeef) + dat = yield from dut.bus.read(0x1235) + self.assertEqual(dat, 0xcafefade) + + def hyperram_gen(dut): + clk = "___--__--__--__--__--__--__--__--__--__--__--__--__--__--__--_" + cs_n = "--____________________________________________________________" + dq_oe = "__------------________________________________________________" + dq_o = "00a000048d0000000000000000000000000000000000000000000000000000" + dq_i = "00000000000000000000000000000000000000deadbeefcafefade00000000" + rwds_oe = "______________________________________________________________" + for i in range(3): + yield + for i in range(len(clk)): + yield dut.pads.dq.i.eq(int(dq_i[2*(i//2):2*(i//2)+2], 16)) + self.assertEqual(c2bool(clk[i]), (yield dut.pads.clk)) + self.assertEqual(c2bool(cs_n[i]), (yield dut.pads.cs_n)) + self.assertEqual(c2bool(dq_oe[i]), (yield dut.pads.dq.oe)) + self.assertEqual(int(dq_o[2*(i//2):2*(i//2)+2], 16), (yield dut.pads.dq.o)) + self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) + yield + + dut = HyperRAM(HyperRamPads(), latency=7, latency_mode="variable") + run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") def test_hyperram_reg_write(self): def fpga_gen(dut):