lib.fifo.AsyncFIFO: fix incorrect latency of r_level.
authoranuejn <jarohabiger@googlemail.com>
Sat, 24 Oct 2020 14:58:23 +0000 (16:58 +0200)
committerLuke Kenneth Casson Leighton <lkcl@lkcl.net>
Fri, 31 Dec 2021 15:15:49 +0000 (15:15 +0000)
Co-authored-by: Andrew Wygle <awygle@gmail.com>
nmigen/lib/fifo.py
tests/test_lib_fifo.py

index fa5b265cfb0e0829e559fb120713216155496051..d0b79bd4993296cc7198eeff2396a8dd16b0b58e 100644 (file)
@@ -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)
index 4722318ed2aade3bd66b17b87aaff1100cc0b2bc..7de265f270d7d08a332e3bf037c96ea6b50711a1 100644 (file)
@@ -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