lib.fifo: work around Yosys issue with handling of \TRANSPARENT.
authorwhitequark <whitequark@whitequark.org>
Fri, 20 Sep 2019 19:38:42 +0000 (19:38 +0000)
committerwhitequark <whitequark@whitequark.org>
Fri, 20 Sep 2019 19:54:27 +0000 (19:54 +0000)
Because of YosysHQ/yosys#1390, using a transparent port in AsyncFIFO,
instead of being a no-op (as the semantics of \TRANSPARENT would
require it to be in this case), results in a failure to infer BRAM.

This can be easily avoided by using a non-transparent port instead,
which produces the desirable result with Yosys. It does not affect
the semantics on Xilinx platforms, since the interaction between
the two ports in case of address collision is undefined in either
transparent (WRITE_FIRST) or non-transparent (READ_FIRST) case, and
the data out of the write port is not used at all.

Fixes #172.

nmigen/lib/fifo.py

index fc9e32d696bedc7468fdeea2dc71368086376837..34c33463311ead71e7256d17cf99e199fd43603d 100644 (file)
@@ -368,7 +368,8 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
 
         storage = Memory(self.width, self.depth)
         w_port  = m.submodules.w_port = storage.write_port(domain=self._w_domain)
-        r_port  = m.submodules.r_port = storage.read_port (domain=self._r_domain)
+        r_port  = m.submodules.r_port = storage.read_port (domain=self._r_domain,
+                                                           transparent=False)
         m.d.comb += [
             w_port.addr.eq(produce_w_bin[:-1]),
             w_port.data.eq(self.w_data),
@@ -377,6 +378,7 @@ class AsyncFIFO(Elaboratable, FIFOInterface):
         m.d.comb += [
             r_port.addr.eq((consume_r_bin + do_read)[:-1]),
             self.r_data.eq(r_port.data),
+            r_port.en.eq(1),
         ]
 
         if platform == "formal":