VHDL描述用LE搭建的小型FIFO
所谓FIFO,从硬件的观点来看,就是一块数据内存。它有两个端口,一个用来写数据,就是将数据存入FIFO;另一个用来读数据,也就是将数据从FIFO当中取出。与FIFO操作相关的有两个指针,写指针指向要写的内存部分,读指针指向要读的内存部分。FIFO控制器通过外部的读写信号控制这两个指针移动,并由此产生FIFO空信号或满信号。
用FPGA实现FIFO的话,一般而言,都是采用片内的双端口RAM作为FIFO的内存的实现形式。但是如果需要设计的FIFO深度和宽度不是很大,或者要在CPLD(没有内部RAM)实现简单的FIFO的话,就需要用LE来搭建了。
下面给出VHDL语言描述的时钟同步FIFO的程序,如果需要异步的话,可以在本程序的基础上简单修改一下就OK了,本程序已经经过本人仿真通过,不过EMPTY和FULL有可能会有点毛刺,(如果要用的话,记得消除毛刺哦,同步设计的话,不消也行),本人仿真器件选择EPM570,大概消耗140多个LE。
还里需要说明一下:sync_ffs : process这个process是为了产生Rdpulse, Wrpulse这两个单周期的读写请求脉冲信号,读数据输出是在读请求信号RDREQ有效后的2~3个周期才算有效的,写请求也是这样,这一点仿真或使用的时候要格外注意!!!
--a first-in first out memory, uses a synchronising clock
--generics allow fifos of different sizes to be instantiated
library IEEE;
use IEEE.Std_logic_1164.all;
entity FIFO94179411 is
generic(m : Positive := 5;
n : Positive := 8); --m is fifo depth, n is fifo width
port(RESET, WRREQ, RDREQ, CLOCK : in Std_logic;
DATAIN : in Std_logic_vector((n-1) downto 0);
DATAOUT : out Std_logic_vector((n-1) downto 0);
FULL, EMPTY : buffer Std_logic);
end FIFO94179411;
architecture A of FIFO94179411 is
type Fifo_array is array(0 to (m-1)) of Bit_vector((n-1) downto 0);
signal Fifo_memory : Fifo_array;
signal Wraddr, Rdaddr, Offset : Natural range 0 to (m-1);
signal Rdpulse, Wrpulse, Q1, Q2, Q3, Q4 : Std_logic;
signal Databuffer : Bit_vector((n-1) downto 0);
begin
--pulse synchronisers for WRREQ and RDREQ
--modified for Synplify to a process
sync_ffs : process
begin
wait until rising_edge(CLOCK);
Q1 <= WRREQ;
Q2 <= Q1;
Q3 <= RDREQ;
Q4 <= Q3;
end process;
--concurrent logic to generate pulses
Wrpulse <= Q2 and not(Q1);
Rdpulse <= Q4 and not(Q3);
Fifo_read : process
begin
wait until rising_edge(CLOCK);
if RESET = '1' then
Rdaddr <= 0;
Databuffer <= (others => '0');
elsif (Rdpulse = '1' and EMPTY = '0') then
Databuffer <= Fifo_memory(Rdaddr);
Rdaddr <= (Rdaddr + 1) mod m;
end if;
end process;
Fifo_write : process
begin
wait until rising_edge(CLOCK);
if RESET = '1' then
Wraddr <= 0;
elsif (Wrpulse = '1' and FULL = '0') then
Fifo_memory(Wraddr) <= To_Bitvector(DATAIN);
Wraddr <= (Wraddr + 1) mod m;
end if;
end process;
Offset <= (Wraddr - Rdaddr) when (Wraddr > Rdaddr)
else (m - (Rdaddr - Wraddr)) when (Rdaddr > Wraddr)
else 0;
EMPTY <= '1' when (Offset = 0) else '0';
FULL <= '1' when (Offset = (m-1)) else '0';
DATAOUT <= To_Stdlogicvector(Databuffer) when RDREQ = '0'
else (others => 'Z');
end A;
--generics allow fifos of different sizes to be instantiated
library IEEE;
use IEEE.Std_logic_1164.all;
entity FIFO94179411 is
generic(m : Positive := 5;
n : Positive := 8); --m is fifo depth, n is fifo width
port(RESET, WRREQ, RDREQ, CLOCK : in Std_logic;
DATAIN : in Std_logic_vector((n-1) downto 0);
DATAOUT : out Std_logic_vector((n-1) downto 0);
FULL, EMPTY : buffer Std_logic);
end FIFO94179411;
architecture A of FIFO94179411 is
type Fifo_array is array(0 to (m-1)) of Bit_vector((n-1) downto 0);
signal Fifo_memory : Fifo_array;
signal Wraddr, Rdaddr, Offset : Natural range 0 to (m-1);
signal Rdpulse, Wrpulse, Q1, Q2, Q3, Q4 : Std_logic;
signal Databuffer : Bit_vector((n-1) downto 0);
begin
--pulse synchronisers for WRREQ and RDREQ
--modified for Synplify to a process
sync_ffs : process
begin
wait until rising_edge(CLOCK);
Q1 <= WRREQ;
Q2 <= Q1;
Q3 <= RDREQ;
Q4 <= Q3;
end process;
--concurrent logic to generate pulses
Wrpulse <= Q2 and not(Q1);
Rdpulse <= Q4 and not(Q3);
Fifo_read : process
begin
wait until rising_edge(CLOCK);
if RESET = '1' then
Rdaddr <= 0;
Databuffer <= (others => '0');
elsif (Rdpulse = '1' and EMPTY = '0') then
Databuffer <= Fifo_memory(Rdaddr);
Rdaddr <= (Rdaddr + 1) mod m;
end if;
end process;
Fifo_write : process
begin
wait until rising_edge(CLOCK);
if RESET = '1' then
Wraddr <= 0;
elsif (Wrpulse = '1' and FULL = '0') then
Fifo_memory(Wraddr) <= To_Bitvector(DATAIN);
Wraddr <= (Wraddr + 1) mod m;
end if;
end process;
Offset <= (Wraddr - Rdaddr) when (Wraddr > Rdaddr)
else (m - (Rdaddr - Wraddr)) when (Rdaddr > Wraddr)
else 0;
EMPTY <= '1' when (Offset = 0) else '0';
FULL <= '1' when (Offset = (m-1)) else '0';
DATAOUT <= To_Stdlogicvector(Databuffer) when RDREQ = '0'
else (others => 'Z');
end A;
呵呵,本程序也是在参考了老外的基础上修改的,并非原创,特此声明。