剛入行時最早看到的時鐘切換電路出自下面這篇文獻,第20頁,Trouble-Free Switching Between Clocks。 這篇極短的小文章可能是 Xilinx 元老 Peter Alfke 寫的。 Peter 是我非常敬重的前輩,讀過幾篇他寫的數字電路小文章,非常實用,受益匪淺。
這個電路雖然概念上是對的,但有明顯瑕疵。如果Select相對于Clock A, Clock B是完全異步asynchronous,電路中的兩個flip flop在Select變化時會有亞穩(wěn)態(tài)metastability的可能性。克服這個瑕疵的fix很簡單,把圖中的單個flip flop換成兩級flip flop組成的同步器synchronizer就可以了。
Xilinx這個電路的基本思想是SR latch。去掉圖中兩個flip flop,最前端的兩個AND組成一個類似SR latch的電路,只不過SR Latch的S,R輸入換成了Select和Select inverted。為了使SR Latch的輸出能與所需控制的時鐘同步,加上了一級flip flop同步一下。當然,兩級flip flop同步會更好。Xilinx這個電路里有一個非常重要的小細節(jié),牽涉到時鐘切換的一條重要原則---先關斷當前選擇的時鐘,再使能新選擇的時鐘。QB反饋到Clock A那邊經過一個反向再和Select反向AND,QA反饋到Clock B那邊經過一個反向再和Select AND,保證了先關斷再使能這個重要原則。
Xilinx這個電路里還有個非常重要的小細節(jié),也是該電路的精妙之處。這兩個flip flop的時鐘輸入端有個小泡泡,意思是時鐘下降沿觸發(fā)。這是一個重要的設計思想。如果要gate off掉一個時鐘,在該時鐘低電平時gate off是最安全的。如果是在高電平時做切換,很容易造成高電平被切掉一段變成一個毛刺,這可是大大的危害。搞笑的是網上隨便搜一下“glitchless clock switching”,會出來一大堆文章,雖然都是基于Xilinx這個電路,但大部分漏掉了低電平觸發(fā)這個細節(jié)。沒有完全理解就胡亂抄胡亂吹牛,比較符合南亞某大國的國民性格。嘴上吹得天花亂墜,做事毛毛躁躁。做出來的電路有時工作有時不工作。玩具上用用倒也沒大問題。這種態(tài)度用到飛機上就是737 MAX。
下面是改進的電路,一級flip flop換成了兩級flip flop同步而已。
電路啟動波形
切換波形– fast to slow
切換波形– slow to fast
這個改進電路依然有一些可以變化的地方。譬如電路中的AND換成ICG貌似更好一些,對后端的工具更友好一些,實際上ICG在初始狀態(tài)有一個額外要求,不見得是好的選擇,見補充2。
以上是一個比較經典的時鐘切換電路。根據實際使用場景的不同,時鐘切換有很多不同的實現方法,都可以做得非常經典。時鐘,復位,是數字設計里最最基本的電路,稍有不慎,就會毀了整個設計,一定要謹慎再謹慎。
順便講一下,在芯片設計里,這種特殊電路都應該是例化instantiate的。例化的好處是便于在后端流程里找到這些門。例如,這里的AND可以用一個bbox_and模塊。bbox_and里例化instantiate庫里的CKAND2門。時鐘切換電路里例化bbox_and模塊,給個u_bbox_and_1 這樣的instance name。在后端設計里,就可以很方便找到u_clkgen/u_bbox_and_1/bbox_and_0,加約束就會很方便。使用bbox模塊也是數字設計中一個重要技巧,以后有時間再討論了。
小結一下。
1)時鐘切換的重要原則---先關斷當前選擇的時鐘,再使能新選擇的時鐘。
2)當前時鐘低電平時切換是比較安全的做法。
補充一下。 上面的電路只是概念上的示意圖。 實際設計中要考慮 DFT, 要加 DFT clock mux, DFT reset mux,會復雜一些。
補充2
前面講了可以考慮把AND換成ICG。一位網友指出,換成ICG后如果時鐘的初始值時高電平,電路可能會出問題。首先感謝這位網友,謝謝指出這個與ICG特性有關的重要問題。
下面是改用ICG后的時鐘切換電路。
下面是在clk1, clk2初始值都為高的場景下該電路啟動時的仿真波形。在這個特殊場景下,由于clk1, clk2初始為高,使得對應的ICG輸出clk_slow_gated, clk_fast_gated初始值為X,造成切換電路輸出在初始時也為X!造成這個現象的是ICG的一個重要“缺陷”–未被初始化uninitialized ICG。
解釋這個現象,首先要先看一下這個電路里用到的ICG的內部構造。這里SE(scan mode ICG enable),E(functional mode ICG enable)是latch的數據輸入。Latch的gate信號為CK的反向。
CK為0時latch打開,(E | SE)通過latch,ICG的輸出=(E|SE)& CK。因為此時CK為0,ICG的輸出也為0。
CK為1時latch關閉并保持以前的狀態(tài)(latch_old_state)。假設CK變?yōu)?前E=1,latch_old_state =1,ICG的輸出=latch_old_state & CK= CK;假設CK變?yōu)?前E=0,latch_old_state =0,ICG的輸出=0 & CK= 0。
如果初始時CLK為1,ICG內部的latch是關閉的,E無法通過,而且因為之前l(fā)atch從來沒有打開過,沒鎖存過任何確定的值,latch_old_state不確定(仿真中顯示為X)。在這個場景下ICG輸出= latch_old_state & CK= X& CK= X,即ICG輸出為X。下面就是這個場景的波形。
如果初始時CLK為0,ICG內部的latch是打開的,ICG的輸出為(E & CLK) = 0,ICG輸出為確定值,ICG被成功初始化。下面是這個場景下的仿真波形。
綜上所述,為了避免上述ICG未初始化引起的問題,使用ICG搭時鐘切換電路時,系統(tǒng)設計中要考慮加一個時鐘初始為0的要求。
補充3
基于補充2的電路,還有一種變化,就是把falling edge DFF換成rising edge DFF。這時要特別小心兩個時鐘周期相差很大的情況。例如一路時鐘為clk_slow (slow clock),另一路為clk_fast (fast clock),選擇信號sel由0變1 (clk_slow to clk_fast switch)。當clk_slow上升沿到來,當clk_slow這一路第二級DFF的輸出(sel_sync_slow)變?yōu)?時,并不意味著clk_slow對應的ICG輸出立刻變0,而是要等到clk_slow下降沿到來。也就是說此時clk_sw的輸出仍舊clk_slow的高電平。這時如果clk_slow第二級DFF輸出(sel_sync_slow)被直接送到clk_fast的選擇輸入邏輯,如果clk_fast非???,就會出現clk_slow ICG尚未關斷,clk_fast ICG已經打開,造成切換后的輸出clk_sw出現毛刺。
為了避免這樣的情況,必須引入第三級DFF。ICG E仍舊用第二級DFF輸出,第三級DFF輸出送到另一路選擇邏輯。整體來看這樣的電路有點浪費資源。
補充4
上面幾種電路都只能在時鐘正常跑起來的情況下完成切換。如果當前選中的時鐘停了,選擇信號無法通過由當前時鐘驅動的兩級DFF,也就無法實現切換了。
時鐘停止屬于系統(tǒng)級錯誤,需要在系統(tǒng)設計找到解決方案,這里就不贅述了。
審核編輯:黃飛
-
Xilinx
+關注
關注
71文章
2155瀏覽量
120854 -
數字電路
+關注
關注
193文章
1595瀏覽量
80379 -
時鐘電路
+關注
關注
10文章
236瀏覽量
50675 -
仿真波形圖
+關注
關注
1文章
5瀏覽量
3140
發(fā)布評論請先 登錄
相關推薦
評論