signal write_pointer , read_pointer : unsigned ( a downto 0 ) ;
signal write_address , read_address : unsigned ( a - 1 downto 0 ) ;
signal almost_full_threshold , almost_empty_threshold : unsigned ( a - 1 downto 0 ) ;
signal almost_full , full , almost_empty , empty : std_logic ;
signal msb_equal , pointer_equal : std_logic ;
pointer_equal <= '1' when write_pointer = read_pointer else '0' ;
almost_full <= '1' when empty = '0' and read_address - write_address <= almost_full_threshold else '0' ;
full <= '1' when address_equal = '1' and pointer_equal = '0' else '0' ;
almost_empty <= '1' when full = '0' and write_address - read_address <= almost_empty_threshold else '0' ;
empty <= '1' when pointer_equal = '1' else '0' ;
writing : process ( clock , reset ) is
begin
if reset = '1' then
write_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if write_request = '1' and full = '0' then
write_pointer <= write_pointer + 1 ;
end if ;
end if ;
end process writing ;
reading : process ( clock , reset ) is
begin
if reset = '1' then
read_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if read_request = '1' and empty = '0' then
read_pointer <= read_pointer + 1 ;
end if ;
end if ;
end process reading ;
I would change the flag generation logic so that it is synchronized to the clock. Having the output status flags be combinatorial outputs that depend on every bit of both pointers as you have it will lead to a lower clock cycle performance in a system.Would you change anything in the code ( while still maintaining the extra bit concept ) ?
Can you please give an example in code...I would change the flag generation logic so that it is synchronized to the clock
Can you please give an example in code...
You mean, use the "lookahead" address method here too?You "right" way in #73.
std_match,
But in post #73 the "Full" and "Empty" flag are asserted with direct dependency on Read/Write requests.
With the "extra bit method", flags aren't generated by the Write and Read requests directly - but as a comparation result of the pointers.
How can I use the lookhead method then?
That's correct. The advantage is that the long combinatorial logic path created by checking to see if "(W-R)=1" feeds into the flip flop that creates the full flag. As you have it written, the 'likely just as long' combinatorial path checking to see if "W=R" does not have that flip flop so the prop delay to 'Full' would be quite a bit longer.K-J,
I understand.
But it will require evaluating the "(W-R)=1" condition under the read request. Correct?
I didn't say it was only affected by read request. Here is an outline of what I was saying:I'm trying to get to my point...
If the condition gets evaluated only under a read request then only a read request can update it and this isn't optimal - because writing to memory should also be able to effect the empty flags.
if (read_request = '1') then
Full <= '0';
elsif (write_request = '1') then
if ((read_pointer-write_pointer) = 1) then -- Think I said it backwards in previous post...should be (R-W, not W-R)
Full <= '1'
end if;
end if;
-- Do something similar to generate 'Empty' except there you will be looking for "if ((write_pointer-read_pointer) = 1) then"
There is nothing inherently unreliable about the synchronizing...not sure what you meanHence, we'll have to evaluate the W-R=1 condition under write requests also. Of course this isn't a problem with synchronous clock domains - but what about asynchronous FIFOs? If I use the same concept, I'll have to synchronize the requests between domains which may prove unreliable.
Unfortunately, it's quite a bit worse than just 'slow'. The write pointer will be synchronized with the write clock; the read pointer will be synchronized with the read clock. Any calculations you do between those two pointers will not be synchronized to any clock, they will be completely useless to anyone outside of a simulation environmentI want to design my FIFO in such a way that the flag generation will depend only on the value of the pointers and won't require the conditions to be evaluated under either write or read requests.
My asynchronous example does just that - but it we'll be slow.
Maybe Google for the source code to lpm_fifo_dc and see how they do it.How would you suggest improving it without departing from the extra address bit method ?
Sure, I know that. That's what I meant in post #81 when I said "with adjustments".Regardless of which implementation #73 or #81 neither will work as an asynchronous FIFO. Given that you want to support asynchronous operation you will have to gray code and synchronize the addresses across the clock domains.
If one clock domain is much faster then another, requests synchronization from the fast domain to the slow may fail.There is nothing inherently unreliable about the synchronizing...not sure what you mean
Yeah look at the link in #94.Do you know a way to design a reliable asynchronous FIFO without having to synchronize requests between domains?
If that is the way you do it, then yes you would have issues...but that is not the way to do it. Peruse the examples of good designs that have stood the test of time like the Cummings paper or lpm_fifo_dc. You're intentionally trying to re-invent the wheel on this and a dual clock fifo has many potential pitfalls. You would be better off studying working designs rather than asking people to review what you've written for one purpose (single clock fifo) and then think that it should be applicable to something much more complex (dual clock fifo). I realize you're trying to come up with your own code, but that does not imply that you can't learn from actual working designs.If one clock domain is much faster then another, requests synchronization from the fast domain to the slow may fail.
assign rbinnext = rbin + (rinc & ~rempty);
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?