FIFO timing, the right way

Hi all,

I am working on a block that needs to accumulate (at least) K data items and then consume them in a burst, while the next group of items might be flowing in. As the items are not consumed sequentially, a very efficient approach is to have a FIFO interface on the write side and a limited lookahead random access interface one on the read side. The read side works OK. The hard part turned out to be the FIFO full flag setting. I would like to use the full capacity of the FIFO and stall the data writer at the correct moment. Say I want to copy the content of a very big ROM into a 4-elements deep FIFO, the basic logic would be as follows:

writer: process(clock) is begin

if (rising_edge(clock)) then

fifo_write_request -1, "11" => +0).

And here comes the problem: simply setting fifo_full

Reply to
Piotr Wyderski
Loading thread data ...

Hello

On 22/04/2019 08:42, Piotr Wyderski wrote: [...]

Either you set the flag at the same time that the counter reaches its max value in a sequential process :

fifo_full 3 which takes care of the case where SIZE goes beyond 4 and is very simple in terms of logic because it only needs the most significant bit of SIZE.

BTW, note that in the expression above, fifo_full is of boolean type, not std_logic)

Nicolas

Reply to
Nicolas Matringe

It is deceptively simple, but unfortunately it doesn't work. This is a write-only (no dequeue ops) simulation for a 4-entry FIFO:

formatting link

All values are signals, i.e. the delay is included. It shows two bugs:

5 items have been accepted and no permanent stall is produced.

The combinatorial solution works, but for some unknown reason I am not particularly fond of it and wanted to consult it with experts here.

SIZE > 4 means the disaster has already happened.

Sure, I just wanted to show the general idea, not to introduce the otherwise required strong typing as an extra layer of obfuscation.

Best regards, Piotr

Reply to
Piotr Wyderski

You could generate an additional fifo_almost_full signal that is set when SIZE reaches 3 and use it like this, along with fifo_full and fifo_write_request :

... if (fifo_full = 0) and ((fifo_almost_full and fifo_write_request) =

0) then fifo_write_request Instead of comparing SIZE = 4, you could use SIZE > 3 which takes care

Inded but what about SIZE > 3, as I stated ? It gives you simple comparison logic and disaster mitigating (stalling whatever the value is once above the limit)

In general when designing these sorts of things I find it helps a huge lot to draw the timing waveforms by hand before starting to code.

Nicolas

Reply to
Nicolas Matringe

The usual procedure is to set full and empty inside a clocked process. I'm assuming that both read and write are clocked by a single clock. If read and write are in different clock domains then you need a dual clock fifo wh ich would go beyond the scope of what you're asking for here.

Normally you want FIFO flag outputs to be clocked since that will maximize the amount of time available for the external logic that will use those fla gs. If you use 'just logic' to generate the flags then you run the risk of that FIFO flag needlessly becoming part of the critical timing path. In o rder to set the full flag synchronously, you simply set it when there are ' n-1' things in the FIFO and there is a write request and no read request. VHDL sample code would be:

if (Reset = '1') then WrUsedw

Reply to
KJ

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.