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)与系统设计》课程