FPGA 中的 FIFO(First-In, First-Out)是一种常见的数据缓冲器,用于在不同的时钟域之间进行数据传输。FIFO 可以暂存一定数量的数据,并支持并行读取和写入操作,同时保持先进先出的数据顺序。
FIFO 在 FPGA 中的应用非常广泛,特别是在需要处理异步数据交换的场景中。以下是一些 FIFO 的基本特性和特点:
FIFO 可以在许多应用中发挥重要作用,例如数据缓存、流水线数据传输、数据帧同步等。借助 FPGA 的灵活性,我们可以根据具体的需求和设计约束来实现定制化的 FIFO。
同步fifo与异步fifo的比较
在选择同步 FIFO 还是异步 FIFO 时,需要根据具体的设计需求和系统要求进行权衡。如果时钟同步性较好且时序要求较低,同步 FIFO 可能是一个更简单和可靠的选择。而在异步时序较为复杂的情况下,异步 FIFO 可以提供解决方案
在quartus右上角搜索fifo,选择文件夹创建ip核
进入fifo后,下图是一些选项的简单介绍,我选择的是同步fifo,数据传输位宽位8bit,总长度位32bit
进入到下面,会让你根据需求创建信号,这些信号的意思分别为
我这里只做简单的,所以只勾选了前三个信号,后面的信号可以根据自己的需求进行勾选
下面勾选工作模式,一般选择正常工作模式即可。后面选择内存的类型,勾选自动即可,如果你想深入了解工作模式的区别,请参考:
详解 altera 的同步 FIFO IP配置及使用 - 知乎 (zhihu.com)
之后选择优化选项,勾画no即可,详情可参考:详解 altera 的同步 FIFO IP配置及使用 - 知乎 (zhihu.com)
最后生成inst文件,就完成了
只写了一段特别简单的仿真进行模拟,如果需要严谨点的话可以写的更复杂
由于我这里勾选的内存字节大小为32,数据位是8位,所以延时4个周期,不断更换rdreq、wrreq信号,达到模拟的效果
`timescale 1 ns/ 1 ns
module fifo_vlg_tst();
// constants
// general purpose registers
reg eachvec;
// test vector input registers
reg clock;
reg [7:0] data;
reg rdreq;
reg wrreq;
// wires
wire empty;
wire full;
wire [7:0] q;
wire [4:0] usedw;
parameter SYS_CLK = 20;
always #(SYS_CLK/2) clock = ~clock;
initial begin
clock = 1'b0;
wrreq = 1'b1;
rdreq = 1'b0;
repeat(4)begin
repeat(4)begin
data = {$random}%64;
#(SYS_CLK*8);
end
wrreq = 1'b0;
rdreq = 1'b1;
repeat(4)begin
#(SYS_CLK*8);
end
wrreq = 1'b1;
rdreq = 1'b0;
end
$stop;
end
// assign statements (if any)
fifo i1 (
// port map - connection between master ports and signals/registers
.clock(clock),
.data(data),
.empty(empty),
.full(full),
.q(q),
.rdreq(rdreq),
.usedw(usedw),
.wrreq(wrreq)
);
initial
begin
// code that executes only once
// insert code here --> begin
// --> end
$display("Running testbench");
end
always
// optional sensitivity list
// @(event1 or event2 or .... eventn)
begin
// code executes for every event on sensitivity list
// insert code here --> begin
@eachvec;
// --> end
end
endmodule
异步fifo几乎与同步fifo相同,主要是勾选的方式不同
这里勾选默认即可
选择勾选的信号,与同步fifo信号基本类似,我这里多勾选了几个,方便观察
其他步骤全部默认,生成文件即可
`timescale 1 ps/ 1 ps
module afifo_vlg_tst();
// constants
// general purpose registers
// test vector input registers
parameter SYS_CLK_READ = 20;
parameter SYS_CLK_WRITE = 10;
reg [7:0] data;
reg rdclk;
reg rdreq;
reg wrclk;
reg wrreq;
// wires
wire [7:0] q;
wire rdempty;
wire rdfull;
wire [4:0] rdusedw;
wire wrempty;
wire wrfull;
wire [4:0] wrusedw;
always #(SYS_CLK_READ/2) rdclk= ~rdclk;
always #(SYS_CLK_WRITE/2) wrclk = ~wrclk;
initial begin
rdclk = 1'b0;
wrclk = 1'b0;
repeat(10)begin
wrreq = 1'b1;
rdreq = 1'b0;
data = {$random}%64;
#(SYS_CLK_WRITE*4);
wrreq = 1'b0;
rdreq = 1'b1;
#(SYS_CLK_READ*4);
end
end
// assign statements (if any)
afifo i1 (
// port map - connection between master ports and signals/registers
.data(data),
.q(q),
.rdclk(rdclk),
.rdempty(rdempty),
.rdfull(rdfull),
.rdreq(rdreq),
.rdusedw(rdusedw),
.wrclk(wrclk),
.wrempty(wrempty),
.wrfull(wrfull),
.wrreq(wrreq),
.wrusedw(wrusedw)
);
endmodule
由于自身水平原因,不能对fifo做一个更为详细的介绍,只作为自己的一个学习记录,如果有需要,可以参考下面链接去进行学习
FPGA(异步FIFO原理及Verilog代码实现)_哔哩哔哩_bilibili
07_FIFO IP核的使用讲解_哔哩哔哩_bilibili
先入先出——FIFO的Verilog实现与仿真(一) - 知乎 (zhihu.com)