异步fifo代码

module asyn_fifo #(parameter FIFO_WIDTH = 32,
                   parameter FIFO_DEPTH = 16,
                   parameter ADDR_WIDTH = 4)
            (
                input                         wr_clk ,
                input                         rd_clk ,
                input                         rst_n  ,
                input                         wr_en  ,
                input      [FIFO_WIDTH-1:0]   wr_data,
                input                         rd_en  ,
                output reg [FIFO_WIDTH-1:0]   rd_data,
                output                        wr_full,
                output                        rd_empty              
            );

            reg [ADDR_WIDTH:0]   wr_addr_ptr;  //地址指针,比地址多一位
            reg [ADDR_WIDTH:0]   rd_addr_ptr;
            reg [ADDR_WIDTH-1:0] wr_addr;      //RAM地址
            reg [ADDR_WIDTH-1:0] rd_addr;

            reg [ADDR_WIDTH:0]   wr_addr_ptr_gray;
            reg [ADDR_WIDTH:0]   wr_addr_ptr_gray_d1;
            reg [ADDR_WIDTH:0]   wr_addr_ptr_gray_d2;

            reg [ADDR_WIDTH:0]   rd_addr_ptr_gray;
            reg [ADDR_WIDTH:0]   rd_addr_ptr_gray_d1;
            reg [ADDR_WIDTH:0]   rd_addr_ptr_gray_d2;

            reg [FIFO_WIDTH-1:0] mem [0:FIFO_DEPTH-1];
            integer i;

            //==========write fifo==============
            always @(posedge wr_clk, negedge rst_n) begin
                if(~rst_n) begin
                    for(i=0;i<FIFO_DEPTH;i=i+1) begin
                        mem[i] <= 'h0;
                    end
                end
                else if(wr_en) begin
                    mem[wr_addr] <= wr_data;
                end
            end

            //==========read fifo==============
            always @(posedge rd_clk, negedge rst_n) begin
                if(~rst_n) begin
                    rd_data <= 'h0;
                end
                else if(rd_en) begin
                    rd_data <= mem[rd_addr];
                end
            end

            //################## write clock ################
            //=========write pointer generate==========
            always @(posedge wr_clk, negedge rst_n) begin
                if(~rst_n) begin
                    wr_addr_ptr <= 'h0;
                end
                else if(wr_en && (~wr_full)) begin
                    wr_addr_ptr <= wr_addr_ptr+1'b1;
                end
            end
            //==========translate write pointer gray code==========
            always @(posedge wr_clk, negedge rst_n) begin
                if(~rst_n) begin
                    wr_addr_ptr_gray <= 'h0;
                end
                else begin
                    wr_addr_ptr_gray <= (wr_addr_ptr>>1)^wr_addr_ptr;
                end
            end
            //===========read pointer gray syn==============
            always @(posedge wr_clk, negedge rst_n) begin
                if(~rst_n) begin
                    rd_addr_ptr_gray_d1 <= 'h0;
                    rd_addr_ptr_gray_d2 <= 'h0;
                end
                else begin
                    rd_addr_ptr_gray_d1 <= rd_addr_ptr_gray;
                    rd_addr_ptr_gray_d2 <= rd_addr_ptr_gray_d1;
                end
            end

            //############### read clock ##################
            //=========read pointer generate==========
            always @(posedge rd_clk, negedge rst_n) begin
                if(~rst_n) begin
                    rd_addr_ptr <= 'h0;
                end
                else if(rd_en && (~rd_empty)) begin
                    rd_addr_ptr <= rd_addr_ptr+1'b1;
                end
            end
            //==========translate read pointer gray code==========
            always @(posedge rd_clk, negedge rst_n) begin
                if(~rst_n) begin
                    rd_addr_ptr_gray <= 'h0;
                end
                else begin
                    rd_addr_ptr_gray <= (rd_addr_ptr>>1)^rd_addr_ptr;
                end
            end
            //===========write pointer gray syn==============
            always @(posedge rd_clk, negedge rst_n) begin
                if(~rst_n) begin
                    wr_addr_ptr_gray_d1 <= 'h0;
                    wr_addr_ptr_gray_d2 <= 'h0;
                end
                else begin
                    wr_addr_ptr_gray_d1 <= wr_addr_ptr_gray;
                    wr_addr_ptr_gray_d2 <= wr_addr_ptr_gray_d1;
                end
            end

            assign wr_addr = wr_addr_ptr[ADDR_WIDTH-1:0];
            assign rd_addr = rd_addr_ptr[ADDR_WIDTH-1:0];

            assign wr_full = (wr_addr_ptr_gray == {~rd_addr_ptr_gray_d2[ADDR_WIDTH:ADDR_WIDTH-1],rd_addr_ptr_gray_d2[ADDR_WIDTH-2:0]});
            assign rd_empty = (rd_addr_ptr_gray == wr_addr_ptr_gray_d2);

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值