您當前的位置:首頁 > 文化

非同步fifo格雷碼同步問題?

作者:由 唐僧洗頭用飄柔 發表于 文化時間:2018-08-17

非同步fifo格雷碼同步問題?張凌2018-08-18 12:23:36

題主不是提到fifo了麼?裡面都是儲存單元啊,傳送端一個一個往fifo裡面寫,寫一個update一次write pointer, 接收端一個一個讀,讀一次update 一次 read pointer。 Write pointer 超過最大值發生上溢位,read pointer 超過最小值發生下溢位。專門有邏輯處理上下溢位的情況,通知兩端停止傳送或接收。

非同步fifo格雷碼同步問題?李虹江2018-08-20 12:55:29

這是非同步FIFO設計中很多初級工程師會困惑的點,也自然而然是面試中經常被問到的問題,這個問題很好的詮釋了什麼叫“知其然而不知其所以然”。

何為知其然?很多工程師在剛接觸到跨時鐘域設計時,通常對於最基本的metastability的原理沒有理解清楚,但是很容易被灌輸了一些工程上的實踐經驗:比如說二進位制碼多bit訊號跨時鐘域不能用double flop來同步單個bit;格雷碼在跨時鐘域的時候因為只有一個bit會變化,所以格雷碼的資料是可以用double flop來同步的,這就是知其然。

何為知其所以然?其實只要再深入問自己一個問題,為什麼簡單的二進位制碼多bit訊號跨時鐘域不能用double flop?如果你的答案只是”因為同步過去之後資料會錯誤“, 那就是不及格的, 你要能夠回答是怎麼錯了,才算合格。

我們來看一個例子,設src_data[2:0] 是二進位制碼的一個up計數器,值的變化為001->010->011->100。。。。

我們以001->010變化為例,在src_clk時鐘沿到來之後,src_data[1]和src_data[0]都發生了反轉。現在假設我們對於每一位都用double flop同步到dst_clk去,dst_clk上的資料之前穩定在001, 那麼當dst

_

clk的上升沿來的時刻和src_data變化的時刻差不多時會發生什麼情況?有可能dst_data會直接變為010, 也有可能會有一個週期是000, 再變為010,也有可能是一個週期變為011,下一個週期再變為010。 這是因為src_data[1]和src_data[0]雖然都由src_clk觸發,但是src_clk到達兩個flop的時間不會完全一樣,總會有先後,導致flop的Q端變化也會有先後。而double flop的第一級flop在latch src_data的時候也可能會latch上不同的值,即bit[0]和bit[1]分別latch上了變化前後的值。另外還有一個原因是如果在dst_clk沿到來的時候src_data的flop的Q正在變化中,也就是在V_ih和V_il之間的時候,double_flop的第一級的D就會latch到一個即不是確定的1也不是確定的0的值,而在這個一個週期內這一級flop會將值穩定在0還是1也是說不準的,以上兩個原因造成了,在dst_clk時鐘域內,用double flop去同步的訊號可能會出現錯誤。注意,

這裡說的多bit在同一個時鐘沿發生翻轉是針對src_clk來說的,而不是dst_clk來說的

,這是回答你這個問題的核心。

那麼格雷碼是怎麼解決這個問題的呢?因為格雷碼被設計成了,在相鄰兩個碼變化時,只會有一個bit發生翻轉。還是以剛才的例子,001->011。 那麼dst_clk時鐘域那邊的data只可能是001->001-011, 或者001->011->011,而不會出現除了這兩個值以外的值。應用在非同步FIFO這邊傳遞pointer來說,pointer必須保證傳遞到對面時可以慢一拍,但是不能有錯誤的值,否則會造成FIFO的空滿邏輯判斷錯誤。

好了,現在在回到最初的問題,如果dst_clk比src_clk慢,然後src_clk那邊的pointer可能在2個src_clk的週期內變了2次,但是在dst_clk的每一個edge來的時候,它只會看到有一個bit在翻轉,其餘的bit都是穩定的!所以這樣同步過去,也可以保證dst_clk那邊的pointer要麼是之前的值,要麼是變化後的值,但一定是

正確

的值。 而FIFO的空滿判斷邏輯依然會判斷正確。

非同步fifo格雷碼同步問題?秦旋2019-12-26 17:03:57

格雷碼過渡不在於慢時鐘域變化多少次

關鍵在於慢時鐘域取樣多bit訊號時,假設一個時鐘沿,可能取樣到格雷碼的狀態一,也可能取樣到格雷碼的狀態二。格雷碼就是用來保證狀態一和狀態二之間只有一bit跳變,從而不會因為不同bit線路延時不同,取樣到某個預期之外的中間態資料導致錯誤。

無論取樣到狀態一,還是狀態二都是有效的,至於狀態一之前的其他狀態,無所謂,不關心。

非同步fifo格雷碼同步問題?城外南風起2021-05-27 14:19:23

想要搞清楚這個問題,首先要知道

為什麼非同步FIFO裡要用格雷碼?

最初學習訊號跨時鐘域傳輸的時候,只是想當然地認為多位元訊號在跨時鐘域傳輸時發生錯誤的機率肯定比單位元大,所以才會採用格雷碼,保證每次只有一位訊號變化,但沒有深入追究這個問題。

在面試官的不斷追問下,我就被問住了。面完以後發現,這個問題在之前看的論文裡已經講得很詳細了[1]。摘錄如下:

The problem is that multiple signals that are synchronized to one clock will experience small data changing skews that can occasionally be sampled on different rising clock edges in a second clock domain。 Even if we could perfectly control and match the trace lengths of the multiple signals, differences in rise and fall times as well as process variations across a die could introduce enough skew to cause sampling failures on otherwise carefully matched traces。

大意是每個位元之間總有一些小的skew,導致它們無法被在同一個時鐘沿被取樣。即便在佈局佈線的時候完美地控制它們的路徑長度,每個位元訊號的上升下降時間、die上的加工工藝差異分佈也會引起skew。

作者給了一個具體的例子:

If a simple 4-bit binary counter changes from address 7 (binary 0111) to address 8 (binary 1000), all four counter bits will change at the same time。 If a synchronizing clock edge comes in the middle of this transition, it is possible that any 4-bit binary pattern could be sampled and synchronized into the new clock domain。

四位二進位制碼從0111變為1000的過程中,這兩個數雖然在數值上相鄰,但它們的每個位元都將發生改變,這時如果它們之間有skew,取樣的值就可能是任意的四位二進位制數,這會給空滿標誌的判斷帶來問題,如果錯誤觸發空滿標誌還好,但如果在空滿成立時沒有觸發,就會導致資料被覆蓋掉或者重複讀出。

如果使用格雷碼,每次只改變一位訊號,就不會出現上述的問題。例如,格雷碼從0001遞增到0011時,即便沒有采集到變化後的0011,也會採集到變化之前的0001,這隻會導致“不該報空滿而報了空滿”,但並不會導致“該報空滿而未報”的情況。詳細來說,如果是讀指標從0001遞增到0011,假設寫時鐘域採到的是0001,那麼也只是會報寫滿(因為寫時鐘域不知道讀時鐘域已經讀到下一個地址了),從而停止寫入,這是安全的;同理,如果是寫指標從0001遞增到0011,假設讀時鐘域採到的是0001,那麼也只是會報讀空(因為讀時鐘域不知道寫時鐘域已經寫到下一個地址了),從而停止讀出,這也是安全的。

現在我們知道了格雷碼之於非同步fifo的重要性,就可以回答題主的問題了。

如果寫時鐘頻率很高,相對讀時鐘是一個快時鐘,那麼如果讀時鐘域才讀了一個數,寫時鐘域就寫了兩三個數,寫地址也隨之變化了兩三次,這是否會引起多bit跨時鐘域的問題呢?舉個例子,如果現在同步到讀時鐘域的格雷碼寫指標是011,而寫時鐘快很多,寫時鐘域的格雷碼寫指標已經發生變化:011→010→110,在讀時鐘域這邊,就需要直接同步110,那麼,讀時鐘域的格雷碼寫指標就會從011變為110,第0位和第2位都發生變化,這會在取樣時造成影響嗎?

答案是不會。

變兩位就變兩位呀,管他幹什麼?

讀時鐘域的格雷碼寫指標是為了去和讀指標作比較的

,變兩位才是好事,變一位反而得不到正確的空訊號。進一步地,我們所說的多bit訊號跨時鐘域傳輸問題中的多bit是針對源時鐘域(即寫時鐘域)而言的,在之前的例子中,如果不用格雷碼,寫指標變化順序為:010→011→100,

在011變為100的過程中,所有位都發生變化

,目標時鐘域(讀時鐘域)取樣時寫指標會無法確定,可能是任意3位二進位制數。但是,如果使用了格雷碼,變化順序為:011→010→110,注意,

這個變化次序是逐個的,並不是從011直接變為110

,所以,即便讀時鐘域已經同步了011,寫時鐘域的寫指標又由於變化太快變到了110,同步時刻來臨時,取樣值也要麼是010(沒采到第2位的變化),要麼是110(採到第2位的變化)。

關鍵是理清一個點:多bit變化的含義是寫時鐘域的寫指標相對於前一個寫時鐘域的寫指標的變化,而不是寫時鐘域的寫指標相對於讀時鐘域的寫指標之間的變化。

如果不使用格雷碼,多bit變化將使取樣紊亂,

使用格雷碼,將多bit變化變為單bit變化,就不會採到錯誤的值,即便採到變化前的值,也是安全、正確的

參考文獻:

[1] CUMMINGS C E。Clock domain crossing (CDC) design&verification techniques using systemverilog[EB/OL]。[2008-09-26]。

http://www。

sunburst-design。com/pap

ers

本回答引自我的文章,連結如下:

跨時鐘域傳輸的黃金搭檔:非同步FIFO與格雷碼verilog實現格雷碼(Gray Code)與二進位制編碼轉換

我是城外南風起,歡迎關注我的公眾號【

木葉芯

】。

非同步fifo格雷碼同步問題?LiuShengrong2021-08-28 02:30:44

解釋這個問題,首先要明確的是亞穩態產生的原因。以單bit訊號為例,簡單來說,當目標時鐘域對源時鐘域的訊號進行取樣時,如果該訊號正處於由0到1,或者由1到0的變化過程中,就有可能產生亞穩態。對於單bit訊號,可以用“打兩拍”的方法,降低亞穩態發生的機率。

對於多bit訊號來說,同一時刻可能會有多個訊號處於由0到1,或者由1到0的變化過程中。在這種情況下,如果簡單地對每個訊號都進行“打兩拍”的處理,將導致目標時鐘域有可能採到一個完全錯誤的值,這顯然是不可取的。

那麼使用格雷碼為什麼沒有這種問題呢,以題主所描述的情況為例,慢時鐘域(目標時鐘域)對快時鐘域(源時鐘域)的訊號進行取樣,本次取樣到的訊號,與上次取樣到的訊號相比,有2bit的變化,但是這2bit的變化並不是同時發生的,而是先後發生的,間隔的時間就是快時鐘域的時鐘週期。也就是說,由於格雷碼的性質,在慢時鐘域對快時鐘域的格雷碼訊號進行取樣時,最多隻有1bit訊號

正在變化

,其它bit的訊號雖然可能與上一次取樣時不同,但是它們的變化已經在之前的時刻(一般是快時鐘域的時鐘上升沿)完成,在此刻已經是一個

穩定

的訊號了。

標簽: 時鐘  bit  格雷  CLK  src