diff --git a/litedram/phy/utils.py b/litedram/phy/utils.py index 801cc1e..5691f0a 100644 --- a/litedram/phy/utils.py +++ b/litedram/phy/utils.py @@ -44,11 +44,9 @@ def edge(mod, cond): return ~cond_d & cond class ConstBitSlip(Module): - def __init__(self, dw, slp, i=None, o=None, cycles=None): + def __init__(self, dw, slp, cycles, i=None, o=None, register=True): self.i = Signal(dw, name='i') if i is None else i self.o = Signal(dw, name='o') if o is None else o - if cycles is None: - cycles = self.min_cycles(slp, dw) assert cycles >= 1, cycles assert 0 <= slp <= cycles*dw-1, (slp, cycles, dw) @@ -57,7 +55,12 @@ class ConstBitSlip(Module): # # # self.r = r = Signal((cycles+1)*dw, reset_less=True) - self.sync += r.eq(Cat(r[dw:], self.i)) + if register: + self.sync += r.eq(Cat(r[dw:], self.i)) + else: + reg = Signal(cycles*dw, reset_less=True) + self.sync += reg.eq(Cat(reg[dw:], self.i)) + self.comb += r.eq(Cat(reg, self.i)) self.comb += self.o.eq(r[slp+1:dw+slp+1]) @staticmethod diff --git a/test/test_phy_utils.py b/test/test_phy_utils.py index 24caaa4..453c912 100644 --- a/test/test_phy_utils.py +++ b/test/test_phy_utils.py @@ -9,7 +9,7 @@ import itertools from migen import * -from litedram.phy.utils import Serializer, Deserializer, Latency, chunks, bit +from litedram.phy.utils import Serializer, Deserializer, Latency, chunks, bit, ConstBitSlip from test.phy_common import run_simulation @@ -186,3 +186,64 @@ class LatencyTests(unittest.TestCase): with self.assertRaises(ValueError): getattr(l, attr) l.sys6x # ok + +class TestConstBitslip(unittest.TestCase): + class Dut(Module): + def __init__(self, dw, **kwargs): + self.i = Signal(dw) + self.o = Signal(dw) + bs = ConstBitSlip(dw, **kwargs) + self.submodules += bs + self.comb += [ + self.o.eq(bs.o), + bs.i.eq(self.i), + ] + + def test_register(self): + outputs = { + 0: [0b0011, 0b0000], + 1: [0b0110, 0b0000], + 2: [0b1100, 0b0000], + 3: [0b1000, 0b0001], + } + + for slp, out in outputs.items(): + with self.subTest(slp=slp): + def generator(dut): + yield dut.i.eq(0b0011) + yield + self.assertEqual((yield dut.o), 0) + yield dut.i.eq(0) + yield + self.assertEqual((yield dut.o), out[0]) + yield + self.assertEqual((yield dut.o), out[1]) + yield + self.assertEqual((yield dut.o), 0) + + dut = self.Dut(dw=4, slp=slp, cycles=1) + run_simulation(dut, generator(dut)) + + def test_no_register(self): + outputs = { + 0: [0b0011, 0b0000], + 1: [0b0110, 0b0000], + 2: [0b1100, 0b0000], + 3: [0b1000, 0b0001], + } + + for slp, out in outputs.items(): + with self.subTest(slp=slp): + def generator(dut): + self.assertEqual((yield dut.o), 0) + yield dut.i.eq(0b0011) + yield + self.assertEqual((yield dut.o), out[0]) + yield dut.i.eq(0) + yield + self.assertEqual((yield dut.o), out[1]) + yield + self.assertEqual((yield dut.o), 0) + + dut = self.Dut(dw=4, slp=slp, cycles=1, register=False) + run_simulation(dut, generator(dut))