cores/hyperbus: Add latency_mode parameter and test different latencies/modes in simulation.

This commit is contained in:
Florent Kermarrec 2024-04-15 10:32:13 +02:00
parent 33a1fcda48
commit 6216bd4e99
2 changed files with 171 additions and 6 deletions

View File

@ -30,10 +30,14 @@ class HyperRAM(LiteXModule):
This core favors portability and ease of use over performance. 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.pads = pads
self.bus = bus = wishbone.Interface(data_width=32, address_width=32, addressing="word") self.bus = bus = wishbone.Interface(data_width=32, address_width=32, addressing="word")
# Parameters.
# -----------
assert latency_mode in ["fixed", "variable"]
# Reg Interface. # Reg Interface.
# -------------- # --------------
self.reg_write = Signal() self.reg_write = Signal()
@ -218,7 +222,7 @@ class HyperRAM(LiteXModule):
NextValue(sr, Cat(Signal(40), self.reg_write_data[8:])), NextValue(sr, Cat(Signal(40), self.reg_write_data[8:])),
NextState("REG-WRITE-0") NextState("REG-WRITE-0")
).Else( ).Else(
If(rwds.i, If((latency_mode in ["fixed"]) | rwds.i,
NextState("WAIT-LATENCY-0") NextState("WAIT-LATENCY-0")
).Else( ).Else(
NextState("WAIT-LATENCY-1") NextState("WAIT-LATENCY-1")

View File

@ -33,7 +33,33 @@ class TestHyperBus(unittest.TestCase):
pads = Record([("clk_p", 1), ("clk_n", 1), ("cs_n", 1), ("dq", 8), ("rwds", 1)]) pads = Record([("clk_p", 1), ("clk_n", 1), ("cs_n", 1), ("dq", 8), ("rwds", 1)])
hyperram = HyperRAM(pads) 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): def fpga_gen(dut):
yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001) yield from dut.bus.write(0x1234, 0xdeadbeef, sel=0b1001)
yield yield
@ -56,10 +82,90 @@ class TestHyperBus(unittest.TestCase):
self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o)) self.assertEqual(c2bool(rwds_o[i]), (yield dut.pads.rwds.o))
yield yield
dut = HyperRAM(HyperRamPads()) dut = HyperRAM(HyperRamPads(), latency=6)
run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") 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): def fpga_gen(dut):
dat = yield from dut.bus.read(0x1234) dat = yield from dut.bus.read(0x1234)
self.assertEqual(dat, 0xdeadbeef) self.assertEqual(dat, 0xdeadbeef)
@ -84,9 +190,64 @@ class TestHyperBus(unittest.TestCase):
self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe)) self.assertEqual(c2bool(rwds_oe[i]), (yield dut.pads.rwds.oe))
yield yield
dut = HyperRAM(HyperRamPads()) dut = HyperRAM(HyperRamPads(), latency=6)
run_simulation(dut, [fpga_gen(dut), hyperram_gen(dut)], vcd_name="sim.vcd") 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 test_hyperram_reg_write(self):
def fpga_gen(dut): def fpga_gen(dut):