P
Piotr Wyderski
Guest
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 <= '0';
if (fifo_full = '0') then
fifo_write_request <= '1';
rom_address <= rom_address + 1;
end if;
end if;
end process;
In the FIFO interface part I have a 3-bit counter SIZE that calculates
the number of items in the FIFO. I update it under the same "if
(rising_edge(clock))" condition to follow the instantaneous
fifo_write_request & fifo_read_request constellation ("00" => +0, "10"
=> +1, "01" => -1, "11" => +0).
And here comes the problem: simply setting fifo_full <= (SIZE = 4)
adds a cycle of latency and the writer thinks it is allowed to write one
more item, corrupting the data. To add insult to injury, SIZE becomes 5
and fifo_full is de-aserted, so the writer pumps in even more data.
Changing it to fifo_full <= (SIZE = 3) behaves equally wrong, just moves
the problem one cycle to the left.
If I move the following into the concurrent part:
fifo_full <= (SIZE = 4) or ((SIZE = 3) and (fifo_write_request = '1'))
(to account for a possible ongoing write), everything works great,
because the condition is very logical (no pun intended). But I think
this solution is lame due to its purely combinatorial nature. So, could
you please tell me either:
a) that it is not lame, if it works, it works and and my concerns are
based on a superstition.
b) or the correct way to setup the flag synchronously.
I don't care if the read side starts as soon as possible (including the
ongoing write) or one cycle later, so it can be excluded from the
write-side logic. This is to drive a string of WS2812 LEDs.
Best regards, Piotr
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 <= '0';
if (fifo_full = '0') then
fifo_write_request <= '1';
rom_address <= rom_address + 1;
end if;
end if;
end process;
In the FIFO interface part I have a 3-bit counter SIZE that calculates
the number of items in the FIFO. I update it under the same "if
(rising_edge(clock))" condition to follow the instantaneous
fifo_write_request & fifo_read_request constellation ("00" => +0, "10"
=> +1, "01" => -1, "11" => +0).
And here comes the problem: simply setting fifo_full <= (SIZE = 4)
adds a cycle of latency and the writer thinks it is allowed to write one
more item, corrupting the data. To add insult to injury, SIZE becomes 5
and fifo_full is de-aserted, so the writer pumps in even more data.
Changing it to fifo_full <= (SIZE = 3) behaves equally wrong, just moves
the problem one cycle to the left.
If I move the following into the concurrent part:
fifo_full <= (SIZE = 4) or ((SIZE = 3) and (fifo_write_request = '1'))
(to account for a possible ongoing write), everything works great,
because the condition is very logical (no pun intended). But I think
this solution is lame due to its purely combinatorial nature. So, could
you please tell me either:
a) that it is not lame, if it works, it works and and my concerns are
based on a superstition.
b) or the correct way to setup the flag synchronously.
I don't care if the read side starts as soon as possible (including the
ongoing write) or one cycle later, so it can be excluded from the
write-side logic. This is to drive a string of WS2812 LEDs.
Best regards, Piotr