跨時鍾域處理--最終詳盡版
為了徹底理解跨時鍾域問題,多方搜集資料,做個簡單整理備忘。主要參考了如下幾個資源:
- https://zhuanlan.zhihu.com/p/45186793 跟IC君一起學習集成電路
- https://www.cnblogs.com/PG13/p/10329678.html 新芯時代
- 格雷碼 https://www.cnblogs.com/zhuruibi/p/8988044.html
- 主要參考來源:“ASIC 中的異步時序設計” 王夏泉 華中科技大學
- 主要參考來源: "Clock Domain Crossing (CDC) Design & Verification Techniques Using SystemVerilog"
- https://blog.csdn.net/lovingduo/article/details/77723219
1. 異步時序定義
異步時序設計指的是在設計中有兩個或以上的時鍾, 且時鍾之間是同頻不同相或不同頻率的關系。而異步時序設計的關鍵就是把數據或控制信號正確地進行跨時鍾域傳輸。
2. 亞穩態
每一個觸發器都有其規定的建立(setup)和保持(hold)時間參數, 在這個時間參數內, 輸入信號在時鍾的上升沿是不允許發生變的。 如果在信號的建立時間中對其進行采樣, 得到的結果將是不可預知的,即亞穩態。
觸發器進入亞穩態的時間可以用參數 MTBF(mean time between failures)來描述, MTBF即觸發器采樣失敗的時間間隔,其公式描述如下:
其中:
- trtr = 分辨時間(時鍾沿開始)
- τ,T0τ,T0 = 觸發器參數
- ff = 采樣時鍾頻率
- a = 異步事件觸發頻率
通常,MTBF越大說明系統采樣失敗的可能越小。可見,對於高速的設計,MTBF是更容易發生的。對於一個典型的 0.25µm 工藝的 ASIC 庫中的一個觸發器,我們取如下的參數:
tr = 2.3ns, τ = 0.31ns, T0 = 9.6as, f=100MHZ, a = 10MHZ, MTBF = 2.01 days
也就是說觸發器以100MHZ工作,假設異步事件觸發的頻率,也就是數據變化的頻率跟采樣時鍾頻率相同。我們用10MHZ的頻率去不停地采它的數據,每個上升沿數據都會發生變化,則每兩天就可能采集到一次亞穩態(個人理解,如有誤請指正)。如果使用單鎖存器同步,b的時鍾上升沿采集a的數據時很可能采到亞穩態數據。
3. 單比特同步策略
方法一:雙鎖存器
為了避免亞穩態,應該使得MTBF盡量大。采用雙鎖存器可以改善這一問題:
當使用了雙鎖存器以后, b_dat2 的MTBF由以下公式可以得出:
如果我們仍然使用上一節所提供的參數,則b_dat2 的MTBF為 9.57*109(years)。由上述結果可以看出,雙鎖存器法可以消除亞穩態問題。
注意問題1
時鍾域B兩級同步的寄存器跟時鍾域A的輸出寄存器之間不能有組合邏輯。組合邏輯電路各個輸入信號的不一致性以及組合邏輯內部路徑的延時時間不一樣,運算后的信號存在毛刺如圖(2),我們無法預先知道CLKB 的上升沿何時會到來,CLKB 采樣到的信號就無法預知。
因此,要想CLKB 能采到穩定的信號,時鍾域A的信號必須是經過CLKA 敲過,在一個時鍾周期內是穩定的信號,如圖(3)所示:
注意問題2
Clock-gating enable 信號沒有經過異步處理:
在下圖中a_in 信號經過CLKA的DFF敲過,再送到兩級DFF 同步器處理,完全沒毛病。但是F2的使能信號EN是從時鍾域A來的,當EN信號變化的時候,由於時鍾域不一樣,無法保證使能之后的CLKB信號采樣數據時滿足setup/hold time 要求,這時F2輸出信號也就變得無法預測了。因此對clk gating的信號也要做處理。
注意問題3
如果較快的時鍾域是較慢時鍾域頻率的1.5倍(或更多),那么將較慢的控制信號同步到較快的時鍾域通常不是問題,因為較快的時鍾信號將采樣較慢的CDC信號一次或多次。因此將快采慢比慢采快引起的潛在問題更少,所以對於快采慢的情況,使用簡單的兩個觸發器同步器在時鍾域之間傳遞單個Clock Domain Crossing (CDC)信號即可。
而對於慢采快的情況則最好更加穩妥些,一般要求在接收時鍾域中采樣信號要保持三個時鍾上升沿的時間("three edge" requirement),也就是1.5倍的采樣時鍾周期。一般來說1.25倍也夠。
如果采樣信號維持時間過短,則慢時鍾域很可能會漏采:
即使采樣信號比采樣周期略長,也可能會面臨信號改變正好落在時鍾沿的setup和hold violation的區域:
解決方案:
1.開環地控制信號的長度
不需要知道接收時鍾域的邊沿信息,只要在發送域保證發送信號的長度就可以。
2.閉環控制
采用反饋信號自動延長快時鍾域的信號:
將A時鍾域要傳輸的信號打一拍送到B域中進行雙reg同步,同步之后的信號在反饋會A中,A中再進行雙reg同步,當A域中反饋同步信號變為高時才將被采信號拉低,這樣的方法時比較穩妥的,但是會有更多的延時,並且需要更多同步reg。 例如下圖就是采用閉環延長信號的一個方法:
FF1由源時鍾驅動,輸入變高,FF1輸出變高。FF1的Q輸出反饋通過與門和或門保證了在FF5輸出為0時,只要FF1輸出變高,FF1輸出就一直保持高。直到FF3同步輸出變成1后,FF5輸出變成1,與門輸出0。這時只要輸入為0,FF1輸出即為0
擴展*
同樣一個快時鍾域的脈沖信號,其寬度只有快時鍾域的一個周期的長度,現在需要將該信號同步到一個相對較慢的時鍾域,如果要求不能在快時鍾域將脈沖信號展寬,並且同樣采用雙寄存器同步,該如何實現?
下面的這個電路可以解決這一問題:
這個電路跟異步復位同步釋放很像,其原理是通過把要處理的異步脈沖當作第一個DFF的時鍾輸入,這樣當有脈沖時該級會拉高,之后后面兩級同步器檢測到后將第一個DFF置位,這樣第一個DFF就置為0,后級之后也變為0. 這種同步器的好處在於不需要再源時鍾域對信號做處理,但是缺點也很明顯,因為需要將信號作為時鍾,會消耗額外的時鍾資源,並且該信號的毛刺會導致不可預知的錯誤。 所以上面這種同步器實際上不推薦使用。還是老老實實展寬脈沖吧。
4.多比特同步策略
經常會遇到多個比特的控制信號或者數據信號跨時鍾域傳輸的問題,解決這類問題的出發點主要有:
- 盡可能將這些信號合並成單bit
- Multi-cycle path (MCP). 使用同步信號。
- 使用Gray碼
控制信號多比特同步
同步變化的控制信號
例如下面的例子,load和en作為兩個控制信號需要跨時鍾同步。兩個信號可能需要同時拉高才能正確操作,但是實際同步時可能兩者存在一定skew,導致再同步域兩級reg同步后兩個信號錯開,導致控制失敗:
這種解決辦法也很簡單,只要將他們合並成一個即可:
控制信號多比特之間有一定時鍾相位差
這種情況下,如果兩個信號隔開固定的相位,在傳輸過程中可能會有一定偏移,則同步時也會導致下面的問題:
可見,ld2信號和ld1信號的相位間隔被改變了,而這通常不是我們希望的。解決辦法是只傳輸其中一個信號,另一個信號在同步域內產生。例如上面的例子可以將ld1在B時鍾域通過ld1打一拍得到:
數據多比特同步
在數據的多比特傳輸時更要注意skew的問題,如果bit之間有skew,則傳輸值很可能出錯:
主要有兩類解決方法: 1. Multi-Cycle Path (MCP) formulation 多周期路徑規划(名字怪怪的,感覺就是握手機制) 2. FIFO
方法一:脈沖同步法(開環的結繩法)
首先用到的一個電路是脈沖產生電路:
一個典型的脈沖同步器用於信號同步的例子:
或者還有另一個版本更加清楚一些:
脈沖同步器的工作方式如下:
- 在A時鍾域產生一組單周期脈沖,其間隔至少需要比B時鍾域的兩個時鍾周期大,否則B中無法進行邊沿檢測。同時這組脈沖也表示了A中數據傳送的開始和結束。
- 在A時鍾域中,兩個脈沖被電平翻轉器(可以由異或門或者mux+inv構成)將脈沖之間的區域變為一段高電平(結繩toggle)
- A中的結繩信號在B中通過邊沿產生器翻譯為兩個單周期脈沖
- B中需要由邏輯去監測脈沖並進行信號的采樣
仿真案例:
(有時間再自己寫個仿真下)
方法二:閉環結繩法
上面的脈沖同步信號實際上是開環產生的,需要考慮B時鍾域的周期寬度。而下面這種閉環方式解決了這個問題:
其具體原理是:
- 首先,asend生成一個脈沖,經過結繩、解繩到B中變為另一個脈沖
- 該脈沖反饋回A中通過邊沿采樣變回A中的單周期脈沖(因為這邊討論的是慢采快,所以A總能采到B的單周期脈沖)
- 一個簡單的FSM接受反饋的脈沖並給出ready信號,表示單次采樣結束,A模塊可以改變adata的數據了,同時控制asend信號給出一個新的脈沖,代表單次傳輸結束,結繩解繩到B中后B也接受到了結束脈沖。
上面的這種方法還是不夠完備,因為反饋信號也是單周期脈沖,在上面第二步中可以發現,如果A的頻率比B慢,采不到脈沖豈不是僵硬,所以為了通用,慢采快還是快采慢都能適配,干脆在B中也加入A的的結繩以及FSM來控制整個流程,原理圖如下:
可見,B中的狀態機接收到脈沖后輸出valid信號告訴外面B可以采數據了,bload置高,數據開始采樣,之后b_ack置高,送入A中產生結束脈沖,結束脈沖返回B中后FSM跳回not valid狀態,一次傳輸結束。
下面是上面的簡陋版本:
其中標明_clk1 的信號表示該信號屬於 clk1 時鍾域, 同理標明_clk2 的信號表示該信號屬於 clk2 時鍾域。在兩次src_req_clk1 之間被 src_vld_clk1“ 結繩” (pluse2toggle),在將src_vld_clk1 用雙鎖存器同步以后, 將該信號轉換為 dst_req_clk2(toggle2pluse)。同理,用dst_vld_clk2 將 dst_req_clk2“結繩”, dst_vld_clk2 表明在 clk2 時鍾域中, src_dat_clk1 已經可以進行正確采樣了。 最后將 dst_vld_clk2 轉換為 dst_ack_clk1(synchronizer and toggle2pluse), dst_ack_clk1 表明 src_dat_clk1 已經被 clk2 正確采樣了, 此后 clk1 時鍾域就可以安全地傳輸下一個數據了。 可以看出,“結繩法” 關鍵是將信號結繩以后, 使其保持了足夠長的時間,以便另一個時鍾可以正確地采樣。
電路圖如下:
上圖描述了握手協議的完整流程,其中三角帶橫線的符號是異或門。同時給出了兩個脈沖之間結繩信號(vld信號)的產生方法。
總之:
- 優點:“結繩法” 可以解決快時鍾域向慢時鍾域過渡的問題, 且其適用的范圍很廣。
- 缺點:實現較為復雜,特別是其效率不高,在對設計性能要求較高的場合應該慎用。
方法三:異步雙口RAM+格雷碼(異步FIFO)
處理多bit數據的跨時鍾域,一般采用異步雙口RAM。假設我們現在有一個信號采集平台,ADC芯片提供源同步時鍾60MHz,ADC芯片輸出的數據在60MHz的時鍾上升沿變化,而FPGA內部需要使用100MHz的時鍾來處理ADC采集到的數據(多bit)。
在這種類似的場景中,我們便可以使用異步雙口RAM來做跨時鍾域處理。先利用ADC芯片提供的60MHz時鍾將ADC輸出的數據寫入異步雙口RAM,然后使用100MHz的時鍾從RAM中讀出。
但我們讀出RAM中的數據時,肯定不是一上電就直接讀取,而是要等RAM中有ADC的數據之后才去讀RAM。這就需要100MHz的時鍾對RAM的寫地址進行判斷,當寫地址大於某個值之后再去讀取RAM。
在這個場景中,其實很多人都是使用直接用100MHz的時鍾對RAM的寫地址進行打兩拍的方式,但RAM的寫地址屬於多bit,如果單純只是打兩拍,那不一定能確保寫地址數據的每一個bit在100MHz的時鍾域變化都是同步的,肯定有一個先后順序。如果在低速的環境中不一定會出錯,在高速的環境下就不一定能保證了。所以更為妥當的一種處理方法就是使用格雷碼轉換。
格雷碼簡介
在一組數的編碼中,若任意兩個相鄰的代碼只有一位二進制數不同,則稱這種編碼為格雷碼(Gray Code),另外由於最大數與最小數之間也僅一位數不同,即“首尾相連”,因此又稱循環碼或反射碼。格雷碼(Gray Code)又稱Grey Code、葛萊碼、格萊碼、戈萊碼、循環碼、反射二進制碼、最小差錯碼等。
格雷碼有多種編碼形式
十進制數 | 4位自然二進制碼 | 4位典型格雷碼 | 十進制余三格雷碼 | 十進制空六格雷碼 | 十進制跳六格雷碼 | 步進碼 |
---|---|---|---|---|---|---|
0 | 0000 | 0000 | 0010 | 0000 | 0000 | 00000 |
1 | 0001 | 0001 | 0110 | 0001 | 0001 | 00001 |
2 | 0010 | 0011 | 0111 | 0011 | 0011 | 00011 |
表中典型格雷碼具有代表性。若不作特別說明,格雷碼就是指典型格雷碼,它可從自然二進制碼轉換而來。
二進制格雷碼的生成方法有很多,具體可自行搜索或見:
https://www.cnblogs.com/zhuruibi/p/8988044.html
回到剛才的問題,多比特利用雙寄存器打兩拍在高速場合不再適用,而使用格雷碼可以將這種多比特變為單比特傳輸(格雷碼每次變化只有一位會變)如果先將RAM的寫地址轉為格雷碼,然后再將寫地址的格雷碼進行打兩拍,之后再在RAM的讀時鍾域將格雷碼恢復成10進制。這種處理就相當於對單bit數據的跨時鍾域處理了。
異步FIFO
使用異步雙口ram的場合其實用異步fifo也是一樣的。
使用場景:在有大量的數據需要進行跨時鍾域傳輸, 並且對數據傳輸速度要求比較高的場合 。
一個異步 FIFO 一般由如下部分組成:
1. Memory, 作為數據的存儲器;
2. 寫邏輯部分,主要負責產生寫信號和地址;
3. 讀邏輯部分,主要負責產生讀信號和地址;
4. 地址比較部分,主要負責產生 FIFO 空、滿的標志。
異步FIFO代碼可以參考我的另一篇文章:
https://www.cnblogs.com/lyc-seu/p/12439203.html#示例代碼
方法四:二深度FIFO同步器
二深度FIFO的地址實際上只有單bit,所以不需要進行gary編碼,所以異步FIFO中的編碼模塊可以簡化:
其中的gray2bin,bin2gray都可以省略,並且空滿信號的產生之間通過同或門和異或門即可產生。
限制: 由於深度只有2,所以只適合某些特定場景(突發傳輸要求FIFO最小深度小於2的場景)
方法五:DMUX同步器
對於多bit的data信號,還可以使用使能技術,也就是通過一個使能信號來判斷data信號是否已經穩定,當使能信號有效的時候說明data處於穩定狀態,在這種情況下終點寄存器才對信號進行采樣,可以保證沒有setup/hold違例。而使能信號一般使用double FF的方法來進行同步。下面是DMUX的同步示意圖: