使用異步FIFO同步源自不同時鐘域的數(shù)據(jù)是在數(shù)字IC設計中經(jīng)常使用的方法。在異步FIFO中,讀指針在讀時鐘域,寫指針在寫時鐘域,所以不能單獨運用一個計數(shù)器去產生空滿信號了。因此,須要將寫指針同步到讀時鐘域去產生空信號,將讀指針同步到寫時鐘域去產生滿信號。
對異步FIFO的讀、寫指針進行判斷,我們首先需要將其同步到統(tǒng)一的時鐘域下,而這就引發(fā)出了新的問題—-讀、寫指針在大多數(shù)情況下都不是個單bit信號,而是個多bit信號。如果讀、寫指針直接使用二進制的形式進行同步,則難以避免同步過程中會出現(xiàn)的多個bit信號同時變化的問題。如7(0111)跳轉到8(1000),此時有4個bit信號都發(fā)生了變化,如果直接同步,則由于不同信號之間的延遲(skew)差別,可能導致亞穩(wěn)態(tài)、錯采、漏采等等問題。為解決因可能的skew問題造成的亞穩(wěn)態(tài)所以采用格雷碼異步FIFO,格雷碼每相鄰位之間只有一個比特的變化。FIFO的指針是遞增的,這使得在傳輸遞增的多bit信號時,格雷碼具有天然的優(yōu)勢。
下圖為常見格雷碼異步FIFO組成框圖,包含四個主要部分。FIFO寫控制端用于判斷是否可以寫入數(shù)據(jù),讀控制端用于判斷是否可以讀取數(shù)據(jù),F(xiàn)IFO Memory用于存儲數(shù)據(jù),兩個時鐘同步模塊用于將讀寫時鐘進行同步處理。
下圖為時鐘同步模塊的組成示意圖。寫操作時,時鐘同步模塊先將寫地址指針轉換成格雷碼,然后通過兩級同步器(兩級同步在讀時鐘下進行),將寫地址指針同步到讀時鐘域下;讀操作時,時鐘同步模塊先將讀地址指針轉換成格雷碼,然后通過兩級同步器(兩級同步在寫時鐘下進行),將讀地址指針同步到寫時鐘域下。
格雷碼異步FIFO解決了跨時鐘的數(shù)據(jù)同步化問題,但如果不額外約束還可能存在其他兩個問題;一是格雷碼各比特位延時不一致,導致同步器采樣的地址不符合gray規(guī)律,導致FIFO功能異常;二是格雷碼到兩級同步器的延時太大,導致異步FIFO性能下降。
為了解決上述兩個問題,一般采用set_max_delay來對寫操作時from point(寫地址格雷碼轉換模塊中的最后一個寄存器的時鐘端口)到to point(兩級同步器的第一級寄存器的數(shù)據(jù)端口)的max delay進行約束;對讀操作時from point(讀地址格雷碼轉換模塊中的最后一個寄存器的時鐘端口)到to point(兩級同步器的第一級寄存器的數(shù)據(jù)端口)的max delay進行約束;延時可設置為讀寫時鐘中最快時鐘周期的一半,也可以設置成源端時鐘的一半。例如:
set_max_delay [expr 0.5*$period_fast_clk] -from [get_pins “XX/waddr_gray_reg/CP”] -to [get_pins “XX/synchronizer_2x_r1/D”]
為了解決上述兩個問題,還會使用set_clock_groups -asynchronous將所涉及的讀寫時鐘設置為異步時鐘群組。這種約束和false path的區(qū)別很大;false path會認為該path上的timing arc不用去分析時序、DRV(max trans、max cap 和max fanout 等)以及串擾噪聲情況,也就是說工具會認為false path上的時序和信號質量對設計功能沒影響;set_clock_groups -asynchronous也不分析兩個時鐘域之間的交互的path上時序情況,但是會分析該path上的timing arc的DRV和串擾噪聲情況,保證信號質量。例如:
set_clock_groups -asynchronous -group clock1 -group clock2