時鐘域
在一個復雜的SoC(System on Chip)系統中,不可能只有一個時鐘。我們一般認為,一個時鐘控制的所有寄存器集合處于該時鐘的時鐘域中。兩個時鐘域之間是可能有信號交互的,而且兩個時鐘域的時鐘信號都可能有源頭、相位以及頻率的區別,如果不是同源、同相位以及同頻率時鐘管理的時鐘域,交互信號是不能直接被使用的。主要面臨以下幾種情況:
時鐘的源頭不同
比方說時鐘域A是工作在振蕩器OSC1的輸出時鐘ClkOsc1下,而時鐘域B是工作在振蕩器OSC2的輸出時鐘ClkOsc2下。由于OSC1和OSC2的輸出時鐘完全不相關,因此無論是頻率還是相位都不同,這叫做不同源不同頻不同相,如下圖所示,DFF1處于ClkOsc1的時鐘域A,而DFF2處于ClkOsc2的時鐘域B,那么DFF2輸入信號如果有來自于DFF1的輸出,是不能直接使用的,針對這種跨時鐘域的電路設計方法,本節后續部分會做詳細描述。
時鐘源頭相同
如下圖所示,DFF1、DFF2與DFF3的時鐘同樣來源于OSC1的輸出ClkOsc1,但DFF2的時鐘是ClkOsc1經過某時序元件(電路)SEQ1(時序元件可以是寄存器、鎖存器、鎖相環等)處理后的輸出ClkSEQ1。ClkSEQ1可能是ClkOsc1的分頻、倍頻、門控時鐘,在相位和頻率上與ClkOsc1都會有區別。
因此,DFF1、DFF3工作在ClkOsc1的時鐘域A,而DFF2工作在ClkSEQ1的時鐘域B,至于其間交互數據,從時鐘域A去往時鐘域B的LOG12,以及從時鐘域B去往時鐘A的LOG21,需要根據ClkOsc1和ClkSEQ1之間相位和頻率的關系進行相應的設計。針對這種跨時鐘域的電路設計方法,本節后續部分會做詳細描述。
電平信號轉脈沖信號處理電路(邊沿檢測電路)
電平信號與脈沖信號之間的轉換過程,是數字集成電路設計中最基本的信號轉換操作。
我們可以將電平信號看成一種狀態(status),一種標志(flag),表示當前電路所處于的一個穩定態。比如說busy信號為高,表示該電路處于工作狀態。比如說test_mode信號為高,表示要求當前系統工作在測試模式下。
而脈沖信號可以看做是一種觸發要求(trigger),一種狀態變化的通知(message)。比方說要啟動電路工作的狀態,給電路一個脈沖信號run。比如某個模塊工作完成了,給個脈沖信號finished。
假設某個模塊對外只有一個busy狀態標志,那么我們怎么知道電路開始工作了,還是工作結束了呢?這就需要將狀態標志busy,分別轉換成電路啟動信號work,以及電路工作完成信號finished,以便告訴系統進行下一步的工作。
下圖所示就是產生worked脈沖信號的電路:
可以看出,busy標志為高的時候,表示電路正在工作,為低的時候,表示電路沒有在工作。那么如果busy從低電平轉換成高電平,表示電路啟動工作了,產生的worked脈沖信號,只有當這種變化出現時才會為高,否則一直為低。這就將電平信號變化轉換成了脈沖信號。
Workded表示busy從低到高的一種變化,所以這種電平轉脈沖電路我們也可以稱之為上升沿采集電路。
以上上升沿采集電路可以用以下Verilog HDL描述:
那么finished信號,表示busy從高變成低的狀態,電路工作結束,可以采用以下結構實現,當然,也被稱之為 下降沿采集電路 。
以上下降沿采集電路可以用以下Verilog HDL描述:
可能會有同學問,既然我們會選取帶異步復位或異步置位(低電平有效)的上升沿觸發寄存器,為什么畫圖的時候,看起來只是一個最簡單的D觸發器元件。
這主要是因為RTL設計時默認采用同步設計方法,在同一個模塊中,所有寄存器都是用同一個時鐘源及復位源輸入,因此畫圖的時候做了簡化處理,時鐘和復位在沒有特殊處理要求時都不做描述了。
本人所有電路在沒有特別說明的情況下,都會按照該原則進行描述。
脈沖信號轉電平信號處理電路
既然電平信號可以轉成脈沖信號,表示在某種狀態變化的時候要求做一個動作。那么需要因為某種動作的需要,改變一種狀態。這就是脈沖轉電平信號處理電路。
假設有兩個輸入信號,一個是開始信號start,一個是停止信號stop,都是脈沖信號。其中start脈沖來了后,要求電路開始工作,run狀態寄存器從低電平變為高電平。當stop脈沖來了后,要求電路停止工作,run狀態寄存器從高電平變為低電平。
則電路可以按照以下方式設計,當stop為高電平時,把run拉低,當start為高電平時,把run置高,否則run保持:
以上脈沖轉電平電路可以用以下Verilog HDL描述:
相信還有很多同學會有一些不同的電路實現方式,但在RTL設計方法學中,有一種通用的數據路徑設計方式,用多路選擇器(Multiplexer),通過不同的控制信號,選擇寄存器下一個周期數據的來源,相對來說,會更切合人類思考的方式,同時對于硬件描述語言來說也更加友好。
至于最終如何實現電路,可以交給邏輯綜合工具來處理。后續我們會重點介紹如何利用選擇器進行通用電路設計,這也是RTL設計的一種常見方法。
時鐘域的概念、電平信號和脈沖信號轉換電路,是作為跨時鐘信號采集電路設計的基礎。跨時鐘域的信號采集,一般分為三種情況,慢時鐘域到快時鐘的單位信號采集、快時鐘域到慢時鐘域的單位信號采集、跨時鐘域多信號采集。
***慢時鐘域到快時鐘域的單位信號采集電路
慢時鐘域到快時鐘域的單位信號采集電路,一般用于控制類信號的傳遞。數據的源寄存器驅動時鐘頻率低于驅動采集信號寄存器的時鐘頻率。如下圖所示,A時鐘域寄存器DFFA,其輸出信號I是由ClkA驅動輸出的,該信號需要由B時鐘域的寄存器采集使用,此時ClkB的頻率大于等于ClkA的頻率,則可以使用以下電路圖來實現采集:
如果在B時鐘域直接使用信號I,則可能因為ClkA與ClkB的相位不同,由于亞穩態原因,造成B時鐘域信號混亂,只需要使用去除亞穩態的電路結構,確保在B時鐘域的信號完整可靠即可。以上電路的工作時序圖如下所示:
這里面Out1和Out2是電平信號輸出,通過去除亞穩態電路處理,確保信號在ClkB的完整性,就可以在B時鐘域使用了。而Out3是該信號上升沿標志位,也已經在B時鐘域同步,也可根據需要選擇使用。
以上信號處理電路可以用以下Verilog HDL描述(此處不描述DFFA的電路,因為來自于A時鐘域的信號并不一定就是DFFA的輸出,也可能是DFFA經過組合邏輯的輸出,電路中只是一個參考):
同樣的電路,用Chisel描述如下:
快時鐘域到慢時鐘域的單位信號采集電路
同樣的,快時鐘域到慢時鐘域的單位信號采集電路,一般也只能用于控制類信號的傳遞。數據的源寄存器驅動時鐘頻率高于驅動采集信號寄存器的時鐘頻率,如果僅僅只是考慮去除亞穩態采集,如果跨時鐘域輸出信號的有效時間小于一個慢時鐘域的時鐘周期,就可能根本踩不到。要處理該信號,則同步處理電路相對較為復雜,需要有一個握手的過程:
如下圖所示,信號I是由ClkA驅動輸出的,該信號需要由B時鐘域的寄存器采集使用,此時ClkB的頻率大于等于ClkA的頻率,可以采用下圖所示電路做信號同步采集:
整個電路的工作時序如下圖所示:
需要通過以下幾步,確保信號的完整傳輸:
A. I通過脈沖轉電平信號處理電路,轉換成電平信號Ilevel_A,并傳輸出給B時鐘域使用,這樣做無論I信號是脈沖信號還是電平信號,只要ClrI_A這個清除信號沒有到來,則一直會處于有效狀態,確保B時鐘域能夠采集完成。
B. B時鐘域將A時鐘域傳輸過來的電平信號Ilevel_A做去除亞穩態處理,并采集使用(Out1,Out2,Out3根據實際需要使用)。在B時鐘域采集到有效信號,并使用的同時,通知A時鐘域清除Ilevel_A。
C. A時鐘域采集到B時鐘域清除信號的需求,做亞穩態處理后,清除Ilevel_A。
D. Ilevel_A被清除后,被B時鐘域采集,并清除采集到的信號Out1以及Out2。同時通知A時鐘域恢復ClrI同步電路的狀態。
E. ClrI同步電路恢復狀態。
以上信號處理電路可以用以下Verilog HDL描述(此處不描述DFFA的電路,因為來自于A時鐘域的信號并不一定就是DFFA的輸出,也可能是DFFA經過組合邏輯的輸出,電路中只是一個參考):
同樣的電路,用Chisel描述如下:
跨時鐘域總線數據處理電路
前面介紹了單bit控制數據跨時鐘域處理的電路,這種電路的特點就是確保單根線可以在某個時刻穩定傳遞到另一個時鐘域中,雖然電路圖中都是打兩個時鐘周期,但因為可能遇到亞穩態傳遞的情況,實際傳遞的過程并不是真的2個時鐘周期采集到,可能2個,也可能大于或小于2個。
假設參考慢時鐘域到快時鐘域傳輸采樣電路,只是簡單去亞穩態的,傳遞多bit數據,則可能造成采集數據在某幾個時鐘周期發生多次跳動的情況,并不會穩定傳遞。如下圖所示,數據在傳輸過程中會因為亞穩態傳遞出一個變化過程,同時傳輸的bit位寬越大,則越不穩定(如果采用格雷碼編碼方式傳遞,在某種應用場景下,看起來是可以使用的):
而慢時鐘采快時鐘的電路就更不能這樣設計了。
這樣看來,握手的過程仍然是需要的。那么如何握手呢?這個見仁見智,一般有2種基本的原則,一個是時間上的握手,一個是事件上的握手。
時間上的握手,相對比較容易理解,我們知道從A時鐘域到達B時鐘域數據傳遞需要一個時間,而這個信號穩定的時間是可控的,那么只要超過這個最大時間,再行采集就可以了。這種電路常見于采集從模擬異步數據處理電路中輸出的數據,比如說下圖所示的嵌入式Flash這種非時鐘控制類元件的輸出。
A時鐘域產生對E-Flash輸出控制的使能信號OE,當E-Flash的OE信號被拉高后,需要一個時間,才能從DataOut上穩定輸出數據。因此,將OE作為驅動信號實現一個B時鐘計數器的使能信號TimerTrigger,使B時鐘域的計數器開始計數,比如說B時鐘的200個時鐘周期,這個時間需要大于E-Flash從OE到DataOut的延時。
計數完成前,B時鐘域的采集電路一直保持,不會將數據送出去使用,確保了電路的穩定性,直到計數完成,TimerFinished脈沖有效,才將數據傳輸出去。同時TimerFinshed脈沖有效又會反饋會A時鐘域,以便把OE拉低,準備下一次傳輸。
因為A時鐘域與B時鐘域不是同一個時鐘域(并不絕對,只是舉例),因此OE轉換成TimerTrigger的電路以及TimerFinished轉換成OE的電路需要做時鐘域同步處理,只是一個單bit控制信號的傳遞,相對來說就比較好設計了。
其實事件信號的握手與時間的握手,從機制上是一致的,主要是考慮一是什么時候數據被送出來了,二是數據是否已經穩定,三是數據是不是已經被采集好,四是數據采集完成后需要恢復初始狀態準備下一次數據發送。
第二點,數據是否已經穩定,在時間握手的電路中,就體現在利用計數器實現判斷。因此時間的握手,其實也可以看成是一種特殊的事件握手。
如果是判斷數據是否穩定采集,原理上可以通過多次比較,比如說如果發生傳輸,且連續幾次收到的數據都是一致的,同時又與發送端數據一致,則認為數據穩定采集。電路的實現方式還是比較靈活的,有興趣的小伙伴可以自己動手設計一下。
因此如果我們把同步電路分成數據路徑和控制路徑,那么就不難理解如何進行同步了。數據不能同步,但控制信號是可以同步的。就像下面這幅框圖一樣:
異步FIFO
對于同步電路來說,穩定的傳輸數據,一定是最重要的。但分析上面提到的同步電路,小伙伴們應該不難發現,如果一次同步工作沒有完成,第二次同步需求是會被忽略掉的。那么我們可以采用異步FIFO的電路設計方法,來規避這個缺點。
FIFO,即First In First Out的縮寫,意味著先被寫進去的,會先被輸出來,就像是火車鉆山洞那樣,火車頭先進的山洞,那么也是火車頭先出的山洞。
異步FIFO的意思就是FIFO輸入和FIFO輸出是不同的兩個時鐘域。一個簡單的異步FIFO電路結構可以看下面這幅圖:
利用異步FIFO可以讓時鐘較連續的從一個時鐘域傳輸到另一個時鐘域。
常見的異步FIFO結構一般有2種,一種是如下讀指針和寫指針控制同一塊存儲區域,這種操作,數據就像流水一樣,只要寫進去,就可以讀出來:
另外一種是如下讀指針和寫指針控制不同的存儲區域,寫數據量較大,且連續的情況下,可以根據一次傳輸數據總量,先把數據存儲在一個區域,下次又來數據的時候,存入另一個區域。而讀的區域與寫的區域直接分開,完全不受干擾。這種操作,又稱為乒乓操作。
而FIFO設計中最重要的就是指針的設計,指針類似于一個計數器,隨著寫或讀的次數發生遞增或遞減,而指針作為存儲塊的地址信號,即可對存儲塊(一般是RAM或Register File)不同地址進行操作了:
一般來說我們建議使用二進制計數做地址指針,而將其轉換成格雷碼用于做空滿控制,這是因為數據信號直接傳輸,但控制信號需要同步,轉換成為格雷碼后,可以確保每次指針增減,都只有1bit數據在發生變換且用于同步,不會在同步過程中產生毛刺。
網上有不少異步FIFO的開源代碼,有興趣的小伙伴可以下載下來進行學習和使用。
-
鎖相環
+關注
關注
35文章
588瀏覽量
87809 -
振蕩器
+關注
關注
28文章
3839瀏覽量
139167 -
寄存器
+關注
關注
31文章
5357瀏覽量
120632 -
信號處理器
+關注
關注
1文章
254瀏覽量
25301 -
SoC系統
+關注
關注
0文章
52瀏覽量
10699
發布評論請先 登錄
相關推薦
評論