天天看點

格雷碼在異步FIFO中的使用

異步FIFO通過比較讀寫位址進行滿空判斷,但是讀寫位址屬于不同的時鐘域,是以在比較之前需要先将讀寫位址進行同步處理,将寫位址同步到讀時鐘域再和讀位址比較進行FIFO空狀态判斷(同步後的寫位址一定是小于或者等于目前的寫位址,是以此時判斷FIFO為空不一定是真空,這樣更保守),将讀位址同步到寫時鐘域再和寫位址比較進行FIFO滿狀态判斷(同步後的讀位址一定是小于或者等于目前的讀位址,是以此時判斷FIFO為滿不一定是真空,這樣更保守),這樣可以保證FIFO的特性:FIFO空之後不能繼續讀取,FIFO滿之後不能繼續寫入。

大多數情形下,異步FIFO兩端的時鐘不是同頻的,或者讀快寫慢,或者讀慢寫快,這時候進行位址同步的時候,可能會有位址遺漏,以讀慢寫快為例,進行滿标志判斷的時候需要将讀位址同步到寫時鐘域,因為讀慢寫快,是以不會有讀位址遺漏,同步後的讀位址滞後目前讀位址,是以可能滿标志會提前産生。進行空标志判斷的時候需要将寫位址同步到讀位址,因為讀慢寫快,是以當讀時鐘同步寫位址的時候,必然會漏掉一部分寫位址(寫時鐘快,寫位址随寫時鐘翻轉,直到滿标志出現為止),那到底讀時鐘會同步到哪個寫位址?不必在意是哪一個,我們關注的是漏掉的位址會不會對FIFO的空标志産生影響。比如寫位址從0寫到10,期間讀時鐘域隻同步到了2,5,7這三個寫位址,漏掉了其他位址。同步到7位址時,真實的寫位址可能已經寫到10位址,相當于“在讀時鐘域還沒來得及覺察的情況下,寫時鐘域可能偷偷寫了資料到FIFO去”,這樣在比較讀寫位址的時候不會産生FIFO“空”讀操作。漏掉的位址也沒有對FIFO的邏輯操作産生影響。

我們可以對異步FIFO的位址采用binary編碼,這樣并不影響異步FIFO的功能,前提是讀寫位址同步時能夠保持正确。這種情況在功能仿真時完全正确,問題隻有到時序仿真時才會遇到。毛刺可以說是異步電路的殺手,一個毛刺被觸發器采樣後會被放大,然後傳播,導緻電路功能出錯。binary編碼的位址總線在跳變時極易産生毛刺,因為binary編碼是多位跳變,在實作電路時不可能做到所有的位址總線等長,address bus skew必然存在,而且寫位址和讀位址分屬不同時鐘域,讀寫時鐘完全異步,這樣位址總線在進行同步過程中出錯不可避免,比如寫位址在從0111到1000轉換時4條位址線同時跳變,這樣讀時鐘在進行寫位址同步後得到的寫位址可能是0000-1111的某個值,這個完全不能确定,是以用這個同步後的寫位址進行FIFO空判斷的時候難免出錯。

這個時候gray碼展現了價值,一次隻有一位資料發生變化,這樣在進行位址同步的時候,隻有兩種情況:1.位址同步正确;2.位址同步出錯,但是隻有1位出錯;第一種正确的情況不需要分析,我們關注第二種,假設寫位址從000->001,讀時鐘域同步出錯,寫位址為000->000,也就是位址沒有跳變,但是用這個錯誤的寫位址去做空判斷不會出錯,最多是讓空标志在FIFO不是真正空的時候産生,而不會出現空讀的情形。是以gray碼保證的是同步後的讀寫位址即使在出錯的情形下依然能夠保證FIFO功能的正确性,當然同步後的讀寫位址出錯總是存在的(因為時鐘異步,采樣點不确定)。這裡需要注意gray碼隻是在相鄰兩次跳變之間才會出現隻有1位資料不一緻的情形,超過兩個周期則不一定,所有位址總線bus skew一定不能超過一個周期,否則可能出現gray碼多位資料跳變的情況,這個時候gray碼就失去了作用,因為這時候同步後的位址已經不能保證隻有1位跳變了。

另外需要将位址總線打兩拍,這是為了避免亞穩态傳播,理論上将打兩拍不能消除亞穩态現象,因為時鐘異步,亞穩态不可避免,但是可以極大降低亞穩态傳播的機率,低頻情況下甚至STA不需要分析這裡的異步時序,因為寄存器都可以在一拍内将亞穩态消除,恢複到正常0/1态。而在高頻情況下則不一定,尤其在28nm工藝以下,需要檢查兩級觸發器的延遲,保證延遲低,這樣可以提高Tr,提高系統MTBF。

異步FIFO使用格雷碼的唯一目的就是“即使在亞穩态進行讀寫指針抽樣也能進行正确的空滿狀态判斷”。

回答一: 格雷碼是的确非常有用。它的特點就是相鄰碼隻有一位發生翻轉,比如00->01->11->10->00...

在編寫狀态機時,我也喜歡用這種相鄰狀态隻發生一位翻轉的編碼。這樣從一個狀态切換到下一個狀态,就隻有一位寄存器發生變化。這麼做可以帶來降低功耗的好處,因為寄存器的翻轉是消耗動态功耗的,而這種編碼将翻轉的次數降到最低,所有有利于降低功耗。 回答二: 你說的降低功耗的前提是,一個狀态到下一個狀态的變化也要遵循格雷碼連續的變化,否則,就不成立了。比如:如你所說,00<->01<->11<->10這樣的變化,确實是有利于降低功耗;但是,狀态的變化不一定就是這樣變化,它有可能是00<->11,01<->10這樣的變化,那麼你說的有利于降低功耗就不成立。  回答三:  低功耗設計的内容還是很博大精深的。如何合理的選擇信号形式,以使得系統在發生狀态變化時隻有少數信号發生翻轉?所依賴的公式為

P=a*C*V^2*f

其中a為信号翻轉率,C為系統等效電容,V為電路驅動電壓,f為時鐘頻率。使用格雷碼降低功耗就是想使a小下來。當然如果電路中做不到嚴格的格雷碼也沒關系,隻要是有利于減小a的,就有利于功耗的降低。

期待牛人能對低功耗設計的内容普及一下。在移動的智能終端上低功耗的問題已經越來越受重視了。

回答四: 主要是為了多比特同步,這個例子中功耗是次要的因素  回答五:  格雷碼有兩個作用,一是消除多個比特同時變化帶來的潛在競争與冒險,二是降低功耗(翻轉次數減少)。在狀态機中通常為了簡單起見表示現态與次态的狀态參數并不使用格雷碼而是二進制碼,因為一個狀态的變化可能是發散的而非單向的,就是說不同的條件對應不同的次态,這個時候用格雷碼對狀态進行編碼達不到一次隻變化一位的目的,除非在特殊情況下,即狀态機的變化是單向的,總是由S0到S1,再到S2,等等,這個時候用格雷碼就能達到原來的目的。  回答六:  十進制計數容易産生毛刺,格雷碼則不會産生毛刺。  回答七:  格雷碼每次隻有一位跳變,兩級寄存才安全。  回答八: 在異步的FIFO中,采用格雷碼進行計數,相鄰的資料僅僅隻有1bit變化,這樣在兩個時鐘域同步的時候僅僅可能隻有1bit産生亞穩态,通過同步以後,亞穩态可以消除,最壞的情況是這1bit采錯,但是即使是采錯位址也隻是相差1個,這對判斷空滿标志不會産生影響。 如果是采用10十進制進行編碼,則相鄰的資料可能有很多位同時進行變化,那麼如果多位同時産生亞穩态而且同時采錯資料,會對寄存器的空滿标志做出嚴重錯誤的判斷,會丢失資料或者讀出無用的資料,使系統出錯。  回答九: 由于跳變減少,可減少功耗,多用于低功耗設計中。  回答十:  我在想這個問題,如果單指gray的話确實如此,但是在實際應用中,往往是将二進制的轉換成gray,就是說不管如何二進制的數依然會存在同時其轉換的外加邏輯必然會帶來損耗。在多比特的情況,功耗是否會跟多呢?gray一般是用在不同時鐘域的連續數值的傳送,即資料必須是遞增或遞減的。這樣,其主要是在asynchronou fifo中使用,感覺功耗并不會下降