引言
在數(shù)字設(shè)計中,利用FIFO進(jìn)行數(shù)據(jù)處理是非常普遍的應(yīng)用,例如,實現(xiàn)時鐘域交叉、低延時存儲器緩存、總線位寬調(diào)整等。下圖給出了FIFO生成器支持的一種可能配置。

設(shè)計中有兩個獨立的時鐘域并且讀數(shù)據(jù)總線的位寬是寫數(shù)據(jù)總線位寬的2倍。使用FIFO生成器可以快速實現(xiàn)這種配置,從而在Xilinx FPGA芯片上實現(xiàn)特定的設(shè)計要求。
實際應(yīng)用案例:本案例背景是將信號處理系統(tǒng)中ADC采集到的數(shù)據(jù)寫入FPGA芯片外掛的DDR3,完成采樣數(shù)據(jù)的存儲。ADC采樣率設(shè)定為96Mhz,兩個采樣點(兩個16bit數(shù)據(jù)拼接成一個32bit)為單位,DDR讀寫時鐘速率為150Mhz,總線數(shù)據(jù)位寬64bit,二者時鐘域、位寬均不同,故需在中間加入一級FIFO,從而實現(xiàn)時鐘域的交叉以及總線位寬的調(diào)整。
下面將從FIFO IP核的創(chuàng)建,模塊程序編寫,功能仿真驗證等三個方面完成本案例的介紹:
1)FIFO IP核的創(chuàng)建:打開Vivado軟件(本例程基于Vivado 2018.3版本)IP catalog一欄,輸入FIFO,雙擊進(jìn)入如下界面,第一個Basic選項卡主要是設(shè)置FIFO接口類型,可設(shè)置為正常的Native模式或AXI總線接口,一般我們選擇Native即可。然后選擇FIFO實現(xiàn)的類型:讀寫使用獨立時鐘還是同一時鐘,實現(xiàn)時使用分布式RAM、Block RAM還是專用的FIFO等等,這里我們選擇Independent Clocks Block RAM,即獨立時鐘塊RAM的FIFO。

切換至第二個Native Ports選項卡,這個界面主要是設(shè)置讀寫數(shù)據(jù)位寬、深度以及一些端口的使能、端口復(fù)位值等的設(shè)置。結(jié)合本案例的應(yīng)用,設(shè)置寫位寬為32bit,深度設(shè)置為1024,讀位寬設(shè)置為64bit。使能復(fù)位管腳,設(shè)置滿信號(Full Flags)的復(fù)位值為0,讀數(shù)據(jù)(Dout)復(fù)位值為0。

然后切換至第三個Status Flags選項卡,本選項卡是設(shè)置其余一些可選的標(biāo)志信號,本案例需使用本界面下的Programmable Flags,即可編程的標(biāo)志信號,設(shè)置滿標(biāo)志門限置位值(Full Threshold Assert Value),可使FIFO寫入的數(shù)據(jù)總數(shù)大于等于該值后將prog_full(可編程滿標(biāo)志信號)拉高,相比full信號使用起來更靈活。DDR讀寫采用Burst方式(突發(fā)傳輸),一次連續(xù)寫入256個數(shù),這里設(shè)置Full Threshold Assert Value為512(256*2,2是FIFO讀寫位寬的比值),當(dāng)FIFO寫入512個數(shù)后,prog_full拉高,進(jìn)行FIFO讀操作,一次連續(xù)讀256個64bit的數(shù)(對應(yīng)寫的512個32bit數(shù))存入DDR。

切換至第四個Data Counts選項卡,本選項卡主要是選擇是否使用讀寫數(shù)據(jù)計數(shù),本案例不使用計數(shù),此頁面保持默認(rèn)設(shè)置。

最后Summary選項卡是FIFO設(shè)置后的各項信息,可核對FIFO設(shè)置是否正確及設(shè)計是否滿足要求。

2)模塊程序的編寫
頂層模塊:FIFO_test.v
module FIFO_test(
input rst,
input wr_clk,
input rd_clk,
input [31:0] din,
input wr_en,
input rd_en,
output [63:0] dout,
output full,
output empty,
output prog_full,
output wr_rst_busy,
output rd_rst_busy
);
fifo_generator_0 U_fifo (
.rst(rst), // input wire rst
.wr_clk(wr_clk), // input wire wr_clk
.rd_clk(rd_clk), // input wire rd_clk
.din(din), // input wire [31 : 0] din
.wr_en(wr_en), // input wire wr_en
.rd_en(rd_en), // input wire rd_en
.dout(dout), // output wire [63 : 0] dout
.full(full), // output wire full
.empty(empty), // output wire empty
.prog_full(prog_full), // output wire prog_full
.wr_rst_busy(wr_rst_busy), // output wire wr_rst_busy
.rd_rst_busy(rd_rst_busy) // output wire rd_rst_busy
);
endmodule
TestBench模塊:FIFO_sim
module FIFO_sim;
reg rst;
reg wr_clk;
reg rd_clk;
reg [31:0] din;
reg wr_en;
reg rd_en;
wire [63:0] dout;
wire full;
wire empty;
wire prog_full;
wire wr_rst_busy;
wire rd_rst_busy;
initial begin
rst = 1;
wr_clk = 0;
wr_en = 0;
rd_clk = 0;
rd_en = 0;
din = 0;
#1000
rst = 0;
end
always #10.4167 wr_clk = ~wr_clk;
always #3.3333 rd_clk = ~rd_clk;
always @(posedge wr_clk) begin
if(!wr_rst_busy && !rst) begin
wr_en <= 1'b1;
din <= din + 1'b1;
end
end
reg [1:0] RD_state = 2'b01;
reg [15:0] rd_count = 'd0;
always @(posedge rd_clk) begin
case(RD_state)
2'b01: begin
if(!rd_rst_busy && prog_full) RD_state <= 2'b10;
end
2'b10: begin
if(rd_count >= 'd256) begin
RD_state <= 2'b01;
rd_count <= 'd0;
rd_en <= 1'b0;
end
else begin
rd_count <= rd_count + 1'b1;
rd_en <= 1'b1;??
end
end
default: begin
RD_state <= 2'b01;
end
endcase
end
FIFO_test U_FIFO_test(
.rst(rst),
.wr_clk(wr_clk),
.rd_clk(rd_clk),
.din(din),
.wr_en(wr_en),
.rd_en(rd_en),
.dout(dout),
.full(full),
.empty(empty),
.prog_full(prog_full),
.wr_rst_busy(wr_rst_busy),
.rd_rst_busy(rd_rst_busy)
);
endmodule
編寫TestBench時,寫時鐘為48Mhz,讀時鐘為150MHz。寫是連續(xù)的,使能一直打開,表示AD是一直連續(xù)工作的,寫入夠512個數(shù)后,prog_full拉高,進(jìn)行一次FIFO讀操作,連續(xù)讀出256個數(shù),然后等待下一次prog_full為高的到來,如此周而復(fù)始。
3)波形功能仿真
點擊Run simulation,啟動功能仿真,可以看到FIFO一開始復(fù)位結(jié)束后,進(jìn)行寫操作,每寫夠512個數(shù)后,prog_full拉高,進(jìn)行一次讀操作,連續(xù)讀出256個數(shù)后,停止讀操作,等待下一次prog_full拉高時刻的到來。將讀出的數(shù)據(jù)和寫入的數(shù)據(jù)對比,完全一致,不存在丟數(shù)的情況,因此驗證了功能的正確性。

總結(jié):通過本案例代碼程序的編寫以及波形功能仿真,可以熟悉并掌握FIFO的基本功能和常用用法:數(shù)據(jù)跨時鐘域及總線位寬調(diào)整。本例程是我自己在一個項目中用到的,結(jié)合自己的需求進(jìn)行編寫的,并不具有普適性,寫此博客的初衷也是讓一些不熟悉FIFO用法的讀者能快速入門,可能并不能直接幫助到所有的讀者。希望大家可以在此基礎(chǔ)上,結(jié)合自己的工程應(yīng)用實例,完成自己相應(yīng)的設(shè)計。
原文鏈接:https://blog.csdn.net/qq_43622265/article/details/113497121
-
FPGA
+關(guān)注
關(guān)注
1660文章
22408瀏覽量
636199 -
fifo
+關(guān)注
關(guān)注
3文章
407瀏覽量
45740 -
IP核
+關(guān)注
關(guān)注
4文章
344瀏覽量
51944 -
生成器
+關(guān)注
關(guān)注
7文章
322瀏覽量
22706
原文標(biāo)題:FIFO IP核的使用
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設(shè)計論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
#硬聲創(chuàng)作季 #FPGA FPGA-27-04 Quartus中fifo IP核介紹與仿真測試-1
#硬聲創(chuàng)作季 #FPGA FPGA-27-04 Quartus中fifo IP核介紹與仿真測試-2
#硬聲創(chuàng)作季 #FPGA FPGA-27-04 Quartus中fifo IP核介紹與仿真測試-3
#硬聲創(chuàng)作季 #FPGA FPGA-27-04 Quartus中fifo IP核介紹與仿真測試-4
求助:用fifo ip核作延時輸出數(shù)據(jù)
求助 FPGA 異步FIFO IP核
ISE中,調(diào)用FIFO IP核遇到的問題?
XILINX FIFO IP核調(diào)用問題
FIFO IP核的使用
FIFO是什么?有什么用?FIFO IP核應(yīng)該如何使用?
鋯石FPGA A4_Nano開發(fā)板視頻:FIFO IP核的使用講解
講解幾點關(guān)于FIFO IP核使用時的注意事項
FPGA學(xué)習(xí)筆記:FIFO IP核的使用方法
FIFO IP核的使用教程
評論