【小月电子】ALTERA FPGA开发板系统学习教程-LESSON12 IPCORE核之FIFO详细教程
ALTERA FPGA IPCORE核之FIFO詳細(xì)教程
若要觀看該博客配套的視頻教程,可點(diǎn)擊此鏈接
一. FIFO簡介
FIFO: 是英文first in first out的縮寫,即先進(jìn)先出,指的是對數(shù)據(jù)的存儲具有先進(jìn)先出特性的緩存器。從字面意思上就可以大致看出和RAM和ROM的區(qū)別,即沒有地址線,無法像RAM和ROM一樣寫入或讀出指定地址的數(shù)據(jù),而必須按順序讀出。
根據(jù)讀寫操作是否使用同一個時(shí)鐘,可以將FIFO分為兩類:
-
同步FIFO
讀寫操作使用同一個時(shí)鐘,一般用于數(shù)據(jù)緩存
-
異步FIFO
讀寫操作使用不同的時(shí)鐘,一般用于跨時(shí)鐘域處理,比如我們在做視頻相關(guān)項(xiàng)目時(shí),假如我們的攝像頭的像素時(shí)鐘是25MHZ,SDRAM的讀寫時(shí)鐘是100MHZ,那我們要把采集到的視頻數(shù)據(jù)寫入SDRAM,那么就必須要用到異步FIFO,進(jìn)行跨時(shí)鐘域處理。還有一種應(yīng)用場景,讀寫數(shù)據(jù)的位寬不一致時(shí),比如寫入的數(shù)據(jù)是16位,讀出的數(shù)據(jù)需要8位,這時(shí)候使用異步FIFO,只需要分別選擇寫數(shù)據(jù)位寬和讀數(shù)據(jù)位寬,非常方便,值得注意的是QuartusII中的同步FIFO,讀數(shù)據(jù)位寬是無法進(jìn)行更改,默認(rèn)和寫數(shù)據(jù)位寬一致。
二. FIFO IPCORE生成步驟及參數(shù)介紹
不同公司的FPGA,生成的FIFO大同小異,本篇我們以一個實(shí)例來對ALTERA的IPCORE來進(jìn)行介紹。我們要生成一個寫數(shù)據(jù)位寬8,讀數(shù)據(jù)位寬16的異步FIFO,利用Modelsim仿真來觀察FIFO的時(shí)序波形。
2.1 首先打開QuartusII軟件,新建一個工程,命令為async_fifo_test
新建QuartusII工程的步驟就不一一說明,為了方便上板驗(yàn)證,選用我們開發(fā)板上的器件:EP4CE6F17C8
2.2 FIFO IPCORE配置
2.2.1 生成IPCORE,命名為async_fifo_w8r16_d1024
我們在對IPCORE命名時(shí),最好能體現(xiàn)出該IPCORE的一些主要特性,比如我們上面的命令,我們知道是一個異步FIFO,寫數(shù)據(jù)位寬8,讀數(shù)據(jù)位寬16,深度1024。說到這,就有必要說一下非對稱讀寫位寬。讀寫數(shù)據(jù)的位寬可以不一致,但是必須滿足比例關(guān)系:1:8,1:4,1:2,1:1,那么讀寫位寬不一致,數(shù)據(jù)的排序關(guān)系是怎么樣的呢?我們分兩種情況做一下說明:
寫位寬大于讀位寬,直截了當(dāng)我做了一個簡單的測試程序仿真出的波形如下:
通過仿真可以看出,寫入16’h0102,先讀出的是8’h02,接著讀出的是8’h01,是不是和我們想的不一樣,所以這個地方一定要注意噢
寫位寬小于讀位寬,直截了當(dāng)我做了一個簡單的測試程序仿真出的波形如下:
通過仿真可以看出,寫入8’h01,8’h02兩個數(shù),讀出的是16’h0201,是不是和我們想的不一樣,所以這個地方一定要注意噢
2.2.2 生成FIFO的步驟如下圖所示:
當(dāng)我們生成好后可以看到左邊FIFO框圖上顯示了FIFO的輸入輸出接口,左下角是FIFO使用的FPGA內(nèi)部資源。
2.2.2 FIFO各接口定義如下:
1. wrfull:選用寫時(shí)鐘域,寫滿是指寫得快讀得慢,FIFO里面的存儲數(shù)據(jù)超過了FIFO的深度,如果這時(shí)候再繼續(xù)寫,數(shù)據(jù)就會溢出丟失,所以這時(shí)需要禁止再往FIFO 中寫入數(shù)據(jù),防止數(shù)據(jù)溢出丟失。高電平表示FIFO寫入數(shù)據(jù)量達(dá)到 FIFO 設(shè)置的最大空間
2. rdempty:選用讀時(shí)鐘域,高電平表示 FIFO 中已經(jīng)沒有數(shù)據(jù)了,此時(shí)應(yīng)該通過該信號控制讀請求信號(也稱為讀使能信號),禁止FIFO 繼續(xù)再讀出數(shù)據(jù),否則讀出的將是無效數(shù)據(jù)。
3. rdusedw:為FIFO里面存存儲的數(shù)據(jù)個數(shù)。在某些應(yīng)用場景下,我們需要用到usedw時(shí)鐘監(jiān)測FIFO存儲的數(shù)據(jù)個數(shù),但是需要注意,同步FIFO的數(shù)據(jù)計(jì)數(shù)是準(zhǔn)確的,因?yàn)樽x寫時(shí)鐘相同,不需要做跨時(shí)鐘域處理;但是異步FIFO的計(jì)數(shù)就不準(zhǔn)確了,只能粗略的進(jìn)行判斷,比如半空,半滿等。
4. wrreq:寫使能,高電平有效
5. wrclk:寫時(shí)鐘
6. data:寫數(shù)據(jù),位寬8
7. rdreq:讀使能,高電平有效
8. rdclk:讀時(shí)鐘
9. aclr:異步復(fù)位信號,用于清空 FIFO
10. almost full:幾乎滿標(biāo)志信號,我們可以控制 FIFO 快要被寫滿的時(shí)候和 full 信號的作用一樣。
11. almost empty:幾乎空標(biāo)志信號,我們可以控制 FIFO 快要被讀空的時(shí)候和 empty 信號的作用一樣。
12. Synchronous clear:同步復(fù)位信號,用于清空 FIFO。
10~12的信號,本例程的FIFO沒有生成,大家可根據(jù)具體需求選擇是否生成這些信號。
三. Verilog代碼設(shè)計(jì)
`timescale 1ns / 100psmodule async_fifo_test(input clk ,//50MHZinput rst_n ,output [15:0] dout);reg [ 7:0] fifo_wdata ;reg fifo_wren ;reg fifo_rden ;wire[15:0] fifo_rdata ;wire fifo_wclk ;wire fifo_rclk ;wire locked ;reg [9:0] wr_cnt ;reg [8:0] rd_cnt ;assign dout=fifo_rdata ;//注意需要在fifo_wclk時(shí)鐘域下,因?yàn)閒ifo寫使能和寫數(shù)據(jù)都是在該計(jì)數(shù)器(wr_cnt)下生成always@(posedge fifo_wclk or negedge locked)beginif(!locked)wr_cnt<=0;else wr_cnt<=wr_cnt+1;end//注意需要在fifo_rclk時(shí)鐘域下,因?yàn)閒ifo讀使能是在該計(jì)數(shù)器(rd_cnt)下生成always@(posedge fifo_rclk or negedge locked)beginif(!locked)rd_cnt<=0;else rd_cnt<=rd_cnt+1;end//在fifo_wclk時(shí)鐘域下生成FIFO寫數(shù)據(jù)和寫使能,位寬8位,寫100個數(shù)據(jù)always@(posedge fifo_wclk or negedge locked)beginif(!locked)beginfifo_wren<=0;fifo_wdata<=0;end else if(wr_cnt>0&&wr_cnt<=100)beginfifo_wren<=1;fifo_wdata<=fifo_wdata+1;end else beginfifo_wren<=0;endend//在fifo_rclk時(shí)鐘域下生成FIFO讀使能,讀數(shù)據(jù)的位寬是16位,所以讀50個數(shù)據(jù)就將FIFo讀空always@(posedge fifo_rclk or negedge locked)beginif(!locked)fifo_rden<=0;else if(rd_cnt>100&&rd_cnt<=150)fifo_rden<=1;elsefifo_rden<=0;end//利用PLL生成FIFO的讀寫時(shí)鐘,寫時(shí)鐘25MHZ,讀時(shí)鐘50MHZpll Upll(.areset (~rst_n ),.inclk0 (clk ),.c0 (fifo_wclk ),.c1 (fifo_rclk ),.locked (locked ));//例化FIFO IPCOREasync_fifo_w8r16_d1024 Uasync_fifo_w8r16_d1024(.aclr (~rst_n ),//復(fù)位,高電平復(fù)位.data (fifo_wdata ),//寫數(shù)據(jù).rdclk (fifo_rclk ),//讀時(shí)鐘.rdreq (fifo_rden ),//讀使能.wrclk (fifo_wclk ),//寫時(shí)鐘.wrreq (fifo_wren ),//寫使能.q (fifo_rdata ),//讀數(shù)據(jù).rdempty (),//讀空標(biāo)志.rdusedw (),//在讀時(shí)鐘域下,FIFO中當(dāng)前存儲的數(shù)據(jù)個數(shù),數(shù)據(jù)位寬16位.wrfull ()//寫滿標(biāo)志);endmodule四. Verilog測試代碼設(shè)計(jì)
`timescale 1ns / 100psmodule async_fifo_test_tb;reg clk =1;reg rst_n =0;initialbegin#1000rst_n=1;end//生成激勵時(shí)鐘always #10 clk<=~clk;//例化被測試模塊async_fifo_test Uasync_fifo_test(.clk (clk ),//50MHZ.rst_n (rst_n ),.dout ( ));endmodule五. 仿真波形分析
1.aclr :fifo復(fù)位信號,高電平復(fù)位
2.wrclk :fifo寫時(shí)鐘
3.wrreq :fifo寫使能,高電平時(shí)表示寫入數(shù)據(jù)。
4.rdclk :fifO讀時(shí)鐘
5.rdreq :fifo讀使能,高電平表示讀數(shù)據(jù),由于我們選擇是正常模式,所以在rdreq有效時(shí),會延時(shí)一個時(shí)鐘周期才會出有效數(shù)據(jù)。
6.q:fifo讀數(shù)據(jù)
7.rdempty:空標(biāo)志,高電平表示fifo為空,在仿真波形中可以看出在fifo復(fù)位時(shí)且未寫入數(shù)據(jù)時(shí),rdempty為高電平,當(dāng)前fifo為空。
8.rdusedw:FIFO里面存存儲的數(shù)據(jù)個數(shù),由于我們用的是異步fifO,這個數(shù)據(jù)并不能精確的反應(yīng)fifo里面的數(shù)據(jù)個數(shù),只能做一個參考。通過上面的仿真圖也可以看出,rdusedw并沒有精確的反應(yīng)fifo中的數(shù)據(jù)個數(shù)。
9.wrfull:滿標(biāo)志,當(dāng)fifo中存儲的數(shù)據(jù)個數(shù)超過fifo自身的深度時(shí),便會溢出,wrful置高。
通過上面的仿真圖,我們可以看到wrfull一直為低,所以fifo數(shù)據(jù)未溢出,不會造成數(shù)據(jù)丟失。同時(shí),fifo在進(jìn)行讀操作時(shí),rdempty一直為低,說明在讀數(shù)據(jù)時(shí),fifo中一直有數(shù)據(jù),不會讀出無效數(shù)據(jù)。一般來說,只要fifo操作滿足以上兩個條件,便可進(jìn)行正常的數(shù)據(jù)寫入和讀取。
如果大家想要該工程的源碼和仿真測試激勵文件用來學(xué)習(xí),可以直接聯(lián)系工程師,謝謝大家的閱讀!
總結(jié)
以上是生活随笔為你收集整理的【小月电子】ALTERA FPGA开发板系统学习教程-LESSON12 IPCORE核之FIFO详细教程的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 微信语音内容怎么录制,电脑如何内录
- 下一篇: 内录音频(Windows系统)