两种异步FIFO的设计及verilog源代码

合集下载

quartus 异步fifo用法

quartus 异步fifo用法

quartus 异步fifo用法在Quartus中使用异步FIFO,可以通过IP Core Catalog中的"ALTAsyncFIFO"来实现。

以下是使用异步FIFO的步骤:1. 打开Quartus Prime软件。

点击"File"菜单,选择"New Project"来创建一个新的项目。

2. 在"New Project Wizard"中,选择项目的名称、储存位置和顶层实体的文件。

点击"Next"继续。

3. 在"Add Files"步骤中,添加设计文件,包括顶层实体和其他组件文件。

点击"Next"继续。

4. 在"Family and Device Settings"步骤中,选择您的目标FPGA 器件。

点击"Next"继续。

5. 在"EDA Tool Settings"步骤中,选择Quartus使用的EDA工具。

点击"Next"继续。

6. 在"Summary"步骤中,查看项目设置的摘要。

点击"Finish"完成项目创建。

7. 在Quartus主界面的左侧面板中,点击"IP"选项卡,然后选择"Library"。

在IP Core Library窗口中,搜索"ALTAsyncFIFO"。

8. 在搜索结果中,选择"ALTAsyncFIFO"并点击"OK"来添加该IP到项目中。

9. 在设计文件中实例化ALTAsyncFIFO组件。

可以使用Quartus的"IP Catalog"来生成实例化代码。

10. 配置ALTAsyncFIFO的参数,包括FIFO大小、输出宽度、寄存器位宽等。

quartus 异步fifo用法 -回复

quartus 异步fifo用法 -回复

quartus 异步fifo用法-回复quartus异步FIFO用法引言:在数字电路设计中,FIFO(First In First Out)是一种常见的数据存储器,它允许数据以先进先出的顺序进出。

在使用Quartus进行FPGA设计时,异步FIFO是一种非常有用的工具,它可以帮助我们处理不同速度的数据流,并实现数据的缓冲和流量控制。

本文将介绍Quartus异步FIFO的基本概念和使用方法,并给出一些实例。

第一部分:Quartus异步FIFO概述1.1 什么是异步FIFO?异步FIFO是一种数据存储器,在其中数据可以以不同速度进入和退出。

与同步FIFO不同,异步FIFO的读写时钟可以是不同的,这使得它可以处理速度不匹配的数据流。

Quartus提供了异步FIFO的库函数和IP核,使得它可以在FPGA设计中方便地使用。

1.2 Quartus异步FIFO的特点Quartus异步FIFO具有以下特点:- 可以使用不同的时钟频率进行读写操作。

- 可以配置不同的缓冲深度来满足特定的设计需求。

- 可以实现流量控制和数据的重排序。

- 可以支持并行读写和读写使能信号。

- 可以适应不同的数据宽度和时钟域要求。

第二部分:Quartus异步FIFO的使用方法2.1 创建异步FIFO在Quartus中创建异步FIFO的方式有两种:使用库函数和使用IP核。

使用库函数创建异步FIFO的步骤如下:- 首先,在Quartus中打开设计工程,并创建一个新的源文件。

- 然后,将异步FIFO的库函数导入到源文件中,以便在设计中调用它。

- 接着,实例化异步FIFO,并通过参数配置其属性,例如宽度,深度,时钟域等。

- 最后,将异步FIFO连接到其他逻辑模块,完成设计。

使用IP核创建异步FIFO的步骤如下:- 首先,在Quartus中打开设计工程,并创建一个新的IP核。

- 然后,在IP核的界面中选择合适的FIFO类型和配置参数。

- 接着,将异步FIFO实例化到设计中,将其连接到其他逻辑模块。

异步fifo程序

异步fifo程序

高速异步FIFO的设计与实现摘要:本文主要研究了用FPGA芯片实现异步FIFO的一种方法。

通过对FPGA芯片内部EBRSRAM的深入研究.提出了一种利用格雷码对地址进行编码的异步FIFO设计方案。

实践证明.增加了系统可靠性和应用灵活性。

引言现代集成电路芯片中,随着设计规模的不断扩大.一个系统中往往含有数个时钟。

多时钟带来的一个问题就是,如何设计异步时钟之间的接口电路。

异步FIFO(First In First Out)是解决这个问题的一种简便、快捷的解决方案。

使用异步FIFO可以在两个不同时钟系统之间快速而方便地传输实时数据.在网络接口、图像处理等方面,异步FIFO都得到广泛的应用。

异步FIFO是一种先进先出的电路,使用在数据接口部分,用来存储、缓冲在两个异步时钟之间的数据传输。

在异步电路中,由于时钟之间周期和相位完全独立,因而数据的丢失概率不为零。

如何设计一个可靠性高、速度高的异步FIFO电路便成为一个难点。

1 异步FIFO的工作原理及逻辑框图本文根据实际工作的需要.给出了一种利用片内RAM构造FIFO器件的设计,重点强调了设计有效.可靠的握手信号FULL和EMPTY的方法。

并在LATTICE公司的FPGA芯片LFXP2-5E上实现。

LFXP2-5E属于LATIICE 公司XP2系列的一款,他采用优化的FlexiFLASH结构。

内部包含有基于查找表的逻辑、分布式和嵌入式存储器,锁相环(PLL)。

工程预制的源同步I/0以及增强的Sys DSP块。

有166Kbits的EBRSRAM。

利用其内部的EBRSRAM可以实现一定容量的异步FIFO.而无需单独购买FIF0器件。

由图1可以看出:异步FIFO一般由四个模块构成:数据存储单元,写地址产生模块,读地址产生模块,标志位产生模块。

整个系统分为两个完全独立的时钟域—读时钟域和写时钟域:在写时钟域部分由写地址产生逻辑产生写控制信号和写地址:读时钟域部分,由读地址产生逻辑产生读控制信号和读地址;在标志位产生模块部分,由读写地址相互比较产生空/满标志。

跨时钟域之异步FIFO

跨时钟域之异步FIFO

跨时钟域之异步FIFOAsynchronous FIFO Design异步FIFO的读写指针写指针写指针指向当前将要写⼊数据的位置,复位之后,读写指针被置零。

执⾏写操作的时候,向写指针指向的存储区写⼊数据,之后写指针加1,指向接下来要被写⼊数据的位置。

On a FIFO-write operation, the memory location that is pointed to by the write pointer is written, and then the write pointer is incremented to point to the next location to be written.读指针:读指针指向当前要被读取数据的位置,复位时,读写指针被置零,FIFO为空读指针指向⼀个⽆效的数据(FIFO为空,empty信号有效——拉⾼)。

当第⼀个有效数据被写⼊FIFO之后,写指针增加,empty flag信号被拉低,且读指针⼀直指向FIFO第⼀FIFO空标志:当读写指针是相等的时候:分两种情况1.当读写指针执⾏复位操作的时候。

2.当读指针赶上写指针的时候,最后⼀笔数据从FIFO读出后FIFO为空FIFO满标志:读写指针相等,当FIFO⾥⾯的写指针写满⼀圈之后⼜转回到和读指针同样的位置。

有个问题,读写指针相等的时候怎么判断FIFO是empty还是full?设计的时候增加⼀位bit去辅助判断FIFO是空还是满。

当写指针超过FIFO的最⼤寻址范围时,写指针将使辅助位zhi⾼,其余位为0.FIFO满的时候:读写指针的低位(n-1位bit)相等,⾼位(第n位bit)不同。

FIFO空的时候,读写指针的低位和⾼位都相等。

(针对⼆进制)但是⼆进制FIFO指针综合电路复杂,⼀般采⽤**格雷码**,⽂章中采⽤⼆进制转换格雷码的⽅法,判断FIFO的空满标志4位⼆进制格雷码,有效地址位为三位。

⼆进制转换为格雷码的算法:rgraynext = (rbinnext>>1) ^ rbinnext;1.顶层模块fifo:例化各个⼦模块//顶层模块实例化各个⼦模块module fifo#(parameter DSIZE = 8, //读写数据位宽均设置为8位parameter ASIZE = 4 // 存储地址位宽设置)(output [DSIZE-1:0] rdata,output wfull,output rempty,input [DSIZE-1:0] wdata,input winc, wclk, wrst_n,input rinc, rclk, rrst_n);wire [ASIZE-1:0] waddr, raddr;wire [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr;// 内部线⽹// synchronize the read pointer into the write-clock domainsync_r2w sync_r2w(.wq2_rptr (wq2_rptr),.rptr (rptr ),.wclk (wclk ),.wrst_n (wrst_n ));// synchronize the write pointer into the read-clock domainsync_w2r sync_w2r(.rq2_wptr(rq2_wptr),.wptr(wptr),.rclk(rclk),.rrst_n(rrst_n));//this is the FIFO memory buffer that is accessed by both the write and read clock domains.//This buffer is most likely an instantiated, synchronous dual-port RAM.//Other memory styles can be adapted to function as the FIFO buffer.fifomem#(DSIZE, ASIZE)fifomem(.rdata(rdata),.wdata(wdata),.waddr(waddr),.raddr(raddr),.wclken(winc),.wfull(wfull),.wclk(wclk));//this module is completely synchronous to the read-clock domain and contains the FIFO read pointer and empty-flag logic.rptr_empty#(ASIZE)rptr_empty(.rempty(rempty),.raddr(raddr),.rptr(rptr),.rq2_wptr(rq2_wptr),.rinc(rinc),.rclk(rclk),.rrst_n(rrst_n));//this module is completely synchronous to the write-clock domain and contains the FIFO write pointer and full-flag logicwptr_full#(ASIZE)wptr_full(.wfull(wfull),.waddr(waddr),.wptr(wptr),.wq2_rptr(wq2_rptr),.winc(winc),.wclk(wclk),.wrst_n(wrst_n));endmodule2.时钟域同步模块sync_r2w:读指针同步到写时钟域wclk// 采⽤两级寄存器同步读指针到写时钟域module sync_r2w#(parameter ADDRSIZE = 4)(output reg [ADDRSIZE:0] wq2_rptr, //读指针同步到写时钟域input [ADDRSIZE:0] rptr, // 格雷码形式的读指针,格雷码的好处后⾯会细说input wclk, wrst_n);reg [ADDRSIZE:0] wq1_rptr;always @(posedge wclk or negedge wrst_n)if (!wrst_n) beginwq1_rptr <= 0;wq2_rptr <= 0;endelse beginwq1_rptr<= rptr;wq2_rptr<=wq1_rptr;endendmodule原理图3.时钟域同步模块sync_w2r:写指针同步到读时钟域rclk//采⽤两级寄存器同步写指针到读时钟域module sync_w2r#(parameter ADDRSIZE = 4)(output reg [ADDRSIZE:0] rq2_wptr, //写指针同步到读时钟域input [ADDRSIZE:0] wptr, //格雷码形式的写指针input rclk, rrst_n);reg [ADDRSIZE:0] rq1_wptr;always @(posedge rclk or negedge rrst_n)if (!rrst_n)beginrq1_wptr <= 0;rq2_wptr <= 0;endelse beginrq1_wptr <= wptr;rq2_wptr <= rq1_wptr;endendmoduleRTL原理图4.存储模块//存储模块module fifomem#(parameter DATASIZE = 8, // Memory data word widthparameter ADDRSIZE = 4 // 深度为8即地址为3位即可,这⾥多定义⼀位的原因是⽤来判断是空还是满,详细在后⽂讲到) // Number of mem address bits(output [DATASIZE-1:0] rdata,input [DATASIZE-1:0] wdata,input [ADDRSIZE-1:0] waddr, raddr,input wclken, wfull, wclk);////////////////////////////////这部分没⽤到,可以单独写⼀个模块来调⽤//////////////`ifdef RAM //可以调⽤⼀个RAM IP核// instantiation of a vendor's dual-port RAMmy_ram mem(.dout(rdata),.din(wdata),.waddr(waddr),.raddr(raddr),.wclken(wclken),.wclken_n(wfull),.clk(wclk));//////////////////////////这部分没⽤到,可以单独写⼀个模块来调⽤//////////////////`else //⽤数组⽣成存储体// RTL Verilog memory modellocalparam DEPTH = 1<<ADDRSIZE; // 左移相当于乘法,2^4 将1左移4位reg [DATASIZE-1:0] mem [0:DEPTH-1]; //⽣成2^4个位宽位8的数组assign rdata = mem[raddr];always @(posedge wclk) //当写使能有效且还未写满的时候将数据写⼊存储实体中,注意这⾥是与wclk同步的if (wclken && !wfull)mem[waddr] <= wdata;`endifendmodule原理图5. rptr_empty模块:产⽣rempty和raddr信号//产⽣empty信号和raddar信号的模块module rptr_empty#(parameter ADDRSIZE = 4)(output reg rempty,output [ADDRSIZE-1:0] raddr, //⼆进制形式的读指针output reg [ADDRSIZE :0] rptr, //格雷码形式的读指针input [ADDRSIZE :0] rq2_wptr, //同步后的写指针同步到读时钟域input rinc, rclk, rrst_n);reg [ADDRSIZE:0] rbin;wire [ADDRSIZE:0] rgraynext, rbinnext;// GRAYSTYLE2 pointer//将⼆进制的读指针与格雷码进制的读指针同步always @(posedge rclk or negedge rrst_n)if (!rrst_n) beginrbin <= 0;rptr <= 0;endelse beginrbin<=rbinnext; //直接作为存储实体的地址rptr<=rgraynext;//输出到 sync_r2w.v模块,被同步到 wrclk 时钟域end// Memory read-address pointer (okay to use binary to address memory)assign raddr = rbin[ADDRSIZE-1:0]; //直接作为存储实体的地址,⽐如连接到RAM存储实体的读地址端。

异步FIFO的VHDL设计

异步FIFO的VHDL设计

异步FIFO的VHDL设计下面是一个异步FIFO的VHDL设计示例:```vhdllibrary ieee;use ieee.std_logic_1164.all;entity AsyncFIFO isgenericDATA_WIDTH : natural := 8; -- 数据宽度FIFO_DEPTH : natural := 16 -- FIFO深度portclk : in std_logic; -- 时钟信号rst : in std_logic; -- 复位信号read_en : in std_logic; -- 读使能write_en : in std_logic; -- 写使能read_data : out std_logic_vector(DATA_WIDTH-1 downto 0); -- 读数据write_data : in std_logic_vector(DATA_WIDTH-1 downto 0); -- 写数据full : out std_logic; -- FIFO满标志empty : out std_logic -- FIFO空标志end AsyncFIFO;architecture Behavioral of AsyncFIFO istype buffer_array is array (FIFO_DEPTH-1 downto 0) ofstd_logic_vector(DATA_WIDTH-1 downto 0);signal buffer : buffer_array; -- 数据缓冲区signal wr_ptr : natural range 0 to FIFO_DEPTH-1; -- 写指针signal rd_ptr : natural range 0 to FIFO_DEPTH-1; -- 读指针signal count : natural range 0 to FIFO_DEPTH-1; -- 缓冲区中数据个数beginprocess (clk)beginif rising_edge(clk) thenif rst = '1' thenwr_ptr <= 0;rd_ptr <= 0;count <= 0;elseif write_en = '1' and full = '0' then -- 写使能且FIFO非满buffer(wr_ptr) <= write_data;wr_ptr <= wr_ptr + 1;count <= count + 1;end if;if read_en = '1' and empty = '0' then -- 读使能且FIFO非空read_data <= buffer(rd_ptr);rd_ptr <= rd_ptr + 1;count <= count - 1;end if;end if;end if;end process;full <= '1' when count = FIFO_DEPTH-1 else '0';empty <= '1' when count = 0 else '0';end Behavioral;```在上面的代码中,`DATA_WIDTH`和`FIFO_DEPTH`是异步FIFO的泛型参数,可以根据实际需求进行配置。

异步fifo_gray code异步fifo的多种约束方式

异步fifo_gray code异步fifo的多种约束方式

异步fifo_gray code异步fifo的多种约束方式英文版Asynchronous FIFOs, also known as Gray code asynchronous FIFOs, are widely used in digital systems to facilitate communication between different clock domains. They are essential for ensuring data integrity and preventing data loss in asynchronous systems. However, designing and implementing asynchronous FIFOs can be challenging due to the potential for metastability issues and timing violations.There are several constraints that need to be considered when designing an asynchronous FIFO. One common constraint is the need for proper synchronization between the read and write pointers to prevent data corruption. This can be achieved using handshaking signals or other synchronization techniques.Another important constraint is the need to ensure proper data transfer between the two clock domains. This requires careful consideration of the setup and hold times of the data signals, as well as the use of Gray code encoding to minimize the chances of metastability.In addition, designers must also consider the impact of clock skew and jitter on the performance of the asynchronous FIFO. Clock skew can lead to timing violations and data corruption, while jitter can cause data loss and synchronization issues.Overall, designing an asynchronous FIFO with Gray code encoding requires careful consideration of various constraints and trade-offs. By carefully analyzing the system requirements and implementing appropriate design techniques, designers can ensure the reliable and efficient operation of their asynchronous FIFOs.中文版异步FIFO,也称为Gray码异步FIFO,在数字系统中被广泛应用,以促进不同时钟域之间的通信。

基于FPGA的异步FIFO设计与实现

基于FPGA的异步FIFO设计与实现

基于FPGA的异步FIFO设计与实现王伟国;张振东【摘要】随着现代数字电路系统密度和规模的不断扩大,一个系统中通常会包含多个时钟,因此不同时钟之间的数据传输成为亟待解决的问题.而一种可靠易行的解决方案就是异步FIFO.异步FIFO需要非常严格的多时钟技术,难以作出正确的设计合成和分析.本文提出了一种利用格雷码作为读写地址计数器的异步FIFO的设计方法,有效的避免了数据在不同时钟时间传输时遇到的亚稳态问题.并给出了综合仿真结果.%With the expanding of the density and scale of modern digital circuitry,a system will contain multiple clock.Therefore,the transfer of data between different clock becomes a serious problem needs to be solved.A reliable and feasible solution is asynchronous FIFO.Asynchronous FIFO require very strict clock technology,it is difficult to make the correct design of synthesis and analysis.This paper presents a design method of asynchronous FIFO which based on read/write counter in terms of gray code.This method effectively avoid the metastable state in the data transmission between different clock and given a comprehensive simulation results.【期刊名称】《聊城大学学报(自然科学版)》【年(卷),期】2012(025)003【总页数】6页(P79-84)【关键词】多时钟;异步fifo;verilog;HDL;格雷码【作者】王伟国;张振东【作者单位】中国科学院长春光学精密机械与物理研究所,吉林长春130033;中国科学院长春光学精密机械与物理研究所,吉林长春130033/中国科学院研究生院,北京100039【正文语种】中文【中图分类】TN4330 引言随着现代数字电路系统的实时数据处理能力的不断提高,逻辑电路的复杂程度和内核处理器的运算速度也快速增长,在使得一些复杂算法得以实现的同时也加剧了快速CPU与慢速外设之间的冲突.异步FIFO大量数据缓存的能力成功的解决了这一问题,但专用的高速异步FIFO芯片价格昂贵,且容量受限,随着现场可编程逻辑器件容量和速度的不断提高,利用现场可编程逻辑器件设计异步FIFO成为可行的方法.本文首先讨论了异步FIFO设计中经常出现的亚稳态问题和二进制计数器多位同时改变的问题,并给出解决办法,然后讨论了两种格雷码计数器的形式并作出比较,最后给出一种以格雷码为读写地址计数器的异步FIFO的设计方法和在设计异步FIFO时必须要注意的细节.1 多时钟电路中的亚稳态问题在一个时序电路中,合理的建立时间和保持时间是触发器正常工作的前提条件.对于下降沿触发的触发器而言,下降沿触发之前输入数据持续的最短时间是建立时间(setup time),下降沿触发之后输入数据持续的最短时间是保持时间(hold time).当电路时序不能满足setup time/hold time的要求时,系统时序就会出现混乱.在异步时序电路中,不同时钟之间是不存在任何关系的,必然会产生建立时间和保持时间冲突.解决系统时序问题常用双锁存器法如下图1所示,即在不同时钟之间传输数据时连续锁存两次.但是这种方法只是保证了电平的稳定,而在实际的系统中还需要FIFO作为不同时钟之间传输多位数据的接口.图1 避免亚稳态出现的双锁存器法2 异步FIFO指针对于同步FIFO来说,使用一个计数器计算读出和写入到FIFO缓存器中的数据量,计数器在只有写没读是递增,只读没写是递减,既读又写和没读也没写时保持不变.当计数器到达设定值时FIFO满信号置位,为零时空信号置位.在异步FIFO中,由于这种计算数据个数增减的计数器会被两个不同的时钟控制,因此这种计数器不能使用.所以,为了决定FIFO“空”和“满”状态,读指针和写指针必须相互比较.设计FIFO最主要的困难是生成FIFO指针和找到一个决定FIFO“空”和“满”状态的可靠方法.在FIFO设计中,读指针和写指针总是指向下一个要读和写的地址空间.当读或写操作完成后指针自动递增,当FIFO是空时读指针和写指针相等,当FIFO满时读指针和写指针也是相等.一种解决的方法是增加一个多余的MSB位来区分两种状态,当写指针递增超过地址范围时,写指针会递增MSB位,其他位清零,读指针同样也是.当读指针和写指针的MSB位不同时,意味着写指针比读指针多走了一圈,当MSB位相同时意味着走的圈数相等(如图2所示)图2 增加多余MSB后区分FIFO空和FIFO满的方法示意图当FIFO存储缓冲区需要(n-1)位地址时,地址指针用n位,当指针相等(包括MSB位)时空标志置位,当指针低(n-1)位相等且MSB位不等时满标志置位.2.1 二进制FIFO指针的情况二进制地址计数量会有多个位同时变化,因此在把二进制量在不同时钟域之间同步时会出现问题.一个解决的方法是取样并把周期计数量寄存在一个保持寄存器中,并发出一个ready信号,新时钟域收到信号并发出确认信号,这样变化的计数量就安全的传送到新时钟域.用这种方法不会产生上溢和下溢,因为当读指针递增到与写指针相等时,空信号置位,取样的写指针不反映当前写指针的值,而是小于当前值,故永远不能产生下溢,满信号也是如此.最常用的解决方法是用格雷码计数器,格雷码在每个时钟只有一位变换可以极大的减少在同步计数时错误的发生.3 格雷码计数器设计格雷码计数器的方法有很多,这里介绍二种简单直接的方法.下面详细介绍两种方法.3.1 格雷码计数器中的问题为了更好的理解把n-bit计数器转换成(n-1)-bit计数器时出现的问题,先考虑一下一个双重4-bit和3-bit格雷码计数器的例子如图3.图3 4-bit格雷码计数器示例及转换成3-bit格雷码时出现的问题在4-bit计数器中除了MSB位其余位关于中间对称,我们把2nd MSB位反相后,上半部分与下半部分的LSBs便相等.但是经过反相操作后整体便不是格雷码了,例如15(1100)到0(0000)的转变过程有两个bits变化,在下面的第一种格雷码计数器中会有解决方法.3.2 第一种格雷码计数器图4是第一种计数器的框图并是双重格雷码计数器中两个bits同时跳变的解决方法.其中假设输出寄存器的值是格雷码(ptr),此格雷码被输出到格雷码到二进制的转换器中,然后通过一个有条件递增的加法器并输出下一个格雷码值(gnext),连接到输出寄存器的输入端,如框图上半部分所示.(n-1)-bit格雷码简单地通过n-bit格雷码的2个MSBs的异或操作产生,(n-2)个LSBs不变.图4 第一种格雷码计数器示意图及其如何避免了两位同时跳变问题3.3 第二种格雷码计数器此种风格的格雷计数器(如图5所示)用了两组寄存器避免了把格雷码转换成二进制数的步骤.而且第二组寄存器也可以直接用来寻址FIFO存储器.n-bit格雷码指针仍然需要同步到不同的时钟域中.二进制指针可以更容易的通过计算产生“几乎满”和“几乎空”信号.因此在本论文的设计中用此种风格的格雷码计数器.图5 第二种格雷码计数器工作示意图4 总体设计及“空”和“满”信号的产生总体设计如图6所示,本设计方案共有四个模块,双口RAM模块,读控制模块,写控制模块,格雷码同步模块.写控制模块主要是当写使能信号有效且写满信号无效时产生写地址并实行地址递增功能,读控制模块实现相似功能,双口RAM模块用来使缓冲数据其读写动作可同时进行.4.1 “空”和“满”信号的产生“空”信号的产生比较简单,只需同步到读时钟域的写地址格雷码与n-bit的读指针的格雷码完全相等即可代码如下图6 异步FIFO总体设计框图及其信号说明但是,“满”信号的产生就没那么容易,简单地用n-bit格雷码作比较判断“满”信号是不可靠的.因为格雷码除了MSB位外是对称的如图3所示.在图3中假如写指针和读指针都指向地址7,此时写指针递增一次后,写指针指向地址8,读指针和写指针相比较,除了MSB位不同外其余各位均相等,满信号此时有效,但这是不符合实际情况的,错误的.这也是为什么在图4中应用双重n-bit格雷码计数器的一个原因.正确判断满信号的条件是:读写指针的n-bit格雷码的前两个MSBs都不相等,其余的写指针和同步读针相等.代码如下4.2 不同时钟速度因为异步FIFO被两个不同的时钟控制,很明显两个时钟运行在不同的速度下.当把较快的时钟同步到较慢的时钟时,会有一些计数值被跳过.当被同步的格雷码递增两次只被取样一次时也不会出现亚稳态问题,因为亚稳态出现在同步时钟上升沿附近有多位同时跳变时,而在两个同步时钟沿之间有格雷码跳变两次,第一次跳变距离同步时钟条边沿较远,只有第二次跳变在同步时钟沿附近,故不会产生亚稳态.当较快的格雷码计数器在较慢时钟沿之间递增多于一次,不会出现已经溢出却没有检测到的现象,因为同步到写时钟域的读指针滞后于当前的读指针,而写指针只会小于或等于同步读指针,故不会出现溢出.5 设计仿真及总结本设计采用Xilinx公司Spartan3A系列的XC3S1400A,封装时PG484,速度是-4,仿真器是ISE Simulator(VHDL/Verilog),硬件描述语言是Verilog,开发工具是ISE.最后对电路进行时序分析,结果为该FIFO运行速度可达到90.63MHz.wclk、rclk时钟周期分别为:75MHz、80MHz.先向FIFO中写入18个数据,当第16个数据被读入后wfull立即被置位如下图7.图7 写满仿真结果同时向FIFO中写入和读出数据,由于wptr要经过两个读周期才能同步到读时钟域,故在waddr递增后的第二个rclk的上升沿rempty才清零如下图8所示.本文对异步FIFO的结构和重要时序问题给予了详细的阐述,并得到了可靠的仿真结果.在高速数据采集系统中,采用高性能FPGA作为数据预处理和高速异步FIFO 作为数据采集缓存的应用都十分广泛.把FIFO集成在FPGA中简化了电路设计的复杂程度,增加了电路的集成化程度和可靠性,是未来高速数据采集系统的重要发展方向.图8 同时写入读出时的仿真结果参考文献【相关文献】[1] Clifford E.Cummings,Synthesis and Scrip ting Techniques for De signing Multi-Asynchronous Clock Designs[A].SNUG-2001,2001(3):2-8.[2]吴自信,张嗣忠.异步FIFO结构及FPGA设计[J].单片机及嵌入式系统应用,2000,22(3):1.[3]赵雅兴.FPGA原理、设计与应用[M].天津:天津大学出版社,1999.[4]夏宇闻.数字系统设计-Verilog实现[M].北京:高等教育出版社,2006.[5]王金明.Verilog HDL程序设计教程[M].北京:人民邮电出版社,2004.。

quartus 异步fifo用法 -回复

quartus 异步fifo用法 -回复

quartus 异步fifo用法-回复Quartus 异步FIFO 用法说明引言:在现代数字系统设计中,FIFO(先进先出)是一种常见的数据缓冲区,用于解决数据在不同速度的模块之间的数据流问题。

在Quartus 中,异步FIFO 提供了一种灵活和方便的方式来实现数据的缓冲和流控。

本文将逐步介绍Quartus 异步FIFO 的基本用法,帮助读者了解其操作和配置。

第一步:创建FIFO首先,在Quartus 中打开自己的设计项目,选择要创建异步FIFO 的模块。

然后,点击菜单栏中的"Project",选择"New",再选择"FIFO MegaWizard"。

接下来,按照提示选择FIFO 的类型、数据位宽和深度等配置参数。

请注意,深度是指FIFO 可以容纳的数据数量。

点击"Next"继续,然后会出现一个界面,该界面将由Quartus 生成FIFO 的RTL(寄存器传输级)代码。

在这个界面上,您可以选择生成的接口样式以及其他自定义选项。

完成配置后,点击"Finish",Quartus 将自动生成FIFO 的VHDL 或Verilog 代码,并将其添加到项目中。

第二步:添加FIFO 的输入和输出端口一旦FIFO 生成完成并添加到项目中,您需要将其引入到适当的模块中,并为其添加输入和输出端口。

假设我们将FIFO 引入到名为"Top_Module"的模块中,请按照以下步骤进行操作:1. 在"Top_Module"的代码中,将FIFO 的引用添加为一个实例,例如:fifo_inst : entity work.my_fifoport map (clk => internal_clk,reset => reset,wr_data => data_in,wr_en => write_enable,rd_data => data_out,rd_en => read_enable,full => fifo_full,empty => fifo_empty);2. 根据您的设计需要,为FIFO 添加输入和输出信号。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

异步FIFO及verilog原码_1 异步FIFO及verilog原码

这几天看了Clifford E. Cummings的两篇大作《Simulation and Synthesis Techniques for Asynchronous FIFO Design》and 《Simulation and Synthesis Techniques for Asynchronous FIFO Design with Asynchronous Pointer Comparisons》颇有感想,真可谓经典之作,不可错过。

1.什么是FIFO? FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

2.什么情况下用FIFO? FIFO一般用于不同时钟域之间的数据传输,比如FIFO的一端是AD数据采集,另一端是计算机的PCI总线,假设其AD采集的速率为16位 100K SPS,那么每秒的数据量为100K×16bit=1.6Mbps,而PCI总线的速度为33MHz,总线宽度32bit,其最大传输速率为1056Mbps,在两个不同的时钟域间就可以采用FIFO来作为数据缓冲。

另外对于不同宽度的数据接口也可以用FIFO,例如单片机位8位数据输出,而DSP可能是16位数据输入,在单片机与DSP连接时就可以使用FIFO来达到数据匹配的目的。

3.FIFO的一些重要参数 FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它只的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM 32位等等,FIFO的宽度在单片成品IC中是固定的,也有可选择的,如果用FPGA自己实现一个FIFO,其数据位,也就是宽度是可以自己定义的。

FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12 ,就可以存储12个8位的数据,FIFO的深度可大可小,个人认为FIFO深度的计算并无一个固定的公式。在FIFO实际工作中,其数据的满/空标志可以控制数据的继续写入或读出。在一个具体的应用中也不可能由一些参数算数精确的所需FIFO深度为多少,这在写速度大于读速度的理想状态下是可行的,但在实际中用到的FIFO深度往往要大于计算值。一般来说根据电路的具体情况,在兼顾系统性能和FIFO成本的情况下估算一个大概的宽度和深度就可以了。而对于写速度慢于读速度的应用,FIFO的深度要根据读出的数据结构和读出数据的由那些具体的要求来确定。

满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。

空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。

读时钟:读操作所遵循的时钟,在每个时钟沿来临时读数据。

写时钟:写操作所遵循的时钟,在每个时钟沿来临时写数据。

读指针:指向下一个读出地址。读完后自动加1。

写指针:指向下一个要写入的地址的,写完自动加1。 读写指针其实就是读写的地址,只不过这个地址不能任意选择,而是连续的。

4.FIFO的分类 根均FIFO工作的时钟域,可以将FIFO分为同步FIFO和异步FIFO。同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

5.FIFO设计的难点 FIFO设计的难点在于怎样判断FIFO的空/满状态。为了保证数据正确的写入或读出,而不发生益处或读空的状态出现,必须保证FIFO在满的情况下,不能进行写操作。在空的状态下不能进行读操作。怎样判断FIFO的满/空就成了FIFO设计的核心问题。由于同步FIFO几乎很少用到,这里只描述异步FIFO的空/满标志产生问题。在用到触发器的设计中,不可避免的会遇到亚稳态的问题(关于亚稳态这里不作介绍,可查看相关资料)。

在涉及到触发器的电路中,亚稳态无法彻底消除,只能想办法将其发生的概率将到最低。其中的一个方法就是使用格雷码。格雷码在相邻的两个码元之间只由一位变换(二进制码在很多情况下是很多码元在同时变化)。这就会避免计数器与时钟同步的时候发生亚稳态现象。但是格雷码有个缺点就是只能定义2^n的深度,而不能像二进制码那样随意的定义FIFO的深度,因为格雷码必须循环一个2^n,否则就不能保证两个相邻码元之间相差一位的条件,因此也就不是真正的各雷码了。 第二就是使用冗余的触发器,假设一个触发器发生亚稳态的概率为P,那么两个及联的触发器发生亚稳态的概率就为P的平方。但这回导致延时的增加。亚稳态的发生会使得FIFO出现错误,读/写时钟采样的地址指针会与真实的值之间不同,这就导致写入或读出的地址错误。由于考虑延时的作用,空/满标志的产生并不一定出现在FIFO真的空/满时才出现。可能FIFO还未空/满时就出现了空/满标志。这并没有什么不好,只要保证FIFO不出现overflow or underflow 就OK了。

很多关于FIFO的文章其实讨论的都是空/满标志的不同算法问题。

第一个算法:Clifford E. Cummings的文章中提到的STYLE #1,构造一个指针宽度为N+1,深度为2^N字节的FIFO(为便方比较将格雷码指针转换为二进制指针)。当指针的二进制码中最高位不一致而其它N位都相等时,FIFO为满(在Clifford E. Cummings的文章中以格雷码表示是前两位均不相同,而后两位LSB相同为满,这与换成二进制表示的MSB不同其他相同为满是一样的)。当指针完全相等时,FIFO为空。 这种方法思路非常明了,为了比较不同时钟产生的指针,需要把不同时钟域的信号同步到本时钟域中来,而使用Gray码的目的就是使这个异步同步化的过程发生亚稳态的机率最小,而为什么要构造一个N+1的指针,Clifford E. Cummings也阐述的很明白,有兴趣的读者可以看下作者原文是怎么论述的,Clifford E. Cummings的这篇文章有Rev1.1 \ Rev1.2两个版本,两者在比较Gray码指针时的方法略有不同,个Rev1.2版更为精简。

第二种算法:Clifford E. Cummings的文章中提到的STYLE #2。它将FIFO地址分成了4部分,每部分分别用高两位的MSB 00 、01、 11、 10决定FIFO是否为going full 或going empty (即将满或空)。如果写指针的高两位MSB小于读指针的高两位MSB则FIFO为“几乎满”,若写指针的高两位MSB大于读指针的高两位MSB则FIFO为“几乎空”。

它是利用将地址空间分成4个象限(也就是四个等大小的区域),然后观察两个指针的相对位置,如果写指针落后读指针一个象限(25%的距离,呵呵),则证明很可能要写满,反之则很可能要读空,这个时候分别设置两个标志位dirset和dirrst,然后在地址完全相等的情况下,如果dirset有效就是写满,如果dirrst有效就是读空。 这种方法对深度为2^N字节的FIFO只需N位的指针即可,处理的速度也较第一种

方法快。

异步FIFO及verilog原码_续 两篇文章的原码 //----------------------STYLE #1-------------------------- module fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n); parameter DSIZE = 8; parameter ASIZE = 4;

output [DSIZE-1:0] rdata; output wfull; output rempty; input [DSIZE-1:0] wdata; input winc, wclk, wrst_n; input rinc, rclk, rrst_n;

reg wfull,rempty; reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr; reg [ASIZE:0] rbin, wbin; reg [DSIZE-1:0] mem[0:(1< wire [ASIZE-1:0] waddr, raddr; wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbnnext; wire rempty_val,wfull_val; //-----------------双口RAM存储器-------------------- assign rdata=mem[raddr]; always@(posedge wclk) if (winc && !wfull) mem[waddr] <= wdata; //-------------同步rptr 指针-------------------------

相关文档
最新文档