异步FIFO空满判断逻辑探讨

异步FIFO的基本概念很简单 。对于写操作,是在写信号下产生累加的写地址Write_Pointer,用这个地址往存储器写数。在读信号下产生累加的读地址Read_Pointer,用这个地址从存储器取数据,原则就是first in first out

FIFO的核心难点是:满和空的产生。对于写操作,得判断FIFO是不是满状态,满了就不能继续往里面写数据,不然就会覆盖还没取走的数据。对于读操作,得判断FIFO是不是空状态,空了就不能接着取数据,不然旧的数据会被取多次。满和空的产生,是拿读和写的Pointer做比较得到的。问题在于:写操作下的Write_Pointer和读操作下的Read_Pointer属于异步时钟的信号。两个异步时钟的信号进行处理,需要同步到同一个时钟域。一般把读指针同步到写时钟域,写时钟域下的写指针和同步读指针作比较,以生成”FULL信号;把写指针同步到读时钟域,读时钟域下的读指针则和同步写指针作比较,以生成”EMPTY信号。多比特的读写指针一般采用格雷码编码后进行同步处理后,通过简单的双触发器进行同步操作,可以极大减少传输出现亚稳态而导致错误的概率。

WR_Pointer通过CDC同步之后,送到读时钟域,得到WR_Pointer_syn,然后再将其和RD_Pointer作比较,就可以得到信号,下面的例子是FIFO深度为16Pointer拓展1bit ,总计5bit,且通过Gray码跨时钟域后需要转换成Binary码后才能比较。

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]);

上面的空满判断逻辑得到的满FULL和空EMPTY其实是假满空或者叫做虚满空,并非真正的满空。原因在于读写指针的CDC同步本身也是需要开销的,一般简单的两级同步器需要目标时钟域两个CYCLE。当我们判断满FULL信号的时候,我们用的是WR_Pointer和同步过来的RD_Pointer_syn做的比较。RD_Pointer_syn要比真正的RD_Pointer要滞后,导致判满的逻辑并不完全准确。当FIFO接近满的时候,Full信号就会为1,从而阻止对FIFO继续写入。同理,Empty信号也不准确。当FIFO接近空,但是实际可能还没空的时候,Empty信号就会为1,从而阻止对FIFO数据的读取。

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

假如Gary码直接进行比较,其空满判断的逻辑脚本如下:

wire [FIFO_DEPTH :0]  wr_addr_glay_wire;

assign wr_addr_glay_wire = (wr_addr_bin_wire>>1)^wr_addr_bin_wire;

always @(posedge wr_clk) begin

       if(!wr_rst_n)

              {rd_addr_glay_r2,rd_addr_glay_r1} <= 0;

       else

              {rd_addr_glay_r2,rd_addr_glay_r1} <= {rd_addr_glay_r1,rd_addr_glay};

end

       wire wr_full_w;

       wire [FIFO_DEPTH :0] wr_addr_glay_wire1;

       assign wr_addr_glay_wire1={~wr_addr_glay_wire[FIFO_DEPTH:FIFO_DEPTH-1],wr_addr_glay_wire[FIFO_DEPTH-2:0]};//MSB与次高位取反,

       assign wr_full_w = (wr_addr_glay_wire1==rd_addr_glay_r2);

       always @(posedge wr_clk) begin

              if(!wr_rst_n)

                     wr_full <= 0;

              else 

                     wr_full <=  wr_full_w;

       end

//空判断EMPTY方法:Gray码与Binary码一致,全部bit相同

assign rd_empty_wire =  (wr_addr_glay_r2== rd_addr_glay_wire); 

最后补充一下FIFO的深度计算:

FIFO写入时钟速率为800M,读出的时钟为250MHz
(1)若100个时钟写入80个数据,一个时钟读取一个数据,求FIFO最小深度(110)
(2)若100个时钟写入80个数据,三个时钟读两个数据,求FIFO的最小深度(127)

FIFO深度计算公式:

当读时钟有效占比为1时,计算公式如下:

FIFODEPTH>(WRITE_FS-READ_FS)*Burst_LenWRITE_FS

当读时钟有效占比为xy时,例子中为2/3,计算公式如下:

FIFODEPTH>Burst_Len-Burst_Len*xy*READ_FSWRITE_FS

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值