您當前的位置:首頁 > 繪畫

非同步FIFO的實現(從verilog程式碼到波形)上

作者:由 上進的京 發表于 繪畫時間:2021-12-24

一、

非同步fifo的簡單介紹

我們知道,fifo最簡易的結構可以由一個DPRRAM實現,只不過fifo不需要地址,每個資料的存取位置都是順序變化的(遵守先進先出的原則),這一點是與正常的儲存器不同的地方。

在設計之前,首先需要明白以下這些問題:

1.何為同步和非同步?

首先要理清我們所說的“同步”與“非同步”的關係。上一篇文章也有提到,“同步”是指時序邏輯的訊號變化是基於同一個時鐘。若訊號是基於不同的時鐘變化,比如clk1和clk2(這兩個時鐘沒有確定的相位關係)稱為非同步。所以,這裡所說的非同步fifo則是讀時鐘和寫時鐘為非同步的fifo。對於非同步fifo,其中有一個很重要的點在於“跨時鐘域處理”。

在處理器和外設之間,一般處理器的資料吞吐率很高,使用非同步fifo就能避免這種速度差異造成的資料丟失問題

2.為什麼要跨時鐘域處理呢?

因為在同步fifo中,我們知道,產生空滿訊號時根據fifo_cnt計數產生。但是在非同步fifo中,由於有兩個不同的時鐘,所以不能單獨使用一個計數器去產生空滿訊號了。因此,我們透過對比讀寫指標來確定空滿,但是讀寫指標在不同的時鐘域,不能直接進行比較,需要將寫指標同步到讀時鐘域,或者將讀指標同步到寫時鐘域。但此時容易出現亞穩態問題。

3.如何進行跨時鐘域處理?

這裡首先介紹“同步器”,對於單bit訊號,從慢時鐘到快時鐘,我們可以透過同步器進行打兩拍的方式進行同步(打一拍取樣可能為亞穩態,打三拍取樣有多餘)。從快時鐘到慢時鐘需要先對訊號進行展寬,展寬為至少一個慢clk的寬度。

非同步FIFO的實現(從verilog程式碼到波形)上

但是對於多bit訊號,不能直接透過同步器去實現同步,因為每個bit的延時不同,取樣可能會採到亞穩態。 考慮到格雷碼具有一定的特殊性:每次當從一個值變化到另外一個值時,有且只有一位發生變化,因此可以用同步器進行同步(只有深度為2的n次方才能用格雷碼的方式去同步,這樣才能保證最大值和最小值只有一位的變化)。我們可以將寫指標轉為格雷碼同步到讀時鐘域再和讀指標進行比較。

4.在進行同步之後,如何產生空滿訊號呢?

空訊號:讀指標等於寫指標(復位時,或者讀指標追上寫指標)

滿訊號:寫指標等於讀指標(寫更快,寫完一圈追上讀指標)

在避免讀寫指標相同時,不知道到底是滿還是空,因此在讀寫指標中額外增加一位,這一位用於表示是否已經發生迴環,但這一位不需要存入memory中。

非同步FIFO的實現(從verilog程式碼到波形)上

5.補充自然二進位制和二進位制格雷碼之間的相互轉換公式:

二進位制轉格雷碼:最高位保留,其他各位為該位的二進位制碼異或上一位的二進位制碼。

格雷碼轉二進位制:最高位保留,其餘各位為該位的二進位制碼異或上一位的格雷碼。

二、 非同步fifo的verilog設計

1。首先定義引數(和同步fifo一樣)、非同步fifo的介面訊號,另外定義了一個內部引數:地址位寬。

非同步FIFO的實現(從verilog程式碼到波形)上

2。定義內部訊號,這些訊號後面都要用到,寫的時候也不必一開始就全部寫全,需要用到的時候在補充。這些內部訊號分別是:讀(寫)地址、下一個讀(寫)地址;寫(讀)地址的格雷碼、下一個寫(讀)地址的格雷碼、寫(讀)地址格雷碼的讀(寫)同步;讀(寫)地址的格雷碼的寫(讀)同步的二進位制碼。以及fifo用於讀(寫)所用的個數。以上這些訊號將用於產生空滿訊號。另外還有讀寫有效等(用於傳遞給dualport_ram)。

非同步FIFO的實現(從verilog程式碼到波形)上

3。產生讀寫有效訊號(往memory中寫或者讀的有效訊號):寫有效發生在寫使能為1且未滿的情況,讀有效發生在讀使能為1且非空的情況。此時另外設計了一個雙埠的ram,在本設計中直接呼叫即可。

非同步FIFO的實現(從verilog程式碼到波形)上

4。接下來對讀寫地址進行控制。寫有效時,下一個寫地址加1(為組合邏輯),在由寫時鐘將下一個寫地址賦給當前寫地址。讀地址的控制類似。

非同步FIFO的實現(從verilog程式碼到波形)上

5。產生下一位寫地址格雷碼(下一位寫地址右移一位異或本身),並用暫存器存起來。下一位讀地址格雷碼的產生也類似。

非同步FIFO的實現(從verilog程式碼到波形)上

6。用寫時鐘去同步讀地址(用於產生滿訊號),用讀時鐘去同步寫地址(用於產生空訊號)。實現方式具體是:透過將讀地址的格雷碼在寫時鐘域進行打兩拍,寫地址的格雷碼在讀時鐘域進行打兩拍。並用暫存器存起來。

非同步FIFO的實現(從verilog程式碼到波形)上

非同步FIFO的實現(從verilog程式碼到波形)上

7。好啦,到這裡我們終於可以用我們前面準備好的訊號去產生空滿訊號了。先準備好一個full_comb(組合邏輯的滿),當下一個寫的地址的格雷碼和讀地址格雷碼的寫同步的高兩位相反,低兩位相同的時候為1。因為組合邏輯的滿是早於時序的滿,因此組合邏輯的滿的產生我們用的下一時刻的地址。在基於寫時鐘將full_comb賦值給full。另一方面,empty_comb當下一個讀地址格雷碼與寫地址格雷碼的讀同步相同時為1,並基於讀時鐘賦給empty訊號。

非同步FIFO的實現(從verilog程式碼到波形)上

8。接下來,產生afull訊號。因為此時我們需要統計fifo已經佔用多少個儲存單元,因此我們要做差,而做差操作二進位制更好實現。因此我們將地址轉為二進位制。已經有資料的儲存單元個數為下一個寫地址減去讀地址格雷碼的寫同步的二進位制碼,當其大於儲存單元數-1時,產生組合邏輯的幾乎滿訊號,在寫時鐘下產生時序邏輯的幾乎滿訊號。幾乎空訊號的產生思路類似。

非同步FIFO的實現(從verilog程式碼到波形)上

非同步FIFO的實現(從verilog程式碼到波形)上

哇!長舒一口氣,我們的非同步fifo的模組的設計部分就完成啦!238行程式碼,比同步fifo確實多了不少。由於篇幅有點長了,dualpot_ram設計、tb搭建和波形下期再見吼!

非同步FIFO的實現(從verilog程式碼到波形)上

標簽: 時鐘  地址  FIFO  格雷  訊號