2019.12.10補充
結論:先寫進的數據在獨處時位於高位,后寫入的數據在低位,且排序單位為Byte,即先后寫入0X01,0X02,讀出后也為0x010x02,此外,在寫入數據量達到讀出數據位寬后5個時鍾empty才會拉低。
過程:
犯傻的時候想到,不同位寬數據進出時可能有一個先后順序的問題,通過在數據手冊上看到這張圖后發現對於寫入位寬小於讀出位寬時(write_witdh<read_witdh),先寫進的數據在讀出時位於低位,后寫入的數據在高位。
不過在仿真中發現,先進的的在MSB處,后進的在LSB處。。。。。服了 ,此外可以看到,fifo的empty信號,即空標志有效在從寫入到拉低,經歷了13個時鍾周期(稍后驗證),在這段時間內,實測是不能讀寫的。(這個FIFO的設置為writh_witdh為24bit,read_witdh為192bit)
為了驗證這13個周期是否是固定的還是什么別的原因造成,我做了幾個小測試,
1.寫入第一個數據后,過一段時間再給入剩余數據,總數據量為192bit。在五個時鍾周期后empty為低。
2.寫入數據未到read_witdh(192bit),empty一直為高。
所以,可以得到結論,當寫入數據量達到讀取位寬時,empty才會在五個時鍾信號后拉低。
1.簡介
定義:
FIFO(First In First Out)一種先入先出(讀寫數據是只能順序寫入順序讀出)的數據緩存器,讀寫數據時,其內部讀寫指針自動加1,因此沒有外部地址線,使用簡單。
分類:
FIFO可以分為同步FIFO和異步FIFO。同步FIFO的寫入時鍾和讀取時鍾完全一樣,內核時一個簡單雙口RAM(Simple Dual Port RAM);異步FIFO寫入時鍾和讀取時鍾不同,不僅需要真雙口RAM(True Dual Port RAM),還需要專門的握手信號進行跨時鍾域的數據傳遞。
用途:
1)使用異步FIFO進行跨時鍾域交互數據;2)進行不同數據寬度的讀寫匹配;3)對高速突發數據進行平均處理,降低瞬時處理速率。
使用場景:
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設計》李慶華著