FPGA学习之 异步FIFO

FPGA学习之 异步FIFO

在FPGA学习过程中遇到的,写篇博客记录下自己的学习经历

参考以下文章,很详细。网上找了很多博客参考,这篇我觉得是真的很容易看懂了,代码部分也很详细

[异步FIFO—Verilog实现]------alangaixiaoxiao

附上代码:

module fifo_async #(parameter DATA_WIDTH = 16,parameter DATA_DEPTH = 256)(
    rst         ,
    wr_clk      ,
    wr_en       ,
    rd_clk      ,
    rd_en       ,
    din         ,
    dout        ,
    vld         ,
    empty       ,
    full        
);
//求底数为2的对数的值 求位宽
function integer log2b(input integer data);
    begin
        for(log2b = 0; data > 0 ; log2b = log2b + 1)begin
            data = data >> 1;
        end
    end
endfunction
//接口定义
input                           rst         ;//复位
input                           wr_clk      ;//写时钟
input                           wr_en       ;//写使能
input                           rd_clk      ;//读时钟
input                           rd_en       ;//读使能
input       [DATA_WIDTH - 1:0]  din         ;//输入数据
output reg  [DATA_WIDTH - 1:0]  dout        ;//输出数据
output reg                      vld         ;//输出有效信号
output                          full        ;//满标注
output                          empty       ;//空标志

//信号定义
reg  [log2b(DATA_DEPTH) - 1:0] wr_ptr;//写指针
reg  [log2b(DATA_DEPTH) - 1:0] rd_ptr;//读指针
wire [log2b(DATA_DEPTH) - 2:0]   wr_addr;//写地址
wire [log2b(DATA_DEPTH) - 2:0]   rd_addr;//读地址

wire  [log2b(DATA_DEPTH) - 1:0]   wr_ptr_gray;//写指针对应格雷码
reg   [log2b(DATA_DEPTH) - 1:0]   wr_ptr_gray_r0;
reg   [log2b(DATA_DEPTH) - 1:0]   wr_ptr_gray_r1;
wire  [log2b(DATA_DEPTH) - 1:0]   rd_ptr_gray;//读指针对应格雷码
reg   [log2b(DATA_DEPTH) - 1:0]   rd_ptr_gray_r0;
reg   [log2b(DATA_DEPTH) - 1:0]   rd_ptr_gray_r1;

reg [DATA_WIDTH - 1:0] fifo_ram [DATA_DEPTH - 1:0];//fifo寄存器组


//写fifo

integer i;
always@(posedge wr_clk or posedge rst)begin
    if(rst)begin
        for(i = 0;i<DATA_DEPTH;i = i + 1)begin
				fifo_ram[i] <= 0;
		  end
    end
    else if(wr_en && (~full))begin
        fifo_ram[wr_addr] <= din;
    end
end
//读fifo
always@(posedge rd_clk or posedge rst)begin
    if(rst)begin
        dout <= 0;
        vld <= 1'b0;
    end
    else if(rd_en && (~empty))begin
        dout <= fifo_ram[rd_addr];
        vld <= 1'b1;
    end
    else begin
        dout <= 0;
        vld <= 1'b0;
    end
end

assign wr_addr = wr_ptr[log2b(DATA_DEPTH) - 2:0];
assign rd_addr = rd_ptr[log2b(DATA_DEPTH) - 2:0];

//同步指针
//读指针同步至写时钟域
always@(posedge wr_clk)begin
    rd_ptr_gray_r0 <= rd_ptr_gray;
    rd_ptr_gray_r1 <= rd_ptr_gray_r0;
end
//写指针变化
always@(posedge wr_clk or posedge rst)begin
    if(rst)begin
        wr_ptr <= 0;
    end
    else if(wr_en && (~full))begin
        wr_ptr <= wr_ptr + 1'b1;
    end
end 
//写指针同步至读时钟域
always@(posedge rd_clk)begin
    wr_ptr_gray_r0 <= wr_ptr_gray;  
    wr_ptr_gray_r1 <= wr_ptr_gray_r0;
end
//读指针变化
always@(posedge rd_clk or posedge rst)begin
    if(rst)begin
        rd_ptr <= 0;
    end
    else if(rd_en && (~empty))begin
        rd_ptr <= rd_ptr + 1'b1;
    end
end

//指针转格雷码
assign wr_ptr_gray = (wr_ptr >> 1) ^ wr_ptr;
assign rd_ptr_gray = (rd_ptr >> 1) ^ rd_ptr;

//空标志
assign empty = (rd_ptr_gray == wr_ptr_gray_r1);
//满标志
assign full = (wr_ptr_gray == ({~(rd_ptr_gray_r1[log2b(DATA_DEPTH)-1:log2b(DATA_DEPTH)-2]),rd_ptr_gray_r1[log2b(DATA_DEPTH)-3:0]}));

endmodule

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值