设为首页 加入收藏

TOP

异步fifo的设计(FPGA)(二)
2017-10-10 12:20:21 】 浏览:8768
Tags:异步 fifo 设计 FPGA
的时钟域,所以在比较之前需要先将读写指针进行同步处理,
将写指针同步到读时钟域再和读指针比较进行FIFO空状态判断,因为在同步写指针时需要时间,而在这个同步的时间内有可能还会写入新的数据,因此同步后的写指针一定是小于或者等于当前实际的写指针,所以此时判断FIFO为空不一定是真空,这样更加保守,一共不会出现空读的情况,虽然会影响FIFO的性能,但是并不会出错,同理将读指针同步到写时钟域再和写指针比较进行FIFO满状态判断,同步后的读指针一定是小于或者等于当前的读指针,所以此时判断FIFO为满不一定是真满,这样更保守,这样可以保证FIFO的特性:FIFO空之后不能继续读取,FIFO满之后不能继续写入。 总结来说异步逻辑转到同步逻辑不可避免需要额外的时钟开销,这会导致满空趋于保守,但是保守并不等于错误,这么写会稍微有性能损失,但是不会出错。
举个例子:大多数情形下,异步FIFO两端的时钟不是同频的,或者读快写慢,或者读慢写快, 慢的时钟域同步到快的时钟域不会出现漏掉指针的情况,但是将指针从快的时钟域同步到慢的时钟域时可能会有指针遗漏举个例子以读慢写快为例,进行满标志判断的时候需要将读指针同步到写时钟域,因为读慢写快,所以不会有读指针遗漏,同步消耗时钟周期,所以同步后的读指针滞后(小于等于)当前读地址,所以可能满标志会提前产生,满并非真满。进行空标志判断的时候需要将写指针同步到读指针 ,因为读慢写快,所以当读时钟同步写指针 的时候,必然会漏掉一部分写指针,我们不用关心那到底会漏掉哪些写指针, 我们在乎的是漏掉的指针会对FIFO的空标志产生影响吗?比如写指针从0写到10,期间读时钟域只同步捕捉到了3、5、8这三个写指针而漏掉了其他指针。当同步到8这个写指针时,真实的写指针可能已经写到10 ,相当于在读时钟域还没来得及觉察的情况下,写时钟域可能偷偷写了数据到FIFO去,这样在判断它是不是空的时候会出现不是真正空的情况,漏掉的指针也没有对FIFO的逻辑操作产生影响。
 
4、多位二进制码如何转化为格雷码
二进制码转换成二进制格雷码,其法则是保留二进制码的最高位作为格雷码的最高位,而次高位格雷码为二进制码的高位与次高位相异或,而格雷码其余各位与次高位的求法相类似。 
  转换示意图
 
我再换种更简单的描述 
二进制数                                       1 0 1 1 0
二进制数右移1位,空位补0               1 0 1 1
异或运算                                       1 1 1 0 1  
这样就可以实现二进制到格雷码的转换了,总结就是移位并且异或,verilog代码实现就一句:assign wgraynext = (wbinnext>>1) ^ wbinnext;
是不是非常简单。
 

三、代码解析
异步FIFO的信号接口:
wclk  wrst_n  winc wdata //写时钟、写复位、写请求、写数据     这几个与写有关的全部与wclk同步
rclk  rrst_n    rinc   rdata //读时钟、读 复位、读 请求、读 数据    这几个与读有关的全部与rclk同步
wfull                              //写满  与wclk同步
rempty                          // 读空 与rclk同步
本次代码共分为6个module
1、fifo.v  是顶层模块,作用是将各个小模块例化联系起来
module fifo
#(
  parameter DSIZE = 8,        
  parameter ASIZE = 4
 ) 
 (
     output [DSIZE-1:0] rdata,  
     output             wfull,  
     output             rempty,  
     input  [DSIZE-1:0] wdata,  
     input              winc, wclk, wrst_n, 
     input              rinc, rclk, rrst_n
 );

  wire   [ASIZE-1:0] waddr, raddr;  
  wire   [ASIZE:0]   wptr, rptr, wq2_rptr, rq2_wptr;
// synchronize the read pointer into the write-clock domain
  sync_r2w  sync_r2w
  (
                    .wq2_rptr    (wq2_rptr),
                    .rptr        (rptr    ),                          
                    .wclk        (wclk    ), 
                    .wrst_n      (wrst_n  )  
 );

// synchronize the write pointer into the read-clock domain
  sync_w2r  sync_w2r 
  (
                   .rq2_wptr(rq2_wptr), 
                   .wptr(wptr),                          
                   .rclk(rclk),
                   .rrst_n(rrst_n)
 );

//this is the FIFO memory buffer that is accessed by both the write and read clock domains.
//This buffer is most likely an instantiated, synchronous dual-port RAM. 
//Other memory styles can be adapted to function as the FIFO buffer. 
  fifomem 
  #(DSIZE, ASIZE)
  fifomem                        
  (
      .rdata(rdata), 
      .wdata(wdata),                           
      .waddr(waddr),
      .raddr(raddr),                           
      .wclken(winc),
      .wfull(wfull),                           
      .wclk(wclk)
  );

//this module is completely synchronous to the read-clock domain and contains the FIFO read pointer and empty-flag logic.  
  rptr_empty
  #(ASIZE)    
  rptr_empty                          
  (
      .rempty(rempty),                          
      .raddr(raddr),                          
      .rptr(rptr),
      .rq2_wptr(rq2_wptr),                          
      .rinc(rinc),
      .rclk(rclk),                          
首页 上一页 1 2 3 4 下一页 尾页 2/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Verilog学习笔记简单功能实现(六.. 下一篇Verilog学习笔记简单功能实现(七..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目