VHDL實現FIFO

FIFO

FIFO緩衝器經常使用在很多設計中,成爲連接具有相同或者不同時鐘的子系統的橋樑,來達到臨時訪問的要求。
下面的代碼實現的是深度8字,寬度9bits的的FIFO,包含組合和同步邏輯設計。

代碼

------------------------------------------------------------------------------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity fifo89 is
    Port (     	
    	clk : in std_logic;
        rst : in std_logic;
        rd : in std_logic;
        wr : in std_logic;
        rdinc : in std_logic;
        wrinc : in std_logic;
        rdptrclr : in std_logic;
        wrptrclr : in std_logic;
        data_in : in std_logic_vector(8 downto 0);
        data_out : out std_logic_vector(8 downto 0));
end fifo89;

-- clk: used to synchronize the buffers;
-- rst: reset the buffers
-- rd: when valid, the output buffers are enabled;
-- wr: when valid, write register with 9-bit width is permitted; 
-- rdinc: read counter enabled;
-- wrinc: write counter enabled;
-- rdptrclr: reset read counter, pointing to the first register for
-- read purpose;
-- wrptrclr: reset write counter, pointing to the first register for
-- write purpose;
-- data_in: data inputs with 9-bit width to the FIFOs;
-- data_out: data outputs with 9-bit width from the FIFOs.

architecture Behavioral of fifo89 is
	type fifo_array is array(7 downto 0) of std_logic_vector(8 downto 0);
	signal fifo: fifo_array;
	signal wrptr, rdptr: std_logic_vector(2 downto 0);
	signal en: std_logic_vector( 7 downto 0);
	signal dmuxout: std_logic_vector(8 downto 0);

begin
	
-- fifo register_array:
reg_array: process (rst, clk)
	begin
		if rst = '1' then
			for i in 7 downto 0 loop
				fifo(i) <= (others => '0'); -- aggregate
			end loop;
		elsif (clk'event and clk = '1') then
			if wr = '1' then
				for i in 7 downto 0 loop
					if en(i) = '1' then
						fifo(i) <= data_in;
					else
						fifo(i) <= fifo(i);
					end if;
				end loop;
			end if;
		end if;
	end process;

-- read pointer
read_count: process (rst, clk)
	begin
		if rst = '1' then
			rdptr <= (others => '0');
		elsif (clk'event and clk = '1') then
			if rdptrclr = '1' then
				rdptr <= (others => '0');
			elsif rdinc = '1' then
				rdptr <= rdptr + 1;
			end if;
		end if;
	end process;

-- write pointer
write_count: process (rst, clk)
	begin
		if rst = '1' then
			wrptr <= (others => '0');
		elsif (clk'event and clk = '1') then
			if wrptrclr = '1' then
				wrptr <= (others => '0');
			elsif wrinc = '1' then
				wrptr <= wrptr + 1;
			end if;
		end if;
	end process;

-- 8:1 output data mux
with rdptr select
	dmuxout <=    fifo(0) when "000",
				  fifo(1) when "001",
				  fifo(2) when "010",
				  fifo(3) when "011",
				  fifo(4) when "100",
				  fifo(5) when "101",
				  fifo(6) when "110",
				  fifo(7) when others;

-- FIFO register selector decoder
with wrptr select
	en <=   "00000001" when "000",
			"00000010" when "001",
			"00000100" when "010",
			"00001000" when "011",
			"00010000" when "100",
			"00100000" when "101",
			"01000000" when "110",
			"10000000" when others;

-- three-state control of outputs
three_state: process (rd, dmuxout)
	begin
		if rd = '1' then
			data_out <= dmuxout;
		else
			data_out <= (others => 'Z');
		end if;
	end process;

end Behavioral;

測試代碼

---------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx leaf cells in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity fifo89_tb is
--  Port ( );
end fifo89_tb;

architecture Behavioral of fifo89_tb is
-- Component Declaration for the Unit Under Test (UUT)	
component fifo89
	port(
    	clk     : in std_logic;
        rst     : in std_logic;
        rd      : in std_logic;
        wr      : in std_logic;
        rdinc   : in std_logic;
        wrinc   : in std_logic;
        rdptrclr: in std_logic;
        wrptrclr: in std_logic;
        data_in : in std_logic_vector(8 downto 0);
        data_out: out std_logic_vector(8 downto 0)		
	);
end component;
	
-- Input	
	signal clk     : std_logic       := '0';
	signal rst     : std_logic       := '0';
	signal rd      : std_logic       := '0';
	signal wr      : std_logic       := '0';
	signal rdinc   : std_logic       := '0';
	signal wrinc   : std_logic       := '0';
	signal rdptrclr: std_logic       := '0';
	signal wrptrclr: std_logic       := '0';
	signal data_in : std_logic_vector(8 downto 0):= (others =>'0');
		
-- Output
    signal data_out: std_logic_vector(8 downto 0);
    	
begin    	
-- Instantiate the Unit Under Test(UUT)
   uut: fifo89 port map(
   	clk      => clk,
   	rst      => rst,
   	rd       => rd,
   	wr       => wr,
   	rdinc    => rdinc,
   	wrinc    => wrinc,
   	rdptrclr => rdptrclr,
   	wrptrclr => wrptrclr,
   	data_in  => data_in,
   	data_out => data_out
   );

-- clk   
   clk_proc: process
   begin
   	clk <= '1';
   	wait for 10 ns;
   	clk <= '0';
   	wait for 10 ns;
   end process;
   
-- Simulus process
    stim_proc: process
    begin
    	rst      <= '1';
   	rd       <= '0';
   	wr       <= '0';
   	rdinc    <= '0';
   	wrinc    <= '0';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= (others => '0');	
   	wait for 100 ns;
   	-- 寫數據16'h1
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000000001";	
   	wait for 20 ns;
   	--寫數據16'h2
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000000010";	
   	wait for 20 ns; 
   	--寫數據16'h4
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000000100";	
   	wait for 20 ns;   
   	--寫數據16'h8
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000001000";
   	wait for 20 ns; 
   	--寫數據16'h16
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000010000";
   	wait for 20 ns; 
   	--寫數據16'h32
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000100000";	   		
   	wait for 20 ns; 
   	--寫數據16'h64
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "001000000";	   		
   	wait for 20 ns; 
   	--寫數據16'h128
    	rst      <= '0';
   	rd       <= '0';
   	wr       <= '1';
   	rdinc    <= '0';
   	wrinc    <= '1';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "010000000";	   		
   	wait for 20 ns;
   	--讀數據
    	rst      <= '0';
   	rd       <= '1';
   	wr       <= '0';
   	rdinc    <= '1';
   	wrinc    <= '0';
   	rdptrclr <= '0';
   	wrptrclr <= '0';
   	data_in  <= "000000000";	   		
   	wait for 200 ns;     	   	 	   	
    end process;
end;

綜合結果

在這裏插入圖片描述

行爲仿真結果

在這裏插入圖片描述

致謝

來自中國科學院大學段成華老師的《超大規模集成電路(VLSI)與系統設計》課程

發佈了30 篇原創文章 · 獲贊 62 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章