有的时候,我们会遇到fifo深度不够用的时候,那么就会采用级联fifo,一般来说思路如下:
测试一:fifo为8bit*16
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity fifo_fifo is
Port (
clk : IN STD_LOGIC;
rst_n : IN STD_LOGIC
);
end fifo_fifo;
architecture Behavioral of fifo_fifo is
COMPONENT fifo_generator_0
PORT (
clk : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
full : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
valid : OUT STD_LOGIC
);
END COMPONENT;
signal fifo0_data_in : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo0_wr_en : STD_LOGIC;
signal fifo0_rd_en : STD_LOGIC;
signal fifo0_data_out : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo0_full : STD_LOGIC;
signal fifo0_empty : STD_LOGIC;
signal fifo0_valid : STD_LOGIC;
signal fifo1_rd_en : STD_LOGIC;
signal fifo1_data_out : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo1_full : STD_LOGIC;
signal fifo1_empty : STD_LOGIC;
signal fifo1_valid : STD_LOGIC;
signal cnt0 : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal cnt_2 : STD_LOGIC_VECTOR(1 DOWNTO 0);
type type_state1 is (s0,s1); --能量数据fifo使能
signal state: type_state1;
begin
fifo0_rd_en <= ((not fifo0_empty ) and (not fifo1_full ));
process(rst_n,clk,state,fifo0_full,fifo0_data_in,fifo1_empty,cnt0,cnt_2)
begin
if (rst_n = '0') then
fifo0_wr_en <= '0';
fifo0_data_in <= (others => '0');
cnt0 <= (others => '0');
fifo1_rd_en <= '0';
state <= s0;
cnt_2 <= (others => '0');
elsif (rising_edge(clk)) then
case state is
when s0 =>
fifo1_rd_en <= '0';
if(fifo0_full = '1') then
fifo0_wr_en <= '0';
fifo0_data_in <= (others => '0');
cnt0 <= (others => '0');
state <= s1;
else
fifo0_wr_en <= '1';
fifo0_data_in <= fifo0_data_in + '1';
cnt0 <= cnt0 + '1';
state <= s0;
end if;
when s1 =>
if(cnt_2 = "11") then
fifo1_rd_en <= not fifo1_empty;
cnt_2 <= (others => '0');
else
fifo1_rd_en <= '0';
cnt_2 <= cnt_2 + '1';
end if;
-- fifo1_rd_en <= not fifo1_empty;
state <= s1;
when others =>
state <= s0;
end case;
end if;
end process;
fifo0 : fifo_generator_0 --存放数据fifo0 32bit*131072
PORT MAP (
clk => clk,
din => fifo0_data_in,
wr_en => fifo0_wr_en,
rd_en => fifo0_rd_en,
dout => fifo0_data_out,
full => fifo0_full,
empty => fifo0_empty,
valid => fifo0_valid
);
fifo1 : fifo_generator_0 --存放数据fifo1
PORT MAP (
clk => clk,
din => fifo0_data_out,
wr_en => fifo0_valid,
rd_en => fifo1_rd_en,
dout => fifo1_data_out,
full => fifo1_full,
empty => fifo1_empty,
valid => fifo1_valid
);
end Behavioral;
结果就会在后面那个fifo满了之后产生错误,因为上一个fifo读出数据之后,要过一两个周期数据写进去,full菜户反应过来满了,但这段时间,上一个fifo任然在读,就导致了数据读出来了,但是后面那个fifo已经满脸,就算wr为1,也没用了,就会导致数据的丢失。
所以在fifo ip核当中,新加入almost_full信号,可以在真正满之前,就不再使能rd了,其实最后是写满了的,大家可以仔细对比一下仿真图:
代码只是把上面的fifo0_rd_en <= ((not fifo0_empty ) and (not fifo1_full ));换成fifo0_rd_en <= ((not fifo0_empty ) and (not fifo1_almost_full ));
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity fifo_fifo is
Port (
clk : IN STD_LOGIC;
rst_n : IN STD_LOGIC
);
end fifo_fifo;
architecture Behavioral of fifo_fifo is
COMPONENT fifo_generator_0
PORT (
clk : IN STD_LOGIC;
din : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
wr_en : IN STD_LOGIC;
rd_en : IN STD_LOGIC;
dout : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
full : OUT STD_LOGIC;
almost_full : OUT STD_LOGIC;
empty : OUT STD_LOGIC;
valid : OUT STD_LOGIC
);
END COMPONENT;
signal fifo0_data_in : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo0_wr_en : STD_LOGIC;
signal fifo0_rd_en : STD_LOGIC;
signal fifo0_data_out : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo0_full : STD_LOGIC;
signal fifo0_almost_full: STD_LOGIC;
signal fifo0_empty : STD_LOGIC;
signal fifo0_valid : STD_LOGIC;
signal fifo1_rd_en : STD_LOGIC;
signal fifo1_data_out : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal fifo1_full : STD_LOGIC;
signal fifo1_empty : STD_LOGIC;
signal fifo1_valid : STD_LOGIC;
signal fifo1_almost_full: STD_LOGIC;
signal cnt0 : STD_LOGIC_VECTOR(7 DOWNTO 0);
signal cnt_2 : STD_LOGIC_VECTOR(1 DOWNTO 0);
type type_state1 is (s0,s1); --能量数据fifo使能
signal state: type_state1;
begin
fifo0_rd_en <= ((not fifo0_empty ) and (not fifo1_almost_full ));
process(rst_n,clk,state,fifo0_full,fifo0_data_in,fifo1_empty,cnt0,cnt_2)
begin
if (rst_n = '0') then
fifo0_wr_en <= '0';
fifo0_data_in <= (others => '0');
cnt0 <= (others => '0');
fifo1_rd_en <= '0';
state <= s0;
cnt_2 <= (others => '0');
elsif (rising_edge(clk)) then
case state is
when s0 =>
fifo1_rd_en <= '0';
if(fifo0_full = '1') then
fifo0_wr_en <= '0';
fifo0_data_in <= (others => '0');
cnt0 <= (others => '0');
state <= s1;
else
fifo0_wr_en <= '1';
fifo0_data_in <= fifo0_data_in + '1';
cnt0 <= cnt0 + '1';
state <= s0;
end if;
when s1 =>
if(cnt_2 = "11") then
fifo1_rd_en <= not fifo1_empty;
cnt_2 <= (others => '0');
else
fifo1_rd_en <= '0';
cnt_2 <= cnt_2 + '1';
end if;
-- fifo1_rd_en <= not fifo1_empty;
state <= s1;
when others =>
state <= s0;
end case;
end if;
end process;
fifo0 : fifo_generator_0
PORT MAP (
clk => clk,
din => fifo0_data_in,
wr_en => fifo0_wr_en,
rd_en => fifo0_rd_en,
dout => fifo0_data_out,
full => fifo0_full,
almost_full => fifo0_almost_full,
empty => fifo0_empty,
valid => fifo0_valid
);
fifo1 : fifo_generator_0 --存放数据fifo1
PORT MAP (
clk => clk,
din => fifo0_data_out,
wr_en => fifo0_valid,
rd_en => fifo1_rd_en,
dout => fifo1_data_out,
full => fifo1_full,
almost_full => fifo1_almost_full,
empty => fifo1_empty,
valid => fifo1_valid
);
end Behavioral;