(完整word版)异步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

跨时钟域之异步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的工作原理

异步fifo的工作原理

异步fifo的工作原理今天咱们来唠唠异步FIFO这个超有趣的东西哦。

你可以把异步FIFO想象成一个特别的小仓库,这个小仓库是用来存放数据的呢。

不过它可有点特别,和咱们平常那种规规矩矩同步的仓库不太一样。

异步FIFO主要是在不同时钟域之间工作的。

就好比啊,有两个世界,一个世界的节奏快,另一个世界的节奏慢,异步FIFO就在这两个节奏不一样的世界之间搭起了一座数据的桥梁。

那它怎么存数据呢?当有数据要进来的时候,就像是有人要往这个小仓库里送货。

在写端口这边,有一个写指针,这个写指针就像一个小向导,它告诉大家数据应该放在仓库的哪个位置。

每次有新的数据要存进来,写指针就会指向下一个空闲的地方。

就像我们在图书馆书架上找空位放书一样,写指针就是那个帮我们找空位的小助手。

再说说读这边吧。

读端口有个读指针,这个读指针就负责从仓库里取数据。

它就像一个小管家,知道哪些数据已经被取走了,哪些还在仓库里等着被取。

读指针也是一步一步地移动,每次取走一个数据,就会指向下一个要取的数据的位置。

这里面有个超关键的东西,就是空满标志的判断。

你想啊,如果仓库满了,还往里塞东西,那不就乱套了嘛;或者仓库都空了,还在傻乎乎地去取数据,那也不行呀。

对于空满标志的判断呢,其实有点小巧妙。

因为是异步的,时钟不一样,所以不能简单地用一个计数器来判断。

一般会采用一些特殊的编码方式,像是格雷码。

为啥用格雷码呢?这就像是给这个小仓库的货物管理上了一道保险。

格雷码的好处就是相邻的码值只有一位不同。

这样在不同时钟域转换的时候,就不容易出错啦。

比如说,写指针和读指针在判断满的时候,不是简单地看数字大小哦。

因为时钟不一样,数字可能会乱套。

用格雷码就不一样啦,它能很准确地判断出是不是真的满了。

就好像是两个人在不同的节奏下数数,但是通过一种特殊的规则,能准确知道什么时候仓库满了。

还有哦,异步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.。

异步fifo原理

异步fifo原理

异步fifo原理异步FIFO原理解析什么是异步FIFO异步FIFO是一种用于数据接收和发送的电子元件,它按照先入先出(FIFO)的原则处理数据。

它被广泛应用于数字电子系统中的数据缓冲、通信和存储等领域。

异步FIFO的原理异步信号与同步信号的区别1.同步信号:数据的传输采用同一个时钟信号驱动,数据的采样和传输是在时钟的上升沿或下降沿进行的。

2.异步信号:数据的传输不依赖于单一的时钟信号,发出数据的一方和接收数据的一方的时钟信号不一定完全一致。

异步FIFO的工作原理异步FIFO是由两个独立的存储器组成,一个作为数据的写入端,另一个作为数据的读取端。

它们通过一系列的控制信号来实现数据的缓冲和传输。

1.当数据写入FIFO时,写指针会自动递增,将数据写入写指针所指向的位置。

2.当数据读取FIFO时,读指针会自动递增,读取指针所指向的数据,并将其传递给外部。

异步FIFO的数据同步由于不同的时钟信号可能有不同的频率和相位,所以在数据传输过程中,可能会出现时钟抖动或者抖动,导致数据读取错误。

因此,为了保证数据的可靠传输,异步FIFO使用了数据同步机制。

1.FIFO的写指针和读指针都需要采用相关的同步电路,使其与本地时钟信号同步。

2.读指针必须等待写指针来自写入端的下一个时钟周期,并且读指针的启动信号必须与读指针同一时钟周期内变化。

异步FIFO的关键问题异步FIFO在使用过程中,需要注意一些关键问题,以确保数据的正确传输。

数据宽度不兼容在异步FIFO中,写入端和读取端的数据宽度不一定相同。

为了解决这个问题,需要使用数据宽度转换电路,将数据进行格式转换。

读写速度不匹配在数据写入和读取的过程中,写入端和读取端的速度可能不一致。

为了解决这个问题,一种常见的解决方案是使用FIFO深度控制电路,来控制数据的写入和读取速度。

异步FIFO的应用场景异步FIFO主要用于数据缓冲、数据通信以及存储系统等领域。

它在数字电子系统中起到了缓冲数据、数据传输和数据存储的重要作用。

高速异步FIFO的设计和实现

高速异步FIFO的设计和实现

万方数据路中,这一信号最终会朝着0和1两个稳态转换,变成稳定的信号。

这一变换所需的时间取决于寄存器的结构和参数,通常在一个时钟周期内可以完成这一从亚稳态到稳态的转换。

所以,在设计中普遍采用两级寄存器串接的同步器来对信号进行同步,如图1所示。

图1解决亚稳态的同步器电路2.2毛刺单根信号的同步采用图1所示的同步电路即可消除亚稳态问题。

然而,对多位总线信号的同步,除了亚稳态外,还有一个重要的问题就是毛刺现象。

如果需要同步的总线的多位同时发生变化,由于在实际电路中各位的延时不可能完全一致,因此中间就可能会产生毛刺现象。

而用另一个频率相位完全不同的时钟采样的时候就有可能采样到毛刺信号,造成错误的同步。

例如,FIFO的读写指针是一个二进制计数器,当它从l计数到2时,位0从1变成0,位l从0变成1。

如果位0从1变成0的延时比位1从0变1要大,就会在1和2中间多出一个毛刺3,而如果直接用图l的同步电路同步,就有可能错误地在另一个时钟域得到一个3的结果。

对于FIFO的设计来说,这样的同步错误是致命的,会造成空满判断的失误。

解决这一问题就是需要采用无毛刺的电路结构,无毛刺电路要求信号同步前必须被寄存器锁存,并且每次只有一位发生变化。

例如,文献[2]中设计的FIFO就采用格雷码来避免这一问题。

3高速异步FIFO结构3.1基本结构本文设计的高速异步FIFO结构如图2所示,主要包括数据通路reg—file和控制模块fifo—eft两个部分。

reg—file模块是FIFO的存储器部分;fifo_eft模块负责FIFO的读写控制,如读写指针的产生和空满信号的产生。

图2高速异步FWO结构框图本设计的外部端口如表l所示。

3.2reg__file模块设计FIFO的存储器部分可以采用双端口SRAM或者用DFF寄存器搭建存储部分。

由于本设计为32×32的FIFC,存储器容量不大,采用双端口SRAM由于powerring等因素,面积会比用寄存器搭建要大,速度也不容易达86到500MHz的高速。

4.异步FIFO的设计

4.异步FIFO的设计

利用异步FIFO在跨时钟域中降低亚稳态发生概率在数字电路设计中,时钟是整个电路最重要、最特殊的信号,系统内大部分器件的操作都是在时钟的跳变沿上进行,如果时序不满足要求,就可能造成逻辑状态出错甚至整个系统设计的失败。

随着SOC技术的不断发展,数字系统设计的复杂度也在日益增加,经常需要跨时钟域的数据传输,通信技术等异步设计才能实现特定的功能需求。

本文设计的异步FIFO就是为了解决将数据从一个时钟域同步的读/写到另一个时钟域,并且能很好的避免亚稳态的发生。

1.异步系统任意的两个系统如果满足以下条件之一,如图1-2所示,就可称其为异步的:(1)工作在不同的时钟频率上;(2)工作在相同频率上,但相位不同图1-2 异步系统时钟当两个不同时钟域的系统进行数据传输,由于接口处是异步的,就可能会违反建立时间和保持时间规则导致亚稳态以及不可靠的数据传输,因此处理起来较同步逻辑复杂困难。

在同步系统中,输入信号必须总是满足寄存器时序要求,所以亚稳态不会发生。

亚稳态问题通常发生在当一个信号在无关的线路中或异步时钟域中传输。

在所有的异步系统中,亚稳态是不可避免的。

1.1亚稳态所有的数字器件寄存器都定义了一个信号时序要求,满足了这个要求寄存器才可以正确地在输入端获取(capture)数据在输出端产生数据。

为了确保数据的可靠与正确性,在数据传输过程中必须满足寄存器的建立时间和保持时间,如图1-1,即输入数据在时钟沿之前必须稳定一段时间(寄存器建立时间Tsu)并且在时钟沿之后稳定一段时间(寄存器保持时间Th),然后寄存器输出经过一个特定的时钟到输出延时(clock to output ,Tco)后有效。

图1-1 建立时间与保持时间如果一个数据信号在翻转中违反了一个寄存器的建立和保持时间的要求,寄存器的输出可能就会出现亚稳态。

在亚稳态中,寄存器的输出值在高和低之间徘徊一段时间,这就意味着输出翻转到一个确定的高或低的延时会超过固定的时钟到输出延时。

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

异步FIFO的实现方式实验目的本次实验介绍一种异步FIFO的实现方式。

使用FIFO存储器可以在两个不同时钟系统之间快速而方便的传输数据。

另外,在网络接口,图像处理等方面异步FIFO存储器也得到了广泛的应用。

因此,异步FIFO存储器具有较大的研究和应用价值。

异步FIFO的介绍和整体结构异步FIFO(First In First Out)存储器是指向FIFO缓冲器中写入数据的时钟域和从FIFO缓冲器中读取数据的时钟域是不同的,这两个时钟之间没有必然的因果关系。

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

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

如何设计一个高可靠性、高速的异步FIFO存储器便成为一个难点。

异步FIFO的一般结构如图1所示,都是由一个读时钟域电路、一个写时钟域电路和一个双端口的RAM来构成的。

异步FIFO与同步FIFO所做的工作是相同的,都是在写信号有效时写数据到RAM中,在读信号有效时把数据从RAM中读出,所以对于中间部分的RAM 设计是比较简单的。

另外,读电路和写电路单独实现起来也是比较容易的,只需要按照同步FIFO的工作情况,如果没有写满或读空的状态时每写一个数据就把写地址加1,每读一个数据就把读地址减1。

设计难点在于两个时钟域的交叠部分:满、空状态的产生,这也是设计的重点。

图1 异步FIFO结构针对这个问题,先从对亚稳态的处理开始介绍亚稳态的处理一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。

在这个稳定期间,触发器输出一些中间级电平,或者可能处于振荡状态、并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。

亚稳态发生的原因是由于在同步系统中,如果触发器的建立时间或保持时间不满足,就可能产生亚稳态,此时触发器输出端Q在亚稳态是指触发器无法在某个规定时间段内达到一个可确认的状态,逻辑误判有可能通过电路的特殊设计减轻危害(如本设计中将使用的Gray码计数器),而亚稳态的传播则扩大了故障面,难以处理。

在数字集成电路中寄存器要满足建立时间和保持时间。

建立时间是在时钟翻转之前数据输入必须有效的时间,保持时间是在时钟沿之后数据输出必须仍然有效的时间。

当一个信号被寄存器锁存时,如果信号和时钟之间不满足这个要求,Q的值是不确定的,并且在未知的时刻会固定到高电平或低电平。

此时寄存器进入了亚稳态(Metastability)。

解决这一问题的最简单方法是使用同步器,使得在另一个时钟域采样时信号足够稳定。

同步器的设计本身就是一个比较麻烦的问题,本次设计中也不深入讨论一些细节性的问题,直接采用两级采样的同步器,避免了使用一级同步器仍可能出现亚稳态的情况。

每个这样的同步器都具有一个等于时钟周期的等待时间。

这种同步器可以把一些亚稳态的值同步为确定值,但并不一定是正确值,同时有一些亚稳态也还是无法稳定成确切值的,这种情况称为同步出错。

由于同步出错的随机性,很难对它们进行跟踪。

如果想进一步降低亚稳态出现的概率、可以再増加同步器的级数,但是太多的同步器会使系统的性能下降,所以系统中不会用太多的同步器,一般使用两个同步器已经足够。

空满状态的判断之所以在前面介绍了亚稳态的问题,是因为这是判断满状态或空状态无法回避的一个问题。

因为读电路在读控制时维持一个地址指针,写电路在写控制时维持一个地址指针,简单来说,这两个地址指针直接一比较,就能得到空满的判断结果,但是实际操作起来非常麻烦。

例如对于满状态来说,这是写入电路所关心的状态,因为满状态下不能继续写入数据,但是空状态对于写电路没有影响。

如果写入电路要判断当前FIFO是否为满,就需要把写电路自身维持的写指针和读电路维持的读指针做比较,这个读指针就需要送入写电路中,此时就发生了穿过时钟域的问题,也就是说,读指针要从读时钟域同步到写时钟域,然后参与判断,此时就需要前面介绍的同步器。

同样,对于空状态来说,这是读出电路所关心的状态,也是由读电路来维持的,因为空状态下再读数就会得到错误的数据,但是满状态下读数是没有影响的。

如果读电路要判断当前FIFO是否为空,就需要把写时钟域中的写指针取到读时钟域来,和读时钟域的读指针进行比较得出是否是空状态,同样跨越了时钟域。

在跨时钟域系统中希望出现错误的概率越低越好,此时格雷码无疑是最好的一个选择。

格雷码属于可靠性编码,是一种误差最小化的编码,它大大减少了由一个状态到下一个状态时电路混淆。

由这种编码相邻的两个码组之间只有一位不同,和其他编码同时改变2位和多位的情况相比更为可靠。

表1所示是格雷码与二进制码的对应关系。

表1 格雷码与二进制码转换真值表由前面的介绍可知通过同步器之后信号稳定的值可能是1也可能是0,可能与输入的值相同也可能与输入的值不同。

如果对于二进制码,这显然是灾难性的。

例如从十进制的7变到8,二进制码是从0111变为1000,把0111送入同步器之后,由于4位都要变化,所以4位都可能会出现亚稳态,从而在同步器的输出端就会出现各种可能性,这样即使数据稳定下来,对整个电路的作用也很小。

而如果采用格雷码,是从0100变为1100,只是最高位发生了改变,也就只有这一位可能会出现亚稳态的情况。

这样经过同步器处理之后,输出端可能得到的值只有两种0100或1100,其中1100是正确的数值,如果得到这个输出自然是最好,但即使是0100的输出,也只是和原来的值相同,可以认为没有变化,这也不会对电路造成负面的影响。

相比二进制代码那种变化后什么值都有可能的情况,格雷码显然是一种更易于接受的编码方式。

格雷码虽然在跨时钟域方面效果比较好,但在本身计数方面是不足的,也就是说还需要把格雷码转换成二进制码来计数,4位的格雷码转二进制码的代码部分如下:bin[0]=gray[3]^gray[2]^ gray[1]^ gray[0];bin[1]=gray[3]^gray[2]^ gray[1];bin[2]=gray[3]^gray[2];bin[2]=gray[3];也可以用for循环完成:module gray[2](bin,gray);parameter size=4;output [size-1:0] bin;input [size-1:0] gray;reg [size-1:0] bin;integer i;always @(gray)for(i=0;i,size;i=i=i+1);bin[i]=^(gray>>1);endmodule计数之后还要变回格雷码,转换的方法与上述方式类似。

这样使用格雷码作为指针就可以降低亚稳态带来的影响。

接下来要解决的是空满判断的问题,常用的判断方法是附加位比较法。

附加位比较法是给每个指针增加一个附加位,对于二进制指针而言,将存储空间的最后一个存储单元写入数据后,地址将变为零,即地址指针低n-1位清零并向最高位(MSB)也就是附加位进位。

读指针也是如此工作。

如果两个指针的最高位(MSBs)不同而其余位相同,就说明写指针比读指针多循环了一次,标志FIFO存储器处于满状态。

如果包括最高位在内的两个指针完全相同,则说明写指针和读指针经历了相同次数的循环,也就是说FIFO存储器处于空状态。

这样读指针和写指针就变成了一个n位指针,其中低n-1位是用来存放FIFO 存储器的地址,可以用来对2n-1个存储单元寻址,而最高位则用来辨别当两个指针的地址相等时是满状态还是空状态。

对二进制指针来说,用这种方式来区分满状态与空状态是可行的。

但是,格雷码指针却不能直接使用这种方式,原因有两个。

举个4位格雷码的例子,格雷码计数器的低3位用于存放存储地址,第四位是附加位,这个FIFO存储器的存储容量为8。

正确的操作应当是,当写(或读)完一个循环时,地址应该重新开始计数,附加位应该翻转。

然而格雷码指针却并非如此,地址由7到8格雷码由0-100到1-100),指针的附加位改变,但是地址位(低n-1位)却没有重新开始计数,这是由于格雷码是一种镜像码造成的。

第二个原因是这种格雷码不能直接产生满状态标志。

如果两个格雷码指针都是Gray-7,这时的FIFO存储器为空状态,在进行一次写操作后写指针将加1,格雷码第4位将变为1而低3位不变,这时的读指针和写指针的最高位将不同而低位相同。

如果这样的话,FIFO存储器满标志将置位,这显然是错误的,因而需要对这个4位的格雷码进行修改。

想要的结果是:一个n位的(即包括附加位)格雷码计数器用在异步时钟域间传递数据,但是又希望它的低n-1位计数器也是格雷码类型的。

这样低n-1位就能单独形成一个循环,而不是一种反射码。

所以,此时需要的是一个既能产生n位的格雷码序列又能产生n-1位的格雷码序列的计数器。

分别实现一个n位的格雷码计数器和一个n-1位的格雷码计数器自是非常简单:用一个计数器来实现一个n位的格雷码计数器,并将这个计数器的次高位进行修改而低位保持不变以实现一个n-1位的格雷码计数器,这也不是一件很难的事情。

这种既能产生n位格雷码又能产生n-1位格雷码的计数器被称为"两重格雷码计数器。

下面以3位和4位格雷码来说明空满状态的判断标准。

3位格雷码表示的就是地址空间,可以有8个存储空间。

由于写入和读出并不是按照从000开始的,而是可以以任意一个位置开始,比如存放数据可以按照十进制地址5、6、7、0、1、2、3、4的地址顺序来存放,读出数据也同理,这样为了表示循环,就增加了1位变为4位格雷码。

首先说明空状态的判断标准,空状态表示读指针和写指针重合,此时无论是看3位格雷码还是4位格雷码都应该是完全相同,比如写指针指向1010,读指针也必然指向1010,这样判断空状态就只需要判断两个指针是否相同,相同时即为空,不同时即为不空。

然后解释满状态的判断标准。

满状态判断比较复杂。

假设一次写入数据是从十进制地址6开始,连续写入8个数据。

到14,这时存满8个数据,应产生满状态输出,这两个地址形式如下:如果是二进制地址,判断的方法已经介绍过了。

而格雷码地址的前两位是不同的,但后面的两位是相同的。

如果扩展成更多位的格雷码,满状态下依然是这种情况,即前两位不同,后面位均相同。

这样判断满状态首先要保证除去前两位之后的剩余部分是相同的。

然后对于本例来说,需要保证前两部分是01和10,如果地址是以01开头,则满时一定是10;如果以10开头,满时一定是01。

判断的方法可以有很多种,这里采用先取前两位的异或值,保证相等,此时只可能是0,1的组合,然后再判断首位不同,这样就只能是01和10这两种情况。

经过这三个条件的判断,就能就保证此时为写满状态。

相关文档
最新文档