异步fifo_IC基础课:异步FIFO的"假"满空和"真"满空

今天讲一个非常基本的知识,关于异步FIFO的,同时也是不常被人注意的。

我们都知道异步FIFO有两个部分,写部分和读部分,分别在两个时钟域里面执行。比如说写操作在Write_Clk时钟下进行,读操作在Read_Clk时钟下进行。Write_Clk和Read_Clk这两个时钟的频率和相位没有任何关系。

异步FIFO别的都很简单 。对于写操作,无非是在写信号下产生累加的写地址Write_Pointer,然后用这个地址往存储器写数。在读信号下产生累加的读地址Read_Pointer,然后用这个地址从存储器取数据。

唯一的难点是:满和空的产生。对于写操作,得判断FIFO是不是满了,满了就不能继续往里面写,不然就会覆盖还没取走的数据。对于读操作,得判断FIFO是不是空了,空了就不能接着取,不然旧的数据会被取多次。

满和空的产生,是拿读和写的Pointer做比较得到的。问题在于:写操作下的Write_Pointer和读操作下的Read_Pointer属于不同的时钟域的信号。两个不同的时钟域的信号是不能直接做运算的,需要同步到同一个时钟域之后才行。

异步信号不能直接运算的原因,是因为会产生很多中间过渡毛刺,这些毛刺被下一级采样之后的输出是不确定的。比如说,下图的一根信号,虽然经过一些波动最终稳定到了高电平,但是如果你的采样点在时刻2,那么就会错误的得到一个低电平。

8bfae9fc4952c5bc41e526738a452fdd.png

当然,也有些变态的异步FIFO,会拿格雷码的Read_Pointer和Write_Pointer在异步时钟下直接进行比较,得到的Full和Epmty信号再通过"去亚稳态"得到稳定的输出值。这种方法理论上也是可行的,但是我们不讲。

1,标准范式的异步FIFO

我们讲最通用的,标准范式的异步FIFO。

87df71a3912174c001e67581300326ad.png

标准范式的异步FIFO结构如上图,假设FIFO的深度为16,地址范围为0~15。那么读写地址都是5bit,即WR_Pointer[4:0],RD_Pointer[4:0],其中最高bit是扩展位。Pointer取值范围是0~31,要比FIFO地址多一倍。这么做的原因在于:满和空本质上是读和写指向了FIFO的同一个存储单元,但是“空”是读指针追上了写指针,“满”是写指针超过了读指针整整一圈。怎么区别是谁追上了谁?最高位就是干的这个。

如果两个Pointer低位全等,最高位不等,那就是“满”;

如果两个Pointer低位全等,最高位也相等,那就是“空”。

2,假满空的产生

将WR_Pointer通过CDC同步之后,送到读时钟域,得到WR_Pointer_syn(上图的蓝线),然后再将其和RD_Pointer作比较,就可以得到“空”信号:

assign Empty = (WR_Pointer_syn[4:0]== RD_Pointer[4:0]);

将RD_Pointer通过CDC同步之后,送到写时钟域,得到RD_Pointer_syn(上图紫线),然后将其和WR_Pointer作比较,就可以得到满信号:

assign Full = (WR_Ponter[4] != RD_Pointer_syn[4]) && (WR_Ponter[3:0] == RD_Pointer_syn[3:0]);

接下来就是重点了。

上面的代码得到的满和空其实是假满空,并非真正的满空。原因在于,CDC同步本身也是需要开销的,一般简单的两级同步器需要目标时钟域两个T。当我们判断满信号的时候,我们用的是WR_Pointer和同步过来的RD_Pointer_syn做的比较。RD_Pointer_syn要比真正的RD_Pointer要滞后,导致判满的逻辑并不完全准确。当FIFO接近满的时候,Full信号就会为1,从而阻止对FIFO继续写入。

同理,Empty信号也不准确。当FIFO接近空,但是实际可能还没空的时候,Empty信号就会为1,从而阻止对FIFO数据的读取。

这种假满空并不会导致FIFO的行为出错,只会导致FIFO的效率略微有下降,相当于FIFO的层数少了那么一两层。本质上对FIFO起到了过保护的作用。

3,真满空的产生

那么怎么得到真满空?也不难。

之前我们是在写时钟域判断“满”信号,在读时钟域判断“空”信号,得到了“假”满空。

如果我们在写时钟域判断“空”信号,在读时钟域判断“满”信号,得到的就是“真”满空!

代码如下:

assign Empty_Real = (WR_Pointer[4:0] == RD_Pointer_syn[4:0]);

assign Full_Real = (RD_Pointer[4] != WR_Pointer_syn[4]) && (RD_Pointer[3:0] == WR_Pointer_syn[3:0]);

原理是这样的:

假如说,在写时钟域,通过滞后的RD_Pointer_syn都得到了“空”信号,那说明实际的RD_Pointer必然真的赶上了WR_Pointer,所以FIFO此刻绝对空了。

在读时钟域,通过滞后的WR_Pointer_syn都得到了“满”信号,那说明实际的WR_Ponter必然真的超过了RD_Pointer一圈,所以FIFO此刻绝对满了。

这个“真”满空信号,用到的时候并不多。但是理解“真”满空和“假”满空,是理解异步FIFO的基础,也是灵活运用异步FIFO的基础。

欢迎大家关注我的微信公众号:半导学社。

  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
异步FIFO_gray code异步FIFO的多种约束方式包括以下几种: 1. 读写时钟约束:异步FIFO_gray code异步FIFO需要读写时钟进行同步操作。读写时钟之间应满足一定的时序关系,以保证数据的正确传输和读写的一致性。通常情况下,写时钟应该在读时钟的上升沿之前完成写入操作,以防止读取到不稳定或无效的数据。 2. 数据宽度约束:异步FIFO_gray code异步FIFO的数据输入和输出宽度应相等,即读写数据的位数应一致。如果数据宽度不匹配,可能会导致数据丢失或错误读取。 3. 读写顺序约束:异步FIFO_gray code异步FIFO的读写操作需要按照一定的顺序进行。通常情况下,写操作应在读操作之前完成,以确保数据的正确读取。同时,读写操作之间需要插入适当的等待时间以保证数据的稳定性。 4. 读写使能约束:异步FIFO_gray code异步FIFO的读写使能信号需要在时钟上升沿进行操作。写使能信号应在写入数据之前启用,读使能信号应在读取数据之前启用。同时,读使能和写使能信号之间需要插入适当的延时以保证数据的正确传输和读写的一致性。 5. 异步FIFO_gray code同步约束:异步FIFO_gray code异步FIFO的读写操作需要通过同步电路进行同步。异步FIFO_gray code异步FIFO通常采用双同步FIFO架构,即读写操作分别采用不同的时钟,但通过同步电路进行数据传输和同步操作。 总之,异步FIFO_gray code异步FIFO在设计和实现时需要考虑时钟约束、数据宽度约束、读写顺序约束、读写使能约束以及异步同步约束等多种约束方式,以确保数据的正确传输和读写的一致性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值