From d8273a15c38a7937d379e34e0f364596cf9584e5 Mon Sep 17 00:00:00 2001 From: anuejn Date: Sat, 24 Oct 2020 16:58:23 +0200 Subject: [PATCH] lib.fifo.AsyncFIFO: fix incorrect latency of r_level. Co-authored-by: Andrew Wygle --- nmigen/lib/fifo.py | 7 ++++--- tests/test_lib_fifo.py | 23 +++++++++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/nmigen/lib/fifo.py b/nmigen/lib/fifo.py index fa5b265..d0b79bd 100644 --- a/nmigen/lib/fifo.py +++ b/nmigen/lib/fifo.py @@ -369,7 +369,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface): produce_dec = m.submodules.produce_dec = \ GrayDecoder(self._ctr_bits) m.d.comb += produce_dec.i.eq(produce_r_gry), - m.d[self._r_domain] += produce_r_bin.eq(produce_dec.o) + m.d.comb += produce_r_bin.eq(produce_dec.o) w_full = Signal() r_empty = Signal() @@ -381,7 +381,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface): ] m.d[self._w_domain] += self.w_level.eq((produce_w_bin - consume_w_bin)[:self._ctr_bits-1]) - m.d[self._r_domain] += self.r_level.eq((produce_r_bin - consume_r_bin)[:self._ctr_bits-1]) + m.d.comb += self.r_level.eq((produce_r_bin - consume_r_bin)[:self._ctr_bits-1]) storage = Memory(width=self.width, depth=self.depth) w_port = m.submodules.w_port = storage.write_port(domain=self._w_domain) @@ -509,12 +509,13 @@ class AsyncFIFOBuffered(Elaboratable, FIFOInterface): self.w_level.eq(fifo.w_level), ] + m.d[self._r_domain] += self.r_level.eq(fifo.r_level + self.r_rdy - self.r_en) + with m.If(self.r_en | ~self.r_rdy): m.d[self._r_domain] += [ self.r_data.eq(fifo.r_data), self.r_rdy.eq(fifo.r_rdy), self.r_rst.eq(fifo.r_rst), - self.r_level.eq(fifo.r_level), ] m.d.comb += [ fifo.r_en.eq(1) diff --git a/tests/test_lib_fifo.py b/tests/test_lib_fifo.py index 4722318..7de265f 100644 --- a/tests/test_lib_fifo.py +++ b/tests/test_lib_fifo.py @@ -280,3 +280,26 @@ class FIFOFormalCase(FHDLTestCase): def test_async_buffered(self): self.check_async_fifo(AsyncFIFOBuffered(width=8, depth=4)) + + +class AsyncFIFOSimCase(FHDLTestCase): + def test_async_fifo_r_level_latency(self): + fifo = AsyncFIFO(width=32, depth=10, r_domain="sync", w_domain="sync") + + ff_syncronizer_latency = 2 + + def testbench(): + for i in range(10): + yield fifo.w_data.eq(i) + yield fifo.w_en.eq(1) + yield + + if (i - ff_syncronizer_latency) > 0: + self.assertEqual((yield fifo.r_level), i - ff_syncronizer_latency) + else: + self.assertEqual((yield fifo.r_level), 0) + + simulator = Simulator(fifo) + simulator.add_clock(100e-6) + simulator.add_sync_process(testbench) + simulator.run() \ No newline at end of file -- 2.30.2