异步FiFO原理及实现

异步FIFO主要用作跨时钟域的数据缓存,设计时的要点在于判断FIFO的空满状态。

一、代码中的重要参数
1、FIFO:First Input First Output,即先入先出队列,本质是RAM。
2、wr_clk:写时钟,所有与写有关的操作都是基于写时钟;
3、rd_clk:读时钟,所有与读有关的操作都是基于读时钟;
4、FIFO_WIDTH: FIFO的位宽,即FIFO中每个地址对应的数据的位宽;
5、FIFO_DEPTH: FIFO的深度,即FIFO中能存入多少个(位宽为FIFO_WIDTH的)数据;
6、full:FIFO发出的满信号,当FIFO满了之后,将full拉高;
7、empty:FIFO发出的空信号,当FIFO空了之后,将empty拉高;
8、wr_en:主机发送给FIFO的写使能,一般受制于FIFO发出的full信号,若full信号为高,一般主机会拉低写使能信号,防止新数据覆盖原来的数据;
9、rd_en:主机发送给FIFO的读使能,一般受制于FIFO发出的empty信号,若empty信号为高,一般主机会拉低读使能信号,防止从FIFO中读出不确定的数据。
二、判断空满状态

空:读快于写时,读指针追上写指针时,写入的数据被读完,写指针和读指针相同,FIFO为空。
满:当写快于读时,当写指针追上读指针,写入的数据比读出的数据多FIFO_DEPTH个,即写指针比读指针大一个FIFO_DEPTH时,此时FIFO为满。

格雷码:格雷码是一种安全码,因为相邻的格雷码只有一位不同,和二进制不同,二进制一般相邻的都有多位不同。格雷码在传输中,因为相邻只有一位不同,所以其误码率比二进制低得多。在同步时,出现亚稳态的概率也比二进制低。
二进制数转化为格雷码时最高位保留,其余从右到左相邻两位进行异或运算。
1、设计fifo时,让读写指针比读写地址多一位,称为标志位。对读写地址有没有影响。
2、使用格雷码的好处
当读写指针完全一样时为空,当读指针写指针除标志位之外完全一样为满。
3、空满信号的同步
因为空信号是对读操作有影响,所以,将空信号在rd_clk下同步(多采用两级寄存器)
因为满信号是对写操作有影响,所以,将满信号在wr_clk下同步(多采用两级寄存器)

跨时钟处理常见问题及解决方案
一般会遇到亚稳态、数据丢失等问题,简单介绍亚稳态及其解决办法。

  1. 单比特信号

当时钟信号上升沿到来的时候正好采样的数据也在发生变化,但是对于采样的时钟信号,如果想要采样得到一个稳定值,在clk的上升沿的前一段时间有一个建立时间TSU和在clk的上升沿的后一段时间有一个保持时间Th,如果在这两个时间段内采样的信号D发生跳变的话,输出的信号Q就会出现0,1之间跳变的不稳定、不确定状态,从而对采样结果产生干扰,这就是亚稳态。
1、从慢时钟到快时钟
采用打两拍,也就是两级锁存器。
第一级寄存器即使出现亚稳态,也会在一个时钟周期内稳定下来,这样第二级寄存器就会采到的就是一个稳定的值。并不是说第二级寄存器所输出的第一个状态 就是输入的第一个状态,只能说第二个寄存器输出第一个的状态是稳定的,之后的状态是跟输入的状态保持一致的。从而将第二个寄存器输出的结果进行处理,这样可以消除亚稳态的影响。
2、快时钟到慢时钟
快时钟域的数据到慢时钟域,如果信号只有一个脉冲宽度,那信号可能会采集不到,此时采用握手协议来解决。
所谓握手,即通信双方使用了专用控制信号进行状态指示。
握手协议:这个控制信号既有发送域给接收域的,也有接收域给发送域的,使用握手协议方式处理跨时钟域数据传输,只需要对双方的握手信号(req和ack)分别使用打两拍进行同步。在具体实现中,假设req、ack总线在初始化时都处于无效状态,当发送域检测到脉冲信号pulse_a,使req信号有效,随后发送有效的req信号给接收域。
接收域在检测到有效的req信号后锁存数据总线,然后回送一个有效的ack信号表示读取完成应答。发送域在检测到有效ack信号后撤销当前的req信号,接收域在检测到req撤销后也相应撤销ack信号,此时完成一次正常握手通信。

首先将快时钟域的信号A进行展宽处理A.zhankuan,当收到握手结束时的反馈时结束展宽。
当收到慢时钟的脉冲信号pulse_a,A.zhankuan信号采用打两拍的方式传送到慢时钟域B.zhankuan。
B.zhankuan打两拍后传送到快时钟域,作为握手结束的反馈信号,此时结束A信号的展宽。
最后输出B.zhankuan。
缺点:就是将aclk的信号进行了扩展,两次的同步也增加了延时。

  1. 多bit信号多位数据传输一般采用异步FIFO和格雷码。

你可能感兴趣的:(fpga开发)