Binome
Full Member level 3
- Joined
- Nov 16, 2009
- Messages
- 152
- Helped
- 2
- Reputation
- 4
- Reaction score
- 2
- Trophy points
- 1,298
- Location
- Lyon, France
- Activity points
- 2,405
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ring_fifo is
generic(
fifo_length : integer:=8;
data_width : integer:=4);
port(
clk : in std_logic;
rst : in std_logic;
ren : in std_logic;
wen : in std_logic;
dataout : out std_logic_vector(data_width-1 downto 0);
datain : in std_logic_vector(data_width-1 downto 0);
empty : out std_logic;
err : out std_logic;
full : out std_logic);
end ring_fifo;
architecture arc of ring_fifo is
type memory_type is array (0 to fifo_length-1) of std_logic_vector(data_width-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
signal readptr,writeptr : integer range 0 to fifo_length-1 := 1;
signal rcycle,wcycle : std_logic := '0';
signal full0 : std_logic := '0';
signal empty0 : std_logic := '1';
begin
full <= full0;
empty <= empty0;
fifo0: process(clk,rst)
begin
if rst='1' then
readptr <= 0;
writeptr <= 0;
rcycle <= '0';
wcycle <= '0';
full0 <= '0';
empty0 <= '1';
err <= '0';
elsif rising_edge(clk) then
if (wen='1' and full0='0') then
memory(writeptr) <= datain ;
if (writeptr=fifo_length-1) then
wcycle <= not wcycle;
writeptr <= 0;
else
writeptr <= writeptr+1;
end if;
end if;
if (ren='1' and empty0='0') then
dataout <= memory(readptr);
if (readptr=fifo_length-1) then
rcycle <= not rcycle;
readptr <= 0;
else
readptr <= readptr+1;
end if;
end if ;
if ((writeptr + 1 = readptr)) or ((writeptr=fifo_length-1) and (readptr=0)) then
full0 <= '1';
else
full0 <= '0';
end if;
if (readptr = writeptr) then
empty0 <= '1';
else
empty0 <= '0';
end if;
if (empty0='1' and ren='1') or (full0='1' and wen='1') then
err <= '1';
else
err <= '0';
end if;
end if;
end process;
end arc;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ring_fifo is
generic(
fifo_length : integer:=8;
data_width : integer:=4);
port(
clk : in std_logic;
rst : in std_logic;
ren : in std_logic;
wen : in std_logic;
dataout : out std_logic_vector(data_width-1 downto 0);
datain : in std_logic_vector(data_width-1 downto 0);
empty : out std_logic;
err : out std_logic;
full : out std_logic);
end ring_fifo;
architecture arc of ring_fifo is
type memory_type is array (0 to fifo_length-1) of std_logic_vector(data_width-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
signal readptr,writeptr : integer range 0 to fifo_length-1 := 1;
signal rcycle,wcycle : std_logic := '0';
signal full0 : std_logic := '0';
signal empty0 : std_logic := '1';
begin
full <= full0;
empty <= empty0;
err <= '1' when (empty0='1' and ren='1') or (full0='1' and wen='1')
else '0';
fifo0: process(clk,rst)
begin
if rst='1' then
readptr <= 0;
writeptr <= 0;
full0 <= '0';
empty0 <= '1';
elsif rising_edge(clk) then
if wen='1' and not(writeptr=readptr and wcycle/=rcycle) then
memory(writeptr) <= datain ;
if (writeptr=fifo_length-1) then
writeptr <= 0;
wcycle <= not wcycle;
else
writeptr <= writeptr+1;
end if;
end if;
if (ren='1' and not(readptr=writeptr and rcycle=wcycle)) then
dataout <= memory(readptr);
if (readptr=fifo_length-1) then
readptr <= 0;
rcycle <= not rcycle;
else
readptr <= readptr+1;
end if;
end if ;
if ((writeptr + 1 = readptr)) or ((writeptr=fifo_length-1) and (readptr=0)) then
full0 <= '1';
else
full0 <= '0';
end if;
if (readptr=writeptr and wcycle=rcycle) then
empty0 <= '1';
else
empty0 <= '0';
end if;
end if;
end process;
end arc;
- The signals rcycle and wcycle serve no useful purpose.I do have a testbench and this component seems to behave pretty well. Do you see some evident errors?
I don't understand what could happen/why there's a problem/how to correct it.The problem comes because full and empty lag the write/read requests by 1 clock cycle. So they will not prevent overrun or underrun if you use them direcly.
Yes, the simulation shows me that. But why?With your new code you can never read and write at the same time. Also, the initial setup requires a read before you can do a write.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ring_fifo is
generic(
fifo_length : integer:=8;
data_width : integer:=4);
port(
clk : in std_logic;
rst : in std_logic;
ren : in std_logic;
wen : in std_logic;
dataout : out std_logic_vector(data_width-1 downto 0);
datain : in std_logic_vector(data_width-1 downto 0);
empty : out std_logic;
err : out std_logic;
full : out std_logic);
end ring_fifo;
architecture arc of ring_fifo is
type memory_type is array (0 to fifo_length-1) of std_logic_vector(data_width-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
signal readptr,writeptr : integer range 0 to fifo_length-1 := 1;
signal rcycle,wcycle : std_logic := '0';
signal full0 : std_logic := '0';
signal empty0 : std_logic := '1';
begin
full <= full0;
empty <= empty0;
err <= '1' when (empty0='1' and ren='1') or (full0='1' and wen='1')
else '0';
fifo0: process(clk,rst)
begin
if rst='1' then
readptr <= 0;
writeptr <= 0;
full0 <= '0';
empty0 <= '1';
rcycle <= '0';
wcycle <= '0';
elsif rising_edge(clk) then
if wen='1' and not(writeptr=readptr and wcycle/=rcycle) then
memory(writeptr) <= datain ;
if (writeptr=fifo_length-1) then
writeptr <= 0;
wcycle <= not wcycle;
else
writeptr <= writeptr+1;
end if;
end if;
if (ren='1' and not(readptr=writeptr and rcycle=wcycle)) then
dataout <= memory(readptr);
if (readptr=fifo_length-1) then
readptr <= 0;
rcycle <= not rcycle;
else
readptr <= readptr+1;
end if;
end if ;
if (writeptr+1=readptr and wcycle/=rcycle) or (writeptr=fifo_length-1 and readptr=0 and wcycle=rcycle) then
full0 <= '1';
else
full0 <= '0';
end if;
if (readptr=writeptr and wcycle=rcycle) then
empty0 <= '1';
else
empty0 <= '0';
end if;
end if;
end process;
end arc;
If there is a one cycle lag, then it is because you haven't generated the full flag to occur on the proper clock cycle. On the clock cycle immediately after the fifo write that causes the fifo to become full, you must set full to 1 otherwise your fifo will not work correctly. Similarly, on the clock cycle immediately after the fifo read that causes the fifo to become empty, you must set empty to 1 otherwise your fifo will not work correctly.@K-J
When writing I'm using "if wen and $the conditions for not full$" and not "if wen and not full" because there would be a 1-cycle lag I don't want.
See my previous post. The 'if' statement that inhibits writing (reading) when full (empty) must be how I wrote it otherwise you will have a condition that does not work because your conditions for inhibiting the read or write do not agree with the fifo status of full and empty.What should I do?
I don't understand what could happen/why there's a problem/how to correct it.
Yes, the simulation shows me that. But why?
And I don't understand the initialization problem.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ring_fifo is
generic(
fifo_length : integer:=8;
data_width : integer:=4);
port(
clk : in std_logic;
rst : in std_logic;
ren : in std_logic;
wen : in std_logic;
dataout : out std_logic_vector(data_width-1 downto 0);
datain : in std_logic_vector(data_width-1 downto 0);
empty : out std_logic;
err : out std_logic;
full : out std_logic);
end ring_fifo;
architecture arc of ring_fifo is
type memory_type is array (0 to fifo_length-1) of std_logic_vector(data_width-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
signal readptr,writeptr : integer range 0 to fifo_length-1 := 1;
signal rcycle,wcycle : std_logic := '0';
signal full0 : std_logic := '0';
signal empty0 : std_logic := '1';
begin
full <= full0;
empty <= empty0;
err <= '1' when (empty0='1' and ren='1') or (full0='1' and wen='1')
else '0';
fifo0: process(clk,rst)
begin
if rst='1' then
memory <= (others => (others => '0'));
readptr <= 0;
writeptr <= 0;
full0 <= '0';
empty0 <= '1';
rcycle <= '0';
wcycle <= '0';
elsif rising_edge(clk) then
if (wen='1' and full0='0') then
memory(writeptr) <= datain ;
if (writeptr=fifo_length-1) then
writeptr <= 0;
wcycle <= not wcycle;
else
writeptr <= writeptr+1;
end if;
end if;
if (ren='1' and empty0='0') then
dataout <= memory(readptr);
if (readptr=fifo_length-1) then
readptr <= 0;
rcycle <= not rcycle;
else
readptr <= readptr+1;
end if;
end if ;
if (writeptr+1=readptr and wcycle/=rcycle) or (writeptr=fifo_length-1 and readptr=0 and wcycle=rcycle) then
full0 <= '1';
else
full0 <= '0';
end if;
if (readptr=writeptr and wcycle=rcycle) then
empty0 <= '1';
else
empty0 <= '0';
end if;
end if;
end process;
end arc;
if wren and (not rden) and wraddr = (rd_addr-1) then
full <= '1';
end if;
Tricky, more likely a school assignment given to students that only know software and barely understand what a gate is.I assume this is some personal project, because altera and xilinx already provide fifo IPs for free.
Binome, You're problem isn't with the understanding VHDL it's with understanding the architecture of a FIFO. If you don't really understand how a FIFO has to function then you're going to end up writing a FIFO that doesn't work (like yours).Sorry but I still don't understand.
wcycle and rcycle are tested to assert full0 and empty0 and you tell me they're not required. Why?
And you tell I can read and write in the same cycle, not before. Explain the difference. You didn't tell me why the precedent version was wrong.
I thought I could easily understand VHDL but it seems I'm not! Explain the differences in the language I don't see.
That's too bad, because it looks like you're probably pretty close. It appears to me if you just delete the signals wcycle and rcycle (and all places where they are used) from your code and do nothing else, that your fifo might actually work. So where you go to use it like this...OK, I'll think about the functions.
rcycle and wcycle were meant to implement a cyclic fifo (aka ring buffer) but if it is so difficult to implement, I'll use altera's dual port fifo to do it.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity ring_fifo is
generic(
fifo_length : integer:=8;
data_width : integer:=4);
port(
clk : in std_logic;
rst : in std_logic;
ren : in std_logic;
wen : in std_logic;
dataout : out std_logic_vector(data_width-1 downto 0);
datain : in std_logic_vector(data_width-1 downto 0);
empty : out std_logic;
err : out std_logic;
full : out std_logic);
end ring_fifo;
architecture arc of ring_fifo is
type memory_type is array (0 to fifo_length-1) of std_logic_vector(data_width-1 downto 0);
signal memory : memory_type := (others => (others => '0'));
signal readptr,writeptr : integer range 0 to fifo_length-1 := 1;
signal full0 : std_logic := '0';
signal empty0 : std_logic := '1';
begin
full <= full0;
empty <= empty0;
err <= '1' when (empty0='1' and ren='1') or (full0='1' and wen='1')
else '0';
fifo0: process(clk,rst)
begin
if rst='1' then
memory <= (others => (others => '0'));
readptr <= 0;
writeptr <= 0;
full0 <= '0';
empty0 <= '1';
elsif rising_edge(clk) then
if (wen='1' and full0='0') then
memory(writeptr) <= datain ;
if (writeptr=fifo_length-1) then
writeptr <= 0;
else
writeptr <= writeptr+1;
end if;
end if;
if (ren='1' and empty0='0') then
dataout <= memory(readptr);
if (readptr=fifo_length-1) then
readptr <= 0;
else
readptr <= readptr+1;
end if;
end if ;
if (writeptr+1=readptr) or (writeptr=fifo_length-1 and readptr=0) then
full0 <= '1';
else
full0 <= '0';
end if;
if (readptr=writeptr) then
empty0 <= '1';
else
empty0 <= '0';
end if;
end if;
end process;
end arc;
full0<= '1' when (writeptr+1=readptr) or (writeptr=fifo_length-1 and readptr=0)
else '0';
empty0<='1' when (readptr=writeptr)
else '0';
I don't see any paper in your post. Did you forget it or didn't I search in the right place?
It's too bad because I'd like to read about that.
if wren and (not rden) and wraddr = (rd_addr-1) then
full <= '1';
end if;
howfull <= wr_addr - rd_addr;
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?