异步FIFO IP核的亚稳态处理

异步FIFO IP核的亚稳态处理

转载请注明出处:http://blog.csdn.net/kevin_hee/article/details/78075853


一、FIFO原理

亚稳态是FPGA设计中永恒的话题,也是很多时序问题的根源,即使是官方的IP核,有些也不能很好的避免亚稳态的产生。

在实际工程中,就遇到了异步FIFO IP核亚稳态带来的困扰,这里简单的分析原因并给出解决方法。

亚稳态绝大多数出现在异步时域关系中,而异步FIFO是经常使用的一种存储队列,它的优点就是可以用来做大通道数据的跨时域处理。但是只要涉及到跨时钟域,亚稳态的危险也就跟着出现。

 

Ø 这里简单分析下为什么异步FIFO会出现亚稳态(这里的分析并不代表IP核的设计就是这种形式,实际上异步FIFO的设计有很多技巧,这里的分析只是大概的原理分析)

1. FIFO本质上是对FPGA片内RAM做了一层协议封装,这些片内RAM可以配置成单口、双口RAM,也可以配置成先进先出队列FIFO

2.对于使用FIFO IP核的用户来说比较重要的信号包括输入输出接口、读写时钟、读写请求、空满标志和usedw。而如果涉及到FIFO底层,必定会包括读写地址,但是地址做为FIFO内部控制信号,是不对用户开放的。

3.FIFO为空的时候,读写地址,或者叫做读写指针是相同的,都指向同一个地址(不一定是0地址)。当用户往FIFO进端写入数据的时候,写地址不断加1。当写地址快赶上读地址的时候,判断FIFO为满,不能再写。

4.当用户往FIFO出端读出数据的时候,读地址不断加1。当读地址快赶上写地址的时候,判断FIFO读空,不能再读。

5.对用户来说,在控制FIFO读写的时候比较重要的三个信号---fullemptyusedw都是要通过比较读写地址来产生的。

 

二、亚稳态产生的原因

假设例化了如下FIFO模型(rdclk=80MHz  wrclk=50MHz)

 

很多时候设计中需要在判断FIFO中有数据后,再将数据读出来。如何判断FIFO中有数据了呢?可以使用两个接口信号,一个是rdempty,另一个是rdusedw信号。

rdclkwrclk属于异步时钟,在使用rdempty信号(判断读端空标识)来进行读控制时,会有两种情况值得注意。

Ø 假设写操作相对于读写时钟来说是很慢的,比如在UART通信缓存FIFO中,在写端很久才有数据进入FIFO。这个时候,使用rdempty信号来控制读操作出现亚稳态的几率非常低,可以忽略。

 

Ø 同样假设写操作相对于读写时钟来说是很快的,比如在视频处理中使用的缓存FIFO,视频源信号源源不断的进入FIFO做跨时钟域处理

因为rdempty信号是通过比较FIFO内的读写地址来判定的,这两个地址属于不同时钟域。所以如果读端正在判断读写地址,这个时候写端写使能有效,写地址加1,就有可能出现亚稳态。

亚稳态如何表现出来的呢?实际工程中,可能有如下代码,在rdempty==0(判断FIFO非空)的情况下有效读请求:

always@(posedge clk or negedge rst_n)

begin

        if(!rst_n)begin

            rd_req <= 1'b0;

        end

        //判断FIFO非空,有效读请求

        else if(rdempty==1'b0)begin

            rd_req <= 1'b1;

        end

        else begin

            rd_req <= 1'b0;

        end

end

如果FIFO此时只剩下一个数据,通过rdempty判断FIFO非空,有效rd_req读请求信号。一个读周期后应该通过rdempty判断FIFO为空,无效rd_req读请求信号。

但是实际情况是,一个读周期后通过rdempty判断FIFO还是不为空,rd_req读请求信号继续有效,这样就发生了错误。

可能原因就是FIFO内部通过比较读写地址产生rdempty信号的时候,这时写地址正在加1,导致建立或保持时间违例,产生亚稳态,使得rdempty信号输出一个不正确的结果。

 

三、解决亚稳态的方法

为了避免出现这样的问题,可以使用另一个读端接口信号---rdusedw信号来计数到一定量后,再进行突发读操作。

reg [3:0] rd_req_cnt;

always@(posedge clk or negedge rst_n)

begin

   if(!rst_n)begin

      rd_req <= 1'b0;

      rd_req_cnt <= 4'd0;

   end

   else if(rd_req_cnt == 4'd10) begin

      rd_req <= 1'b0;

      rd_req_cnt <= 4'd0;

   end

   else if(rd_req_cnt > 4'd0) begin

      rd_req_cnt <= rd_req_cnt+4'd1;

      rd_req <= 1'b1;

    end

    //计数到10个后,进行突发读操作

   else if( rdusedw >= 10'd10) begin

      rd_req <= 1'b1;

      rd_req_cnt <= rd_req_cnt+4'd1;

   end

   else begin

      rd_req <= 1'b0;

      rd_req_cnt <= 4'd0;

   end

   end

 

rdusedw信号也是通过比较读写地址来产生的,同样的,这个信号也会遭遇亚稳态的风险。但是因为我们的设计是通过判断rdusedw达到一定量后再有效rd_req读请求信号进行一次突发读操作,所以这将rdusedw信号产生亚稳态后所带来的影响降到最低。实际工程中表明这种简单的设计方法可以有效稳定的处理FIFO跨时钟域的亚稳态问题。

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
异步FIFO IP核的调用中,首先需要进行FIFO IP核的参数配置。然后,编写顶层模块的FIFO调用代码。这个代码示例如下: module fifo ( input wire sys_clk, input wire sys_clk2, input wire [7:0 pi_data, input wire rd_req, input wire wr_req, output wire empty, output wire full, output wire [7:0 po_data, output wire [7:0 usedw ); dcfifo_8x256 dcfifo_8x256_inst ( .clock1 (sys_clk), .clock2 (sys_clk2), .data (pi_data), .rdreq (rd_req), .wrreq (wr_req), .empty (empty), .full (full), .q (po_data), .usedw (usedw) ); endmodule 在这个顶层模块的FIFO调用代码中,我们使用了异步FIFO IP核,其中包括两个时钟信号:sys_clk和sys_clk2。同时,还有输入信号,如写请求信号(wr_req)、读请求信号(rd_req)和输入数据信号(pi_data),以及输出信号,如空状态信号(empty)、满状态信号(full)、输出数据信号(po_data)和已使用字节信号(usedw)。通过这个FIFO调用代码,可以实现对异步FIFO IP核的调用。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [FIFO IP 核的调用](https://blog.csdn.net/ziyouruf/article/details/123862569)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *2* [FPGA中FIFO IP核配置与调用](https://blog.csdn.net/m0_72885897/article/details/128649678)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值