shaiko
Advanced Member level 5
- Joined
- Aug 20, 2011
- Messages
- 2,644
- Helped
- 303
- Reputation
- 608
- Reaction score
- 297
- Trophy points
- 1,363
- Activity points
- 18,302
signal full , empty : std_logic ;
signal write_address , read_addres : unsigned ( 2 downto 0 ) ;
signal write_pointer , read_pointer : unsigned ( 3 downto 0 ) ;
write_address <= write_pointer ( 2 downto 0 ) ;
read_address <= read_pointer ( 2 downto 0 ) ;
if write_pointer ( 2 downto 0 ) = read_pointer ( 2 downto 0 ) then
if ( write_pointer ( 3 ) = read_pointer ( 3 ) ) then
full <= '0' ;
empty <= '1' ;
else
full < = '1' ;
empty < = '0' ;
end if ;
end if ;
-- The red equations are evaluated only under the read or write operations.
-- The logic "knows" the state it was at prior to the read or write operation - therefore it can assert the correct flag afterwards...
if rising_edge ( clock ) then
if read_operation = '1' and empty = '0' then
read_address <= read_address + 1 ;
full <= '0' ;
if [COLOR="#FF0000"]write_address - read_address = 1[/COLOR] then
empty <= '1' ;
end if ;
end if ;
if write_operation = '1' and full = '0' then
write_address <= write_address + 1 ;
empty <= '1' ;
if [COLOR="#FF0000"]read_address - write_address = 1[/COLOR] then
full <= '1' ;
end if ;
end if ;
end if ;
diff <= write_addr - read_addr;
if diff = 0 and empty and write then
empty <= '0';
elsif diff = 1 and read = 1 and write = 0 then
empty <= '1';
end if;
if diff = 0 and full and read then
full <= '0';
elsif diff = -1 and read = 0 and write = 1 then
full <= '1';
end if;
Why?? the leftmost bit doesn't "participate" in actual addressing...1. This option flags the fifo as full when only half the addresses are used.
Please post an example in code...You must increment the pointers in parallel and use those values together with the current values to decide if the full or empty flags should be set.
What do you mean by "waste one word" ?It is common to waste one word, so the pointers are only equal when the FIFO is empty.
What do you mean by "waste one word" ?
The only "waste" I see is the extra leftmost bit of both pointer...
Do you agree with my reply (post #3)?This option flags the fifo as full when only half the addresses are used.
Please show an example in code.You must increment the pointers in parallel and use those values together with the current values to decide if the full or empty flags should be set.
diff <= write_addr - read_addr;
if diff = 0 and empty and write then
empty <= '0';
elsif diff = 1 and read = 1 and write = 0 then
empty <= '1';
end if;
if diff = 0 and full and read then
full <= '0';
elsif [COLOR="#FF0000"]diff = -1[/COLOR] and read = 0 and write = 1 then
full <= '1';
end if;
It is an alternative to an extra address bit in the pointers.What do you mean by "waste one word" ?
Very clear now.It is an alternative to an extra address bit in the pointers.
If the full flag is set when there is still one unused word in the FIFO, the read and write pointers can only be equal when the FIFO is empty. The trick with the extra address bit is not needed in that case.
Please explain why not?You want to update the empty/full flags at the same time you update the pointer(s). This means that you can not test for equality in the lower bits of the pointers.
I don't quite understand what you mean. Please post a code example...it will help a lot!You must increment the pointers in parallel and use those values together with the current values to decide if the full or empty flags should be set.
write_flags_and_queue : process ( clock , reset ) is
begin
if reset = '1' then -- Asynchronous reset.
full <= '0' ;
write_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if write_request = '1' and full = '0' then
write_pointer <= write_pointer + 1 ;
end if ;
if
( write_pointer ( write_pointer ' high - 1 downto 0 ) =
read_pointer ( read_pointer ' high - 1 downto 0 ) ) and
( write_pointer ' high /= read_pointer ' high ) then
full < = '1' ;
else
full < = '0' ;
end if ;
end if ;
end process write_flags_and_queue ;
read_flags_and_queue : process ( clock , reset ) is
begin
if reset = '1' then
empty <= '1' ;
read_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if read_request = '1' and empty = '0' then
read_pointer <= read_pointer + 1 ;
end if ;
if write_pointer = read_pointer then
empty <= '1' ;
else
empty <= '0' ;
end if ;
end if ;
end process read_flags_and_queue ;
clk write p full
0 110 0
1 111 0 --fifo not currently full, so write pointer can increment
2 000 1
3 000 0 --full flips here as full condition no longer met
Code VHDL - [expand] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 signal write_pointer, read_pointer, write_request, read_request; variable new_write_pointer; -- write process if reset = '1' then full <= '0' ; write_pointer <= ( others => '0' ) ; elsif rising_edge(clock) then new_write_pointer := write_pointer + 1; if write_request = '1' and full = '0' then write_pointer <= new_write_pointer; if new_write_pointer = read_pointer then full <= '1'; end if; end if; if read_request = '1' then full <= '0'; end if; end if;
if
( write_pointer ( write_pointer ' high - 1 downto 0 ) =
read_pointer ( read_pointer ' high - 1 downto 0 ) ) and
( write_pointer ' high /= read_pointer ' high ) then
full < = '1' ;
else
full < = '0' ;
write_pointer_next <= write_pointer + 1 ;
write_flags_and_queue : process ( clock , reset ) is
begin
if reset = '1' then -- Asynchronous reset.
full <= '0' ;
write_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if write_request = '1' and full = '0' then
write_pointer <= write_pointer + 1 ;
end if ;
if
( write_pointer_next ( write_pointer_next ' high - 1 downto 0 ) =
read_pointer ( read_pointer ' high - 1 downto 0 ) ) and
( write_pointer_next ' high /= read_pointer ' high ) then
full < = '1' ;
else
full < = '0' ;
end if ;
end process write_flags_and_queue ;
read_pointer_next <= read_pointer + 1 ;
read_flags_and_queue : process ( clock , reset ) is
begin
if reset = '1' then -- Asynchronous reset.
empty < = '0' ;
read_pointer <= ( others => '0' ) ;
elsif rising_edge ( clock ) then
if read_request = '1' and empty = '0' then
read_pointer <= read_pointer + 1 ;
end if ;
if read_pointer_next = write_pointer then
empty < = '1' ;
else
empty < = '0' ;
end if ;
end if ;
end process read_flags_and_queue ;
I assume you mean that I wrote:To help the synthesis tool, you should use the incremented signal write_pointer_next when you assign the incremented value to the pointer. Maybe a good synthesis tool can merge the identical additions, but why take any risk when it is so easy to write "safer" code.
write_pointer <= write_pointer + 1 ;
write_pointer <= write_pointer_next ;
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?