From: Jaro Habiger Date: Tue, 18 Aug 2020 11:11:30 +0000 (+0200) Subject: lib.fifo: fix {r,w}_level in AsyncFIFOBuffered X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=b15f0562a62ebbd48b87f2d662cd01845c857c62;p=nmigen.git lib.fifo: fix {r,w}_level in AsyncFIFOBuffered --- diff --git a/nmigen/lib/fifo.py b/nmigen/lib/fifo.py index bbe0e9d..c78c964 100644 --- a/nmigen/lib/fifo.py +++ b/nmigen/lib/fifo.py @@ -506,10 +506,15 @@ class AsyncFIFOBuffered(Elaboratable, FIFOInterface): fifo.w_data.eq(self.w_data), self.w_rdy.eq(fifo.w_rdy), fifo.w_en.eq(self.w_en), - 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) + r_consume_buffered = Signal() + m.d.comb += r_consume_buffered.eq(self.r_rdy - self.r_en) + m.d[self._r_domain] += self.r_level.eq(fifo.r_level + r_consume_buffered) + + w_consume_buffered = Signal() + m.submodules.consume_buffered_cdc = AsyncFFSynchronizer(r_consume_buffered, w_consume_buffered, o_domain=self._w_domain) + m.d.comb += self.w_level.eq(fifo.w_level + w_consume_buffered) with m.If(self.r_en | ~self.r_rdy): m.d[self._r_domain] += [ diff --git a/tests/test_lib_fifo.py b/tests/test_lib_fifo.py index c8674ba..bd5a9d9 100644 --- a/tests/test_lib_fifo.py +++ b/tests/test_lib_fifo.py @@ -282,6 +282,7 @@ class FIFOFormalCase(FHDLTestCase): self.check_async_fifo(AsyncFIFOBuffered(width=8, depth=4)) +# we need this testcase because we cant do model equivalence checking on the async fifos (at the moment) class AsyncFIFOSimCase(FHDLTestCase): def test_async_fifo_r_level_latency(self): fifo = AsyncFIFO(width=32, depth=10, r_domain="sync", w_domain="sync") @@ -331,6 +332,18 @@ class AsyncFIFOSimCase(FHDLTestCase): with simulator.write_vcd("test.vcd"): simulator.run() + def test_async_fifo_level(self): + fifo = AsyncFIFO(width=32, depth=8, r_domain="read", w_domain="write") + self.check_async_fifo_level(fifo, fill_in=5, expected_level=5) + def test_async_fifo_level_full(self): fifo = AsyncFIFO(width=32, depth=8, r_domain="read", w_domain="write") self.check_async_fifo_level(fifo, fill_in=10, expected_level=8) + + def test_async_buffered_fifo_level(self): + fifo = AsyncFIFOBuffered(width=32, depth=9, r_domain="read", w_domain="write") + self.check_async_fifo_level(fifo, fill_in=5, expected_level=5) + + def test_async_buffered_fifo_level_full(self): + fifo = AsyncFIFOBuffered(width=32, depth=9, r_domain="read", w_domain="write") + self.check_async_fifo_level(fifo, fill_in=10, expected_level=9)