异步FIFO的Verilog代码

// *****************************************************************************
// Project Name     : *
// Target Device    : *
// Tool version     : *
// Module Name      : dcfifo
// Description      : Dual Clock First In First Out
// Function         : asynchronous FIFO
// Attention        : The FIFO must be reseted firstly before used
// Version History  : *
// *****************************************************************************
// Engineer         : zyhe
// Date             : 2016-01-01
// Modification     : 1) initial version
// *****************************************************************************
// Engineer         : zyhe
// Date             : 2016-05-01
// Modification     : 1) standard coding style
//                    i_ for input, o_ for output, w_ for wire, r_ for register
// *****************************************************************************
// All rights reserved.
// *****************************************************************************
 
`timescale 1ns / 1ps
 
module dcfifo # (
    parameter   DW      = 8                 , // Data Width
    parameter   AW      = 4                   // Address Width
    ) (
    input               i_wr_rst            , // write reset, active high
    input               i_wr_clk            , // write clock
    input               i_wr_ena            , // write enable
    input       [DW-1:0]i_wr_dat            , // write data
    output  reg         o_wr_ful            , // write full
    input               i_rd_rst            , // read reset, active high
    input               i_rd_clk            , // read clock
    input               i_rd_ena            , // read enable
    output      [DW-1:0]o_rd_dat            , // read data
    output  reg         o_rd_ept              // read empty
    );
 
    reg [DW-1:0]r_2d_mem[0:(1<<AW)-1]; // register for 2D array memory
    wire[AW:0]  w_rd_adr    ; // wire for read address
    reg [AW:0]  r_rd_adr    ; // register for read address
    wire[AW:0]  w_rd_gry    ; // wire for read graycode
    reg [AW:0]  r_rd_gry    ; // register for read graycode
    reg [AW:0]  r_rd_gry_d0 ; // register for read graycode, cross clock domain 1 cycle
    reg [AW:0]  r_rd_gry_d1 ; // register for read graycode, cross clock domain 2 cycle
    wire[AW:0]  w_wr_adr    ; // wire for write address
    reg [AW:0]  r_wr_adr    ; // register for write address
    wire[AW:0]  w_wr_gry    ; // wire for write graycode
    reg [AW:0]  r_wr_gry    ; // register for write graycode
    reg [AW:0]  r_wr_gry_d0 ; // register for write graycode, cross clock domain 1 cycle
    reg [AW:0]  r_wr_gry_d1 ; // register for write graycode, cross clock domain 2 cycle
 
    assign  w_wr_adr = r_wr_adr + (i_wr_ena & ~o_wr_ful);
    assign  w_wr_gry = w_wr_adr ^ (w_wr_adr >> 1);
    assign  w_rd_adr = r_rd_adr + (i_rd_ena & ~o_rd_ept);
    assign  w_rd_gry = w_rd_adr ^ (w_rd_adr >> 1);
    assign  o_rd_dat = r_2d_mem[r_rd_adr[AW-1:0]];
 
    always @ (posedge i_wr_clk)
    begin
        if (i_wr_ena & ~o_wr_ful)
            r_2d_mem[r_wr_adr[AW-1:0]] <= i_wr_dat;
    end
 
    always @ (posedge i_wr_clk)
    begin
        if (i_wr_rst)
        begin
            r_wr_gry <= 0;
            r_wr_adr <= 0;
            r_rd_gry_d0 <= 0;
            r_rd_gry_d1 <= 0;
            o_wr_ful <= 0;
        end
        else
        begin
            r_wr_gry <= w_wr_gry;
            r_wr_adr <= w_wr_adr;
            r_rd_gry_d0 <= r_rd_gry;
            r_rd_gry_d1 <= r_rd_gry_d0;
            o_wr_ful <= (w_wr_gry == {~r_rd_gry_d1[AW:AW-1], r_rd_gry_d1[AW-2:0]});
        end
    end
 
    always @ (posedge i_rd_clk)
    begin
        if (i_rd_rst)
        begin
            r_rd_gry <= 0;
            r_rd_adr <= 0;
            r_wr_gry_d0 <= 0;
            r_wr_gry_d1 <= 0;
            o_rd_ept <= 1;
        end
        else
        begin
            r_rd_gry <= w_rd_gry;
            r_rd_adr <= w_rd_adr;
            r_wr_gry_d0 <= r_wr_gry;
            r_wr_gry_d1 <= r_wr_gry_d0;
            o_rd_ept <= (w_rd_gry == r_wr_gry_d1);
        end
    end
 
endmodule

 

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
异步FIFO是一种在读写时钟不一致的情况下进行数据传输的存储器。与同步FIFO不同,异步FIFO需要使用同步打拍逻辑来进行读写地址的比较,这会导致一定的延时。因此,在异步FIFO中,空状态的指示信号可能存在一定的延迟。如果在延迟期间有新的数据写入FIFO,就会出现空状态指示信号有效,但实际上FIFO中仍存在数据的情况。 在Verilog中,可以使用一些方法来实现异步FIFO的设计。异步FIFO的设计需要考虑以下几个方面: 1. FIFO的大小:确定FIFO所能容纳的数据量,包括数据位宽和深度。 2. 读写指针:使用两个指针来追踪读写操作的位置。读指针指向最早写入的数据,写指针指向最新写入的数据。 3. 读写逻辑:通过判断读写指针的状态来实现读写操作。读操作会使读指针向前移动,写操作会使写指针向前移动,并将数据写入相应位置。 4. 空状态指示信号:通过判断读写指针的状态来确定是否存在数据。当读写指针相等时,说明FIFO为空。 综上所述,异步FIFOVerilog设计需要考虑读写指针和读写逻辑,并且要注意空状态指示信号的延迟问题。根据具体的需求和设计要求,可以选择适合的设计方法进行实现。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [异步FIFO的Verilg实现方法](https://blog.csdn.net/wuzhikaidetb/article/details/121152844)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* *3* [异步FIFO设计(Verilog)](https://blog.csdn.net/qq_21842097/article/details/118307227)[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^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值