FPGA学习之 异步FIFO

Posted 满足没有

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

以上是关于FPGA学习之 异步FIFO的主要内容,如果未能解决你的问题,请参考以下文章

FPGA学习之 异步FIFO

FPGA开发基础————异步FIFO深度的计算与分析

FPGA开发基础————异步FIFO深度的计算与分析

ZYNQ从入门到秃头08 FPGA片内异步FIFO读写测试实验

ZYNQ从入门到秃头08 FPGA片内异步FIFO读写测试实验

v3学院 FPGA专家 带你学习FPGA实现格雷码跨时钟域异步fifo