1.簡介緩存
定義:異步
FIFO(First In First Out)一種先入先出(讀寫數據是隻能順序寫入順序讀出)的數據緩存器,讀寫數據時,其內部讀寫指針自動加1,所以沒有外部地址線,使用簡單。ide
分類:spa
FIFO能夠分爲同步FIFO和異步FIFO。同步FIFO的寫入時鐘和讀取時鐘徹底同樣,內核時一個簡單雙口RAM(Simple Dual Port RAM);異步FIFO寫入時鐘和讀取時鐘不一樣,不只須要真雙口RAM(True Dual Port RAM),還須要專門的握手信號進行跨時鐘域的數據傳遞。設計
用途:指針
1)使用異步FIFO進行跨時鐘域交互數據;2)進行不一樣數據寬度的讀寫匹配;3)對高速突發數據進行平均處理,下降瞬時處理速率。code
使用場景:blog
1)AXI總線工做在1GHz以上,而USB2.0工做在480MHz時,就須要內嵌異步FIFO;2)AD採樣爲24位,而傳輸協議爲8位時,可使用FIFO進行不一樣數據寬度的讀寫匹配...接口
2.空滿原理同步
空或滿時應知足:讀寫指針相等。當復位後,或者讀指針讀出FIFO中最後的數據後追上了寫指針則說明FIFO爲空;當寫指針寫滿一圈後又追上讀指針則說明滿。可是隨之而來又有一個問題,當讀寫指針相等時,究竟是空仍是滿呢?對此,目前採用的方法有兩種:1)指針中增長一個額外的位用於肯定滿或空。2)採用格雷碼完成FIFO空/滿判斷。
法1)在異步FIFO中容易出現問題(將一個二進制的計數值從一個時鐘域同步到另外一個時鐘域時容易出現問題),例如1111在下一刻變成0000,但在實際電路中這個過程可能會持續較長時間,實際須要4個狀態才能實現(例如1111=>1011=>1001=>1000=>0000),若寫時鐘而在這個期間採樣,得出的指針就會是錯誤的。
法2)則能解決這個問題,由於格雷碼每次變換隻有一位發生改變。
3.建立
通常來講,如今使用FIFO時,能夠直接使用公司自帶的IP覈實現,此處以ISE爲例(新建項目就不說了,直接新建文件)。
(1)New Source
(2)選擇IP 並填寫文件名
(3)在Memories&Storage Elements中找到FIFOs
(4)接下來程序會自動打開FIFO Generator
(5)此處選擇讀寫公用時鐘仍是獨立時鐘,採用塊RAM仍是分佈RAM,(我選擇的是獨立時鐘,Block RAM)
(6)接下來選擇寫寬度,寫深度,讀深度,讀寬度。(由於本文舉例的FIFO實在實際工程中,所以根據實際要求作了選擇)
(7)接下來還有一些可選項,能夠依照本身的需求選擇。
(8)在生成以後點擊View HDL Instantiation Template即可以查看接口信息,方便實例化;同時在
(9)同時在自定義的目錄下會生成相關的文件與文件夾,以下圖;其中simulation包含仿真信息。
4.使用(無具體代碼,介紹方法)
fifo_da U2_0_2_F0(
.rst(!rst_n), // FIFO復位信號,高電平有效
.wr_clk(wr_clk), // 寫FIFO時鐘
.wr_en(u_rd_en), // 寫FIFO使能
.din(din), // 寫入FIFO的數據
//寫入:wr_en爲高電平時wr_clk的上升沿會把din寫入fifo中;(同步寫入)
.rd_clk(rd_clk), // 讀FIFO時鐘
.rd_en(rd_en), // 讀FIFO使能
.dout(dout), // 讀出FIFO的數據
.full(full), // output full
.empty(empty) // output empty
//讀出:rd_en爲高電平時,會在下一個rd_clk的上升沿會把fifo的數據讀出;(下一個時鐘數據讀出)
);
5.相關
1)二進制碼轉格雷碼
binarycode = graycode^(graycode>>1);
2)格雷碼轉二進制碼
1 always@(geraycode)begin 2 3 for(i=0;i<n-1;i=i+1) 4 5 binarycode[i]=^(geraycode>>i); 6 7 end
5.參考資料
1)《通訊IC設計》李慶華著