From: Sebastien Bourdeauducq Date: Thu, 25 Apr 2013 11:30:37 +0000 (+0200) Subject: genlib/fifo: add asynchronous FIFO X-Git-Tag: 24jan2021_ls180~2099^2~601 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=67c3119249da0f7b6ba9747d7b11e47459f0ee47;p=litex.git genlib/fifo: add asynchronous FIFO --- diff --git a/migen/genlib/fifo.py b/migen/genlib/fifo.py index 23f8c9be..9f88ab5e 100644 --- a/migen/genlib/fifo.py +++ b/migen/genlib/fifo.py @@ -1,6 +1,7 @@ from migen.fhdl.structure import * from migen.fhdl.specials import Memory from migen.fhdl.module import Module +from migen.genlib.cdc import MultiReg, GrayCounter def _inc(signal, modulo): if modulo == 2**len(signal): @@ -12,7 +13,7 @@ def _inc(signal, modulo): signal.eq(signal + 1) ) -class SyncFIFO(Module): +class _FIFOInterface: def __init__(self, width, depth): self.din = Signal(width) self.we = Signal() @@ -21,6 +22,10 @@ class SyncFIFO(Module): self.re = Signal() self.readable = Signal() # not empty +class SyncFIFO(Module, _FIFOInterface): + def __init__(self, width, depth): + _FIFOInterface.__init__(self, width, depth) + ### do_write = Signal() @@ -62,3 +67,47 @@ class SyncFIFO(Module): self.writable.eq(level != depth), self.readable.eq(level != 0) ] + +class AsyncFIFO(Module, _FIFOInterface): + def __init__(self, width, depth): + _FIFOInterface.__init__(self, width, depth) + + ### + + depth_bits = log2_int(depth, True) + + produce = GrayCounter(depth_bits+1) + self.add_submodule(produce, "write") + consume = GrayCounter(depth_bits+1) + self.add_submodule(consume, "read") + self.comb += [ + produce.ce.eq(self.writable & self.we), + consume.ce.eq(self.readable & self.re) + ] + + # TODO: disable retiming on produce.q and consume.q + + produce_rdomain = Signal(depth_bits+1) + self.specials += MultiReg(produce.q, produce_rdomain, "read") + consume_wdomain = Signal(depth_bits+1) + self.specials += MultiReg(consume.q, consume_wdomain, "write") + self.comb += [ + self.writable.eq((produce.q[-1] == consume_wdomain[-1]) + | (produce.q[-2] == consume_wdomain[-2]) + | (produce.q[:-2] != consume_wdomain[:-2])), + self.readable.eq(consume.q != produce_rdomain) + ] + + storage = Memory(width, depth) + self.specials += storage + wrport = storage.get_port(write_capable=True, clock_domain="write") + self.comb += [ + wrport.adr.eq(produce.q_binary[:-1]), + wrport.dat_w.eq(self.din), + wrport.we.eq(produce.ce) + ] + rdport = storage.get_port(clock_domain="read") + self.comb += [ + rdport.adr.eq(consume.q_binary[:-1]), + self.dout.eq(rdport.dat_r) + ]