异步FIFO(格雷码实现)

异步FIFO(格雷码实现)


一、FIFIO简介

  FIFO是一种现先进先出的数据缓冲器,特点是没有外部的读写地址。由于没有外部的地址信号,所以只能顺序的读写,而不能跳读。FIFO的读写是根据满和空信号设计写使能和读使能来写/读FIFO,当FIFO满的时候不可以往里面写、当FIFO空的时候不能读数据。读FIFO时,内部的读指针自动的加一,当写FIFO时写指针自动的加一。

二、异步FIFO的用途

1、使用异步FIFO可以在两个不同的时钟域之间快速而方便的传输数据,起到跨时钟域处理的作用。经常用于处理跨时钟域的问题。
2、对于不同宽度的数据接口也可以采用FIFO进行缓冲,如8位输入,16位输出。(注:本文只简介输入输出位宽相同的情况)

三、FIFO的常见参数

wfull: 满标志, 表示FIFO已经满,不能再写入数据。
rempty:空标志,表示FIFO已经空,不能再读取数据。
wclk: 写时钟
rclk: 读时钟
winc: 写使能
rinc: 读使能
wdata:写数据
rdata: 读数据
wrst_n: 写复位
rrst_n:读复位

四、FIFO满空标志的产生

  FIFO设计的关键是如何产生可靠的读写指针和满空信号。


  判空:读指针追上写指针的时候,两者相等,为空。
判空和使用二进制一样,只需判断读写指针是否完全相同即可。

  判满:写指针追上读指针的时候,两者相等,为满。
图中使用格雷码,最高位是辅助判断是否空满(实际深度为8)。如:当写指针为1000,读指针为0100,则写指针超过读指针一圈,写满状态。因此判断其是否写满,需判断高两位是否相反,剩下的是否相同。

五、异步FIFO的模块图
在这里插入图片描述
六、异步FIFO实现代码

module afifo 
#(
    parameter WSIZE = 8,
    parameter DSIZE = 16
)
(
    input   [WSIZE - 1:0]wdata,
    input   wclk,
    input   winc,
    input   wrst_n,

    input   rclk,
    input   rinc,
    input   rrst_n,

    output  wfull,
    output  rempty,
    output  [WSIZE - 1:0]data
);
    reg     [WSIZE - 1:0] mem [0:DSIZE - 1];
    wire    [3:0] waddr;
    wire    [3:0] raddr;
    reg     [4:0] wptr;
    reg     [4:0] rptr;
    reg    rempty_val;
    reg    wfull_val;
    
    assign data = mem [raddr];
    always @(posedge wclk) begin
        if(winc && !wfull)begin
            mem[waddr] <= wdata;
        end
    end

    reg     [4:0]wbin;
    always @(posedge wclk or negedge wrst_n) begin
        if(!wrst_n)begin
            wbin <= 5'b0;
        end
        else if(winc && !wfull) begin
            wbin <= wbin + 1'b1;
        end        
    end
    assign  waddr = wbin[3:0];
    reg    [4:0]wgray;
    always @(posedge wclk or negedge wrst_n) begin
        if (!wrst_n) begin
            wgray <= 5'b0;
        end
        else begin
            wgray <= (wbin >> 1) ^ wbin;
        end
    end

    always @(posedge wclk or negedge wrst_n) begin
        if (!wrst_n) begin
            wptr <= 5'b0;
        end
        else begin
            wptr <= wgray;
        end  
    end

    reg     [4:0]wptr_1;
    reg     [4:0]wptr_2;
    
    always @(posedge wclk or negedge wrst_n) begin
        if(!wrst_n)begin
            {wptr_2 , wptr_1} <= 10'd0;
        end
        else begin
            {wptr_2 , wptr_1} <= {wptr_1 , rptr};
        end
    end   
    assign  wfull = {~wptr_2[4:3],wptr_2[2:0]} == wgray;

    reg     [4:0]rbin;
    always @(posedge rclk or negedge rrst_n) begin
        if (!rrst_n) begin
            rbin <= 5'b0;
        end
        else if(rinc && !rempty) begin
            rbin <= rbin + 1'b1;
        end
    end
    assign  raddr = rbin[3:0];
    reg     [4:0]rgray;
    always @(posedge rclk or negedge rrst_n) begin
        if(!rrst_n)begin
            rgray <= 5'b0;
        end
        else begin
            rgray <= (rbin >> 1) ^ rbin;
        end
    end
    always @(posedge rclk or negedge rrst_n) begin
        if(!rrst_n)begin
            rptr <= 5'b0;
        end
        else begin
            rptr <= rgray;
        end
    end

    reg     [4:0]rptr_1;
    reg     [4:0]rptr_2;

    always @(posedge rclk or negedge rrst_n) begin
        if(!rrst_n)begin
            {rptr_2 , rptr_1} <= 10'd0;
        end
        else begin
            {rptr_2 , rptr_1} <= {rptr_1 , wptr};
        end
    end
    
    assign rempty = rptr_2 == rgray;
    
endmodule

tb文件

`timescale 1ns / 1ps
module tb_afifo(
    );
    reg     wclk;
    reg    [7:0]wdata;
    reg     winc;
    reg     wrst_n;
    
    reg     rclk;
    reg     rrst_n;
    reg     rinc;
    
    wire    wfull;
    wire    rempty;
    wire    [7:0]data;
    integer i = 0;
    localparam CYCLE = 20;
    localparam CYCLE1 = 40;
    
    initial begin
        wclk = 0;
        forever
        #(CYCLE/2)
        wclk = ~wclk;
    end
    
    initial begin
        rclk = 0;
        forever
        #(CYCLE1/2)
        rclk = ~rclk;
    end
    
    initial begin
        wrst_n = 1;
        #2;
        wrst_n = 0;
        #(CYCLE*3);
        wrst_n = 1;   
    end
    
    initial begin
        rrst_n = 1;
        #2
        rrst_n = 0;
        #(CYCLE*3);
        rrst_n = 1;
    end
    always@(posedge wclk or negedge wrst_n)begin
        if(!wrst_n)begin
            i <= 0;
        end
        else if(!wfull)begin
            i <= i+1;
        end
        else begin
            i <= i;
        end
    end
    
    afifo u_afifo(
    .wclk   (wclk),
    .wdata  (wdata),
    .winc   (winc),
    .wrst_n (wrst_n),
    
    .rclk   (rclk),
    .rrst_n (rrst_n),
    .rinc   (rinc),
    
    .wfull  (wfull),
    .rempty (rempty),
    .data   (data)
    
    );
      
     always  @(posedge wclk or negedge wrst_n)begin
         if(wrst_n==1'b0)begin
            i <= 0;
         end
         else if(!wfull)begin
            i = i+1;
         end
         else begin
            i <= i;
         end
         end

     always  @(rempty or rrst_n)begin
        if(rrst_n==1'b0)begin                  
            rinc = 1'b0;
        end
        else if(!rempty)begin                
            rinc = 1'b1;
        end
        else
            rinc = 1'b0;
        end
            
    always@(wfull or wrst_n)begin
    	if(wrst_n)
    		winc = 1'b0;
    	else if(!wfull)
    		winc = 1'b1;
        else
            winc = 1'b0;
    end
    always@(*)begin
      if(!wfull)
        wdata= i;
      else
        wdata = 0;
    end

endmodule

七、异步FIFO仿真效果
在这里插入图片描述

参考文献:
C.E. Cummings, Simulation and Synthesis Techniques for Asynchronous FIFO Design, SNUG 2002 .User Papers, 2002.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值