异步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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值