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的主要内容,如果未能解决你的问题,请参考以下文章
ZYNQ从入门到秃头08 FPGA片内异步FIFO读写测试实验