fpga 级联fifo(VHDL)

有的时候,我们会遇到fifo深度不够用的时候,那么就会采用级联fifo,一般来说思路如下:

fpga 级联fifo(VHDL)_第1张图片

 测试一: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,也没用了,就会导致数据的丢失。

fpga 级联fifo(VHDL)_第2张图片

所以在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;

fpga 级联fifo(VHDL)_第3张图片

 

 fpga 级联fifo(VHDL)_第4张图片

 

你可能感兴趣的:(FPGA,VHDL,VIVADO,xilinx,fpga,ip核使用例程(VHDL),fpga开发)