dongzhiqing 发表于 2010-3-16 09:47:13

刚出锅的FIFO代码(VHDL),欢迎大家拍砖。

FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,没有地址线。

FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端时AD数据采集,另一端时计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。


下面是我写的一个FIFO代码,是深度和宽度都可以改变的,也只是刚刚前仿通过,欢迎大家拍砖。


端口的输入/输出解释:
----------------------------------------------------------------------------------------
---rst为复位信号。
---rd为读允许位,wr为写允许位
---data_in为数据输入,data_out 为数据输出;
---clk_wr,clk_rd分别是写数据 和 读 数据的时钟。
---wr_reset,rd_reset 分别是 写的指针复位 读的指针复位
---wr_yichu,rd_ok 分别是写满溢出位和“读完毕位”

-----------------------------------------------------------------------


----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date:    19:02:19 03/15/2010
-- Design Name:
-- Module Name:    fifo - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
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 instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity fifo is
generic (bits : integer :=8;
         words: integer :=5);
port(rst,clk_rd,clk_wr,rd,wr,rd_reset,wr_reset:in std_logic;
          data_in:in std_logic_vector(bits-1 downto 0);
          wr_yichu,rd_ok:out std_logic;
          data_out:out std_logic_vector(bits-1 downto 0));
end fifo;

architecture Behavioral of fifo is
type fifo_array is array(0 to words-1) of
   std_logic_vector(bits-1 downto 0);
signal vector_array:fifo_array;
signal addr_rd:integer range 0 to words;
signal addr_wr:integer range 0 to words;

begin
reset_andwr:process(rst,clk_wr)
      begin
                if (rst='1') then
                for i in vector_array'range loop
                vector_array(i)<=(others =>'0');
                end loop;
                elsif(clk_wr'event and clk_wr='1') then
                if(wr='1' and(addr_wr/=words)) then
                vector_array(addr_wr)<=data_in;
                end if;
                end if;
           end process;
---------------------------------------------------
read: process(rst,clk_rd)
      begin
      if(rst='1') then
                data_out<=(others=>'Z');
                elsif(clk_rd'event and clk_rd='1') then
                if(rd='1') then
                data_out<=vector_array(addr_rd);
                end if;
                end if;
                end process;
-----------------------------------------
wr_count:process(rst,clk_wr)
      begin
                if (rst='1') then
                addr_wr<=0;
                elsif(clk_wr'event and clk_wr='1') then
                if(wr_reset='1') then
                addr_wr<=0;
                elsif (wr='1') then addr_wr<=addr_wr+1;
               
                end if;
                end if;
               if(addr_wr=words) then wr_yichu<='1';
                          else wr_yichu<='0';
                          end if;   
                end process;
-------------------------------------------------
rd_count:process(rst,clk_rd)
      begin
                if (rst='1') then
                addr_rd<=0;
                elsif(clk_rd'event and clk_rd='1') then
               
                if (rd='1') then addr_rd<=addr_rd+1;
          
                end if;
                end if;
               if(addr_rd=words)then rd_ok<='1';
                          else rd_ok<='0';
                          end if;
      if(rd_reset='1') then
                addr_rd<=0;               
                end if;
                end process;
------------------------------------               
end Behavioral;




--------------------------------------------------
wr_count为写到哪里的标志,如果写满,则会停止写。并且wr_yichu置‘1’,然后等待wr_reset;
rd_count为读到哪里的标志 ,如果读不允许,则输出高阻态。读完时,rd_ok置‘1’,等待rd_reset.
------------------------------------------------------------------------------------



结束语:等到下到板子里后肯定会修改的,到时候再说,大家先看看。

281229961 发表于 2010-3-16 10:47:58

回复【楼主位】dongzhiqing
-----------------------------------------------------------------------

期待

z4057 发表于 2010-3-16 10:57:52

期待,好,想要一个最全的,参考

NJ8888 发表于 2010-3-16 12:19:20

这样会被综合在逻辑资源区,你应当用IP核的块RAM做FIFO

dongzhiqing 发表于 2010-3-16 12:51:48

回复【3楼】888888888888
-----------------------------------------------------------------------

我用的是xilinx的spartan ii,有20万门。还不知道他的ram多大。一般fifo都用ram来做吗?
我主要是刚入门,希望说的明白点。

yvhksovo 发表于 2010-3-16 12:51:54

我也觉得,fifo不是有ip核么,用着也挺方便的。为什么大家都想自己编呢?高手别拍我。。。。

NJ8888 发表于 2010-3-16 12:54:17

回复【4楼】dongzhiqing
回复【3楼】888888888888
-----------------------------------------------------------------------
我用的是xilinx的spartan ii,有20万门。还不知道他的ram多大。一般fifo都用ram来做吗?
我主要是刚入门,希望说的明白点。
-----------------------------------------------------------------------

XC2S100 10个块RAM,每个4096位,我试过16位宽,2048深度能通过

jerrychenglei 发表于 2010-3-16 17:47:17

楼主想法很好,但是实际异步时钟的FIFO需要考虑一些问题.
需要有同步采样电路,必然同时要用格雷码作为内部地址计数器的编码~
给楼主一分资料参考一下吧~
异步FIFO的设计ourdev_538703.pdf(文件大小:434K) (原文件名:异步FIFO的设计.pdf)

dongzhiqing 发表于 2010-3-17 08:55:14

回复【7楼】jerrychenglei
-----------------------------------------------------------------------

非常感谢啊。

tanguoyong 发表于 2010-3-17 12:57:53

好东西

ammcu 发表于 2010-3-17 20:12:11

thanks

Spunky 发表于 2010-3-19 15:42:05

mark

GAMEFPGA 发表于 2010-10-15 21:42:10

MARK
页: [1]
查看完整版本: 刚出锅的FIFO代码(VHDL),欢迎大家拍砖。