【FPGA学习记录1】异步FIFO的介绍

写在前面

本人在今天学习FIFO之前,对FIFO的了解仅限于它的名字,First in First out,一些博客中提及异步FIFO要比同步FIFO更加复杂,所以就头铁地直接开始学习异步FIFO。本篇文章是在学习了一些视频教程并阅读了一些其他博客之后,总结得到的,所以如果有不对的地方或者不完善的地方欢迎大家在评论区里指出,我会及时更改。

本文所涉及到的参考博客和参考视频都会列在文章末尾,需要的同学可以去阅读。另外本文并未涉及到异步FIFO的Verilog实现,之后我会去学习一些开源代码,尝试实现。

1.FIFO的定义以及为什么要用FIFO、FIFO的分类

1.1什么是FIFO

FIFO即first in first out,是先进先出的数据缓存器,类似于C++中的queue,只能通过内部读写指针来顺序地写入数据,顺序地读出数据,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
在FPGA中生成FIFO有两种方式:

  • 当所需要的FIFO较小时,可以使用分布式RAM(distributed RAM)或者寄存器来生成,通常一个基于寄存器生成的FIFO的深度为32字节(即可以存储32个数据)
  • 当所需要的FIFO较大时,可以使用嵌入式存储单元(也称Block RAM或简称为BRAM)来生成。BRAM 由一定数量固定大小的存储块构成的。

1.2为什么要用FIFO

FIFO是系统的缓冲单元,如果没有FIFO存储器,整个系统就不可能正常工作。
FIFO的功能可以概括为
(1)对连续的数据流进行缓存,防止在进机和存储操作时丢失数据;
(2)数据集中起来进行进机和存储,可避免频繁的总线操作,减轻CPU的负担;
(3)允许系统进行DMA操作,提高数据的传输速度。这是至关重要的一点,如果不采用DMA操作,数据传输将达不到传输要求,而且大大增加CPU的负担,无法同时完成数据的存储工作。

FIFO可以用来跨时钟域进行数据传输(FIFO写满再读) (图片来自BV1ci4y1T7KY
在这里插入图片描述
FIFO可以用来在不同不同宽度的数据接口间进行数据传输
在这里插入图片描述
在这里插入图片描述

1.3FIFO的分类

FIFO可分为同步FIFO和异步FIFO,顾名思义,同步FIFO 是指读时钟和写时钟为同一个时钟,在时钟沿来临时同时发生读写操作;异步FIFO 指读写时钟不一致,读写时钟互相独立。

2.异步FIFO的工作原理

随着现代集成电路芯片设计规模的不断扩大,一个系统中往往含有数个时钟。多时钟域带来的一个问题就是,如何设计异步时钟之间的接口电路。异步FIFO是解决这个问题的一种简便方案。使用异步FIFO可以在两个不同时钟系统之间快速方便地传输实时数据。在网络接口、图像处理等方面,异步FIFO得到了广泛的应用。

2.1FIFO的结构

在这里插入图片描述
上图中的信号解释如下:
wfull: 满标志, 表示FIFO已经满,不能再写入数据。
rempty:空标志,表示FIFO已经空,不能再读取数据。

wclk: 写时钟
rclk: 读时钟

winc: 写使能
rinc: 读使能

rptr: 读指针,总是指向当前要被读出的数据,复位时,指向第1个单元(编号为0)
wptr: 写指针,总是指向下一个将要被写入的单元,复位时,指向第1个单元(编号为0)

wdata:写数据
rdata: 读数据

wrst_n: 写复位
rrst_n:读复位

wq2_rptr: 输出到全判断模块的格雷码地址指针
rq2_wptr: 同步模块传入的写指针

FIFO的重要参数
FIFO的宽度:FIFO一次读写操作的数据位数(比如一次读/写8位二进制数);
FIFO的深度:FIFO可以存储多少个N位的数据(如果宽度为N)

如果觉得上图太过复杂,可以看看下图[6]:
在这里插入图片描述

2.2FIFO的工作流程

从以上两张图片中可以得知,FIFO是一块双端口的内存。一个端口由发送者控制,用于写入数据;另一个端口由接收者控制,用于读取数据。发送者和接收者各自维护一套FIFO的状态: empty、full,然后根据状态进行存取数据的操作。

FIFO的状态是由读指针和写指针之间的运算和比较决定的。但这两个指针处于不同的时钟城,不能在一个时钟域直接使用另一个时钟域的指针,所以需要把这两个指针同步到对应的时钟域再进行比较。

当地址以二进制来记录表示时:
当有16个数据时,需要有4个bit来表示地址,这样2^4==16,才能将地址和数据一一对应起来。但是下图中为什么有5个二进制位呢?因为我们需要有一个进位来辅助我们判断FIFO的状态,是读空了还是写满了。故而地址指针位数 = 表示数据的二进制位数 + 1,以下图为例则为4 + 1 = 5

对于FIFO而言,当FIFO为空时,写指针和读指针完全相等(00000==00000),表示FIFO为空,然后不断地向FIFO中写入数据,写指针不断自增1,直至将FIFO写满(wptr = 10000, rptr=00000,读指针追上了写指针)。FIFO写满后,便不能再写入,读指针开始不断地读数据,读指针不断自增1,当将FIFO读空后(wptr = 10000, rptr=10000),写指针自下而上不断重新写入,直至写满(wptr = 00000, rptr=10000),循环往复。
在这里插入图片描述
上图来自BV1DF411u7DA,可以去看看小姐姐录的课程,讲的很不错。

满空信号的生成:
1、读空信号是在读时钟域生成的,从而保证能够实时的没有延迟的确定读空;
当读空发生时,是读指针追赶上写指针,两个指针值相同(包括最高位),此时其格雷码也是相同的。

2、写满信号是在写时钟域生成的,从而保证能够实时的没有延迟的确定写满;
当写指针追赶上读指针的时候发生,此时两个指针的二进制计数器的低(n-1)位相同,最高位不同。但是由于扩展了格雷码,而对于n位格雷码,其(n-1)位是关于中间值镜像对称的。

简单地直接把二进制的指针从一个时钟域锁存到另一个时钟域,这样是有问题的。例如写指针当前位置是4’b0111, 把它同步到接收者的时钟域,在接收者锁存的时候,如果写指针变为4’b1000,那么接收者实际锁存到的值可能是4’0000~4’b1111 之间的任意一一个, 因为在锁存时每一位都在变化着。

为了解决同步指针的问题,就要使用格雷码传递指针。因为对格雷码每次做加1或减1操作时只能改变其中的一位,所以对格雷码使用同步器,格雷码的每次改变只会导致一根信号线发生改变。于是就消除了数据通过同步器时的错误情况。在传递指针时,要把二进制的指针变换到格雷码的指针并保存到寄存器中,在新时钟域同步后,再把格雷码的指针变换到二进制的指针,最后计算比较生成FIFO的状态。

3.FIFO的空满判断

3.1亚稳态介绍及亚稳态的危害[8]

亚稳态指的是FPGA内部触发器的输出未知或不确定的状态。
在这里插入图片描述
左边这是一个触发器的模型。假设一开始输入D的逻辑电平为0,时钟CLK的逻辑电平为0,A节点上的逻辑电平为1,B节点上的逻辑电平为0。此时如果输入D从0变到1,按照我们学过的数电模电知识,A也应该相应的从1变到0,B应该相应的从0变到1,但是要注意逻辑0与逻辑1只是模拟值的一个区间,这个跳变不是瞬间完成的,而且跳变要经过中间未定义的模拟电平值。下面是一个TTL模拟电平与数字电平的示例,2V5V代表逻辑电平1,0V0.8V代表逻辑电平0,中间的0.8V~2V没有定义,不妨称之为“模糊电平”。
在这里插入图片描述
如果此时CLK突然产生了一个上升沿,“时钟门”相当于就被关闭了(如右边所示),A与B由于还没完成跳变,就处在了“模糊电平”,需要一定的时间才能恢复到明确定义的逻辑电平,此时就引起了亚稳态。
在这里插入图片描述
上面是对这个触发器的仿真结果。横轴是仿真时间,纵轴是仿真的电压值。输入的跳变边缘分别以100ps为步长进行移动,可以非常明显的看到,一方面输出会有较长时间处于不明确的电压值,另一方面,最后的输出结果也是不确定的。
可以看出来,由于输入与clk的变化不同步而导致了亚稳态。所以从宏观角度来说,亚稳态的产生是由于输入的异步性。

在这里插入图片描述
[公式] :表示的是在时钟上升沿到来前数据需要保持稳定的最小时长。
[公式] : 表示的是在时钟上升沿到来后数据需要保持稳定的最小时长。
[公式] ​(clock−to−output):表示的是在时钟到来,这么长时间的延迟之后寄存器输出的数据就可以被读取了(即此时的输出数据是稳定的)
正常情况下,在时钟边沿到来之前,触发器的输入要维持一个最小的时长[公式],同样的也要在时钟边沿到来之后维持一个最小的时长[公式],并且要想得到一个平稳的正确的输出,要在时钟上升沿到来后等待一个[公式]。图中的时序就明显不符合这个要求,在 [公式] 还没结束的时候时钟就产生了时钟上升沿,导致的明显结果就是信号输出变化稳定到固定的0或者1状态的时间远超过了寄存器的固有 [公式] ,如果输出信号输入到的后级在进行信号捕获时,信号的输出变化还没有稳定,那么就会对后级产生影响,这样就会对整个电路系统带来不可预知的危害。

3.2FIFO为什么要使用格雷码代替二进制

3.2.1格雷码与二进制的转换

格雷码(Gray Code) 在数电里大家应该都学过,很熟悉了。
所谓格雷码就是任意相邻两个数字的代码只有一位二进制数不同的编码。
下图是维基百科上4位二进制数的二进制编码及格雷码编码的表格:

在这里插入图片描述
普通n位2进制数转换为n位格雷码(最低位下标由0开始)
1.最高位不变,G(n-1) = B(n-1)

  • 7
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值