Source code for hwtLib.mem.fifoAsync
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from hwt.code import If, log2ceil
from hwt.hdl.types.bits import Bits
from hwt.interfaces.std import Clk, Rst_n, FifoWriter, FifoReader
from hwt.serializer.mode import serializeParamsUniq
from hwtLib.logic.cntrGray import GrayCntr
from hwtLib.mem.fifo import Fifo
[docs]@serializeParamsUniq
class FifoAsync(Fifo):
"""
Asynchronous fifo using BRAM memory, based on:
http://www.asic-world.com/examples/vhdl/asyn_fifo.html
"""
[docs] def _declr(self):
assert int(self.DEPTH) > 0, "FifoAsync is disabled in this case, do not use it entirely"
if int(self.EXPORT_SIZE) or int(self.EXPORT_SPACE):
raise NotImplementedError()
self.dataIn_clk = Clk()
self.dataOut_clk = Clk()
self.rst_n = Rst_n()
with self._paramsShared():
with self._associated(clk=self.dataIn_clk):
self.dataIn = FifoWriter()
with self._associated(clk=self.dataOut_clk):
self.dataOut = FifoReader()
self.pWr = GrayCntr()
self.pRd = GrayCntr()
self.addrW = log2ceil(self.DEPTH)
for cntr in [self.pWr, self.pRd]:
cntr.DATA_WIDTH.set(self.addrW)
[docs] def _impl(self):
ST_EMPTY, ST_FULL = 0, 1
memory_t = Bits(self.DATA_WIDTH)[self.DEPTH]
memory = self._sig("memory", memory_t)
full = self._sig("full", defVal=0)
empty = self._sig("empty", defVal=1)
status = self._sig("status", defVal=ST_EMPTY)
In = self.dataIn
InClk = self.dataIn_clk._onRisingEdge()
Out = self.dataOut
OutClk = self.dataOut_clk._onRisingEdge()
self.pWr.en(In.en & ~full)
self.pWr.clk(self.dataIn_clk)
self.pWr.rst_n(self.rst_n)
pNextWordToWrite = self.pWr.dataOut
self.pRd.en(Out.en & ~empty)
self.pRd.clk(self.dataOut_clk)
self.pRd.rst_n(self.rst_n)
pNextWordToRead = self.pRd.dataOut
# data out logic
If(OutClk,
If(Out.en & ~empty,
Out.data(memory[pNextWordToRead])
)
)
# data in logic
If(InClk,
If(In.en & ~full,
memory[pNextWordToWrite](In.data)
)
)
equalAddresses = pNextWordToWrite._eq(pNextWordToRead)
aw = self.addrW
nw = pNextWordToWrite
nr = pNextWordToRead
setStatus = nw[aw - 2]._eq(nr[aw - 1]) & (nw[aw - 1] ^ nr[aw - 2])
rstStatus = (nw[aw - 2] ^ nr[aw - 1]) & nw[aw - 1]._eq(nr[aw - 2])
# status latching
If(rstStatus | self.rst_n._isOn(),
status(ST_EMPTY)
).Elif(setStatus,
status(ST_FULL)
)
# data in logic
presetFull = status & equalAddresses
# D Flip-Flop with Asynchronous Preset.
If(presetFull,
full(1)
).Elif(InClk,
full(0)
)
In.wait(full)
# data out logic
presetEmpty = ~status & equalAddresses
# D Flip-Flop w/ Asynchronous Preset.
If(presetEmpty,
empty(1)
).Else(
If(OutClk,
empty(0)
)
)
Out.wait(empty)
if __name__ == "__main__":
from hwt.synthesizer.utils import toRtl
u = FifoAsync()
u.DEPTH.set(4)
print(toRtl(u))