【FPGA】异步FIFO学习

发布时间 2023-04-04 22:29:53作者: dacon132

学习FIFO的目的是为了给DDR3读写数据的时候提供缓存!

本来想着看个FIFO  IP核的使用方法算球了,但是理智告诉我不行!得深入了解!毕竟了解了FIFO的原理之后用着能更加得心应手,不是嘛?

推荐一个CSDN上的非常牛逼的大佬:孤独的单刀。文章写的深入浅出,看着非常爽!

传送门:异步FIFO的Verilg实现方法_verilog 异步fifo_孤独的单刀的博客-CSDN博客

 

异步FIFO的作用:

1、用作数据之间的缓存

2、实现两个不同时钟域数据的实时传输

 

FIFO需要解决的关键问题:

在关键的时候产生读空信号和写满信号!(可以牺牲FIFO的性能,但是绝对不能发生错误!)(第一次切实感受到宝贵的工程经验)

细说什么是关键的时候:

这个关键的时候并不是在FIFO中恰好没有数据的时候产生读空信号和FIFO中恰好写满了数据的时候产生写满信号。

其实在FIFO只存在几个数据的时候产生读空信号,这样只会浪费掉FIFO中一点点bit的存储空间,但是绝对不能在已经读空之后再产生读空信号,那样之前产生的信号就是错误的,错误是不允许发生的!(写满信号同理)

 

产生写满和读空信号的方法

1、计数器法(只能用于同步FIFO,异步FIFO中说不清这个计数器属于哪一个时钟)

2、高位拓展法:将地址位拓展一位作为指示位,用来只是是否超过一轮。如果没超过一轮,地址位相等,说明读空;如果超过一轮,地址位相等,说明写满。(当然这是针对正常的二进制编码而言的,如果是格雷码的话,有稍微一点点的差别)

但是在使用高位拓展法的时候需要解决跨时钟域的问题!!!

 

FIFO的实现:

FIFO其实就是两个东西,一片RAM用来存数据,一个读写控制器。数据来了放进去,写地址加1,外面要数据了,给传出去,读地址加1;然后比一比地址,要么读空了,要么写满了。但是呢,异步FIFO在比地址的时候,需要进行跨时钟域信号的同步,在同步的时候呢,为了降低亚稳态出现的概率,所以会将地址转换成格雷码,到此异步FIFO所有的知识点就全部梳理完了。

1、如何产生读空、写满信号(高位拓展法)

2、异步时钟下的信号同步

3、格雷码

 

下面细说跨时钟域的问题:

慢时钟域到快时钟域,打两拍!

需要注意的是打两拍的作用是为了消除亚稳态,打完两拍之后亚稳态消失的概率是90%,而并不能保证采集数据的正确性,亚稳态稳定后的结果是随机的。

快时钟域到慢时钟域,方法:快时钟域脉宽拓展+慢时钟域延时打拍

大体思路:快时钟域下检测到脉冲,将该脉冲转化为高电平,慢时钟域下检测该高电平,反馈给快时钟域检测到了,快时钟域收到反馈,拉低电平。

需要注意的是:连续的快时钟域下的脉冲会使该方法失效,因此快时钟域同步到慢时钟域时必然会发生信号的丢失!

参考代码:https://www.runoob.com/w3cnote/verilog2-fast2slow.html

 

跨时钟域的信号同步特点(被同步的信号会发生延时)根据该特点读写地址同步的方式不同

“写满”的判断:需要将读地址同步到写时钟域,再与写地址判断,读地址慢了几拍不要紧,提前产生写满信号呗

“读空”的判断:需要将写地址同步到读时钟域,再与读地址判断,写地址慢了几拍也不要紧,提前产生读空信号呗

这里体现的就是所谓牺牲FIFO的性能!牺牲的性能是因为信号同步时的延时产生的。

同样的读写时钟域势必会有一个快时钟,一个慢时钟,从快时钟域同步到慢时钟域势必会丢失信号,但是此时丢失信号也没事,即使是丢失了信号,也会保存之前的信号,牺牲掉一部分性能罢了。

 

格雷码:

Verilog实现的格雷码与二进制码的互相转换_格雷码与二进制码的互转_孤独的单刀的博客-CSDN博客

在同步读写地址的格雷码之后,需要进行地址比较,

当最高位和次高位相同,其余位相同是读空

当最高位和次高位不同,其余为相同是写满

 

 

 

哟西!明天跟着单刀学习vivado  fifo  ip核的使用!