1 時鐘無縫切換

2021-07-26 04:18:17 字數 3828 閱讀 9051

時鐘切換分成兩種方式,普通切換去毛刺無縫切換

普通切換

,就是不關心切出的時鐘是否存在毛刺,這種方式電路成本小。如果時鐘切換時,使用此時鐘的模組電路處於非工作狀態,或者模組內電路被全域性復位訊號reset住的,即使切出毛刺也不會導致dff誤觸發,這樣的模組可以選擇用此種切換方式。

寫法很簡單assign clk_o = sel_clkb ? clkb : clka,當sel_clkb為 1 時選擇clkb,否則選擇clka。不過在實際設計中,建議直接呼叫庫里的mux單元set_dont_touch,不要採用這裡的assign寫法,因為這種寫法最後綜合得到的可能不是mux而是複雜組合邏輯,給前後端流程的時鐘約束和分析帶來不便。

無縫切換

,就是切換時**刺時鐘平穩過渡。在時鐘切換中,只要出現比clka或者clkb頻率更高的窄脈衝,不論是窄的高電平還是窄的低電平,都叫時鐘毛刺。工作在切換後時鐘clk_o下的電路模組,綜合約束是在max頻率下的,也就是說設計最後signoff的時候,只保證電路可以穩定工作的最高頻率是max,如果切換中出現更高頻的時鐘毛刺,電路可能出現無法預知的結果而出錯。無縫切換,一般用在處於工作狀態的模組需要調頻或者切換時鐘源,比如內部系統匯流排,cpu等。你剛用手機打完遊戲後馬上關屏聽**,這兩種場景中,cpu在滿足效能前提下為了控制功耗,其工作頻率會動態地從很高調至較低,此時就可能是在cpu一直處於工作狀態下,通過無縫切換時鐘源頭實現的。

在無縫切換電路中,切換訊號sel_clkb可以是任意時鐘域下的訊號,包括但不限於clka或者clkb域,但是sel_clkb必須是乙個dff輸出 訊號;clka與clkb的頻率大小相位關係可以任意。無縫切換需要解決兩個問題:

一是非同步切換訊號的跨時鐘域同步問題,這裡需要使用

《verilog基本電路設計之一》

裡的同步電路原理消除亞穩態;

二是同步好了的切換訊號與時鐘訊號如何做邏輯,才能實現**刺。

下面寫出無縫切換電路的主體部分,忽略了內部訊號的定義宣告等。

module clk_switch (

rst_n,

clka,

clkb,

sel_clkb,

clk_o

);always @ (posedge clka or negedge rst_n)

begin

if (!rst_n) begin

sel_clka_d0 <= 1'b0;

sel_clka_d1 <= 1'b0;

endelse begin

sel_clka_d0 <= (~sel_clkb) & (~sel_clkb_dly3) ;

sel_clka_d1 <= sel_clka_d0 ;

endend// part2

//always @ (posedge clka_n or negedge rst_n)

always @ (posedge clka or negedge rst_n)

begin

if (!rst_n) begin

sel_clka_dly1 <= 1'b0;

sel_clka_dly2 <= 1'b0;

sel_clka_dly3 <= 1'b0;

endelse begin

sel_clka_dly1 <= sel_clka_d1;

sel_clka_dly2 <= sel_clka_dly1 ;

sel_clka_dly3 <= sel_clka_dly2 ;

endend// part3

//always @ (posedge clkb_n or negedge rst_n)

always @ (posedge clkb or negedge rst_n)

begin

if (!rst_n) begin

sel_clkb_d0 <= 1'b0;

sel_clkb_d1 <= 1'b0;

endelse begin

sel_clkb_d0 <= sel_clkb & (~sel_clka_dly3) ;

sel_clkb_d1 <= sel_clkb_d0 ;

endend// part4

//always @ (posedge clkb_n or negedge rst_n)

always @ (posedge clkb or negedge rst_n)

begin

if (!rst_n) begin

sel_clkb_dly1 <= 1'b0;

sel_clkb_dly2 <= 1'b0;

sel_clkb_dly3 <= 1'b0;

endelse begin

sel_clkb_dly1 <= sel_clkb_d1 ;

sel_clkb_dly2 <= sel_clkb_dly1 ;

sel_clkb_dly3 <= sel_clkb_dly2 ;

endend// part5

clk_gate_*** clk_gate_a ( .cp(clka), .en(sel_clka_dly3), .q(clka_g) .te(1'b0) );

clk_gate_*** clk_gate_b ( .cp(clkb), .en(sel_clkb_dly3), .q(clkb_g) .te(1'b0) );

//assign clka_g = clka & sel_clka_dly3 ;

//assign clkb_g = clkb & sel_clkb_dly3 ;

assign clk_o = clka_g | clkb_g ;

endmodule

上面是我認為比較合理的無縫切換電路,其他切換方式跟這個會有些許出入,但基本大同小異原理是一樣的。

有幾點說明:

拋開注釋掉的電路不看,由於part5部分直接呼叫庫里的clock gating cell,使得整個切換電路全部只需要用到時鐘上公升沿,無需額外定義反向時鐘,精簡了dc綜合的時鐘約束;直接呼叫gating cell的 另乙個好處是,前後端工具會自動檢查gating cell的cp訊號與en訊號的setup/hold時間,使得gating後的q時鐘輸出**刺尖峰。te端可以根據實際需要接上scan測試模式訊號。如果使用part5部分的gating cell實現,前面的part1,2,3,4全部替換成注釋掉的反相時鐘也是沒有問題。

part2和part4部分,具體需要多少級dff,甚至完全不要也是可以的,這就回到了《verilog基本電路設計之一》裡討論的到底多少級dff消除亞穩態才算合理的問題。時鐘頻率很低可能無所謂,如果時鐘頻率達到ghz,這部分建議至少保留**dff,因為**dff延時也僅僅只有3ns的時間裕度。沒必要為了省這麼幾個dff降低電路可靠性,在複雜ip以及大型soc系統中,你會發現多幾十個dff,面積上可以忽略,系統可靠性和穩定性才是首要的。

如果part5部分希望使用注釋掉的兩行「與」邏輯實現時鐘gating,此時part1與part3使用正相或者反相時鐘都可以,但是必須把part2和part4部分改為注釋掉的反相時鐘實現,目的是初步從rtl設計上避免「與」邏輯的毛刺,同時還需要後端配合,因為很多後端工具對時鐘「與」邏輯的clock gating check未必會檢查。用clk下降沿拍出的en訊號,再跟clk做與邏輯得到的門控時鐘,在rtl**階段看到的一定不會有毛刺,但是佈線完成後,如果clk相對en後移,那與邏輯得到的門控時鐘就有毛刺了。這就是用與邏輯做門控的缺點,由於後端工具可能不會去檢查這個與門的時序關係而導致出錯。但直接呼叫庫里的gating cell,工具天然就會去檢查這個時序,免去人工確認的後顧之憂。

STM8 時鐘切換

hse hsi lsi 都可以作為系統主時鐘源,stm8 微控制器復位以後預設 hsi 的 8 分頻作為系統主時鐘,其原因是 hsi 穩定時間短,而其 8 分頻又可以保證系統在較差的 vdd 條件下安全啟動。在系統執行的過程中可以切換系統的主時鐘源。系統時鐘源的切換有 2 種方式 自動切換 手動切換...

STM8 時鐘源切換

1 1 24mhz的高速外部晶體振盪器 hse 即外部晶振 2 1 24mhz的高速外部時鐘訊號 hse 3 16mhz的高速內部rc振盪器 hsi 4 128khz的低速內部rc振盪器 lsi 由上述時鐘框圖,可以分析得知,16mhz hsi rc振盪器經過乙個分頻器,將時鐘訊號輸出到主時鐘選擇器...

FPGA 時鐘設計 1 時鐘資源總結

關於一款晶元,最權威 最新的資料當然是廠家的官方檔案。很多大牛都推薦直接閱讀原廠的 datasheet 和 user guide。根據我的體驗,這確實是最好的途徑。原因有兩個 實驗室有的晶元是 xilinx 的 virtex 5 系列,virtex 5 的 user guide 是 ug190,以下...