FIFO是FPGA內部一種常用的資源,可以通過FPGA廠家的的IP生成工具生成相應的FIFO。FIFO可分為同步FIFO和異步FIFO,其區別主要是,讀寫的時鐘是否為同一時鐘,如使用一個時鐘則為同步FIFO,讀寫時鐘分開則為異步FIFO。一般來說,較大的FIFO可以選擇使用內部BLOCK RAM資源,而小的FIFO可以使用寄存器資源例化使用。
一般來說,FIFO的主要信號包括:
|
信號 |
數據信號 |
|
讀信號 |
rd_en |
|
讀數據 |
dout |
|
讀空信號 |
empty |
|
寫信號 |
wr_en |
|
寫數據 |
din |
|
寫滿信號 |
full |
實際使用中,可編程滿的信號(XILINX 的FIFO)較為常用,ALTERA的FIFO中,可以通過寫深度(即寫入多少的數據值)來構造其可編程滿信號。通過配置threshold(門限)的值可以設定可編程滿起效時的FIFO深度。
上圖所示為FIFO的模型,可以看做一個漏桶模型,其中輸入、輸出、滿信號、空信號、可編程滿等信號如圖所示,一目了然。 其中threshold信號可以看做水位線,通過此信號可以設置可編程滿信號。FIFO的其他的信號也大都與其深度相關,如有特殊需求,可通過廠商提供的IP生成工具的圖形界面進行選擇使用。
FIFO的使用場景有多種,其中主要如下所示:
(1)數據的緩沖,如模型圖所示,如果數據的寫入速率高,但間隔大,且會有突發;讀出速率小,但相對均勻。則通過設置相應深度的FIFO,可以起到數據暫存的功能,且能夠使后續處理流程平滑,避免前級突發時,后級來不及處理而丟棄數據。
(2)時鐘域的隔離。對于不同時鐘域的數據傳遞,則數據可以通過FIFO進行隔離,避免跨時鐘域的數據傳輸帶來的設計與約束上的復雜度。
FIFO設計中有兩個需要注意事項,首先,不能溢出,即滿后還要寫導致溢出,對于數據幀的操作來說,每次寫入一個數據幀時,如果每寫一個寬度(FIFO的寬度)的數據,都要檢查滿信號,則處理較為復雜,如果在寫之前沒滿,寫過程不檢查,則就容易導致溢出。因此可編程滿的設定尤為必要,通過設置可編程滿的水位線,保證能夠存儲一個數據幀,這樣寫之前檢查可編程滿即可。
其次,另一更容易出錯的問題,就是空信號。對于FIFO來說,在讀過程中出現空信號,則其沒有代表該值沒有被讀出,對于讀信號來說,如設定讀出一定長度的值,只在一開始檢測非空,如狀態機的觸發信號,容易出現過程中間也為空的信號,會導致某些數據未讀出,特別是寫速滿而讀速快的場景下。 因此rden與!empty信號要一起有效才算將數據讀出。
空信號處理相對容易出錯,懶人自有笨方法,下面介紹一種應用于數據幀處理的FIFO使用方式,只需在讀開始檢測空信號即可,可以簡化其處理讀數據的流程:
其處理結構如上圖所示,數據緩存以大FIFO(BLOCK RAM實現)為主,而每存儲完畢一個數據幀向小FIFO(寄存器實現)內寫入值。當小FIFO標示非空時,則標示大FIFO中已存儲一個整幀。則下一級模塊可以只需檢測小FIFO非空時,從而讀出一個整幀,過程中大FIFO一直未非空,可以不用處理非空信號,從而簡化設計和驗證的流程。
FIFO在FPGA設計中除了上篇所介紹的功能之外, 還有以下作為以下功能使用:
(1)內存申請
在軟件設計中,使用malloc()和free()等函數可以用于內存的申請和釋放。特別是在有操作系統的環境下,可以保證系統的內存空間被動態的分配和使用,非常的方便。如果在FPGA內部實現此動態的內存分配和申請,相對來說較為復雜,例如某些需要外部數據存儲且需動態改變的應用需求下,需要對FPGA外部DDR(或SRAM等)的存儲空間,進行動態的分配和釋放。通過使用FIFO作為內存分配器,雖然比不上軟件的靈活和方便,但是使用也較為簡便。
舉例說明假設外部存儲空間為8Mbyte,可將其劃分為8192個1Kbyte空間。并將數值0-8191存儲FIFO中,FIFO內部存儲所標示可用的內存空間。如下圖所示。
首先,進行內存的初始化,即將0-8191寫入FIFO中。
如需申請內存后,從FIFO中讀取值A,然后根據A的標示,寫入A所指示的外部存儲區(DDR)中相應的位置,即申請{A,10’h0_00} ->{A,10’h3_FF}的空間區域。
如釋放內存后,即可向FIFO中寫入相應的值。即可保證下次該空間能夠被設計使用。
在此種設計中,FIFO承擔了內存分配和釋放器的角色。此時只能申請或釋放最小單元倍數的內存空間,如本例所示:為1Kbit。如FIFO讀空,則代表申請內存失敗,需要等待其他塊內存釋放后再寫入FIFO中,才能再次申請。
(2)串并轉換
對于串并轉換,可能對于FPGA工程師來說,非常常見,但是如果有專門的IP實現此功能,可簡化設計,減少出錯及驗證的工作量。例如:對于外部輸入的需要進行串并轉換的信號,并進行存儲的信號,如設計進行串并轉換在存儲等操作,設計,可以直接通過例化讀寫位寬不一致的FIFO,例如1入8出的FIFO,可直接將外部輸入信號直接轉換成8BIT信號并進行存儲后,供后續處理使用(其他的)。
(3)業務優先級劃分
通過FIFO設置不同水位線,可以劃分不同的業務優先級,保證高業務優先級數據流在帶寬受限時,優先通過,而低業務優先級只能在滿足高優先級需求后有多余的帶寬時才能通過。并且可以劃分多個優先級,滿足多種業務的需求。設計將在以后篇幅中詳述。
(4)固定帶寬設定
通過對FIFO接口的讀出使能,能夠保證實現固定帶寬的輸出,例如FIFO讀接口為32bit,而讀時鐘為50Mhz,則輸出為1.6Gbit/S。如實現固定帶寬的輸出(如1Gbit/S),有兩種方式,一種可以通過降低時鐘頻率到31.25Mhz。另一種方式,可通過讀信號中間插入等待周期,如果讀出長度為N的數據所需時鐘周期為M,則需等待(3M/5)的周期,從而降低至1Gbit/S的處理能力,這在某些需要進行流量限制的業務方式中使用。
對于FIFO來說,作為FPGA內部資源的一個常用器件,最常見應用于異步時鐘域劃分和緩沖數據,但不僅限于此,簡化設計、減少耦合、輸入輸出接口固定,便于仿真和驗證,都是使用FIFO帶來的設計上的益處。
作者: 阿昏豆, 來源:面包板社區
鏈接:https://www.mianbaoban.cn/blog/787532-366580.html
點擊 “閱讀原文”申請!