1. 程式人生 > 實用技巧 >glitchless的時鐘切換電路

glitchless的時鐘切換電路

問題:

在多時鐘設計中可能需要進行時鐘的切換。由於時鐘之間可能存在相位、頻率等差異,直接切換時鐘可能導致產生glitch。

組合邏輯實現時鐘切換:

HDL程式碼:

module clock_mux(
    input clk0, clk1,
    input select,
    output out_clock
);

    assign out_clock = selsect ? clk1: clk0;

endmodule

電路圖:

波形圖:

問題:

使用上述電路進行時鐘切換會導致在控制訊號sel附近出現glitch。其原因在於控制訊號可以在任意時刻進行時鐘切換,切換訊號相對於兩個時鐘都是非同步訊號。

解決方法:

使用暫存器使得控制訊號僅在時鐘邊沿作用,避免在任何時鐘都為高電平是進行時鐘切換。

適用於倍頻時鐘切換的時序邏輯電路

HDL程式碼:

module clock_mux(
    input clk0, clk1,
    input select,
    output out_clock
);
    
    reg q1;
    reg q0;

    always @(negedge clk1)
        q1 <= !q0 && selected

    always @(negedge clk0)
        q0 <= !q1 && ~select;

    
assign out_clock = (clk1 && q1) || (clk0 && q0); endmodule

電路圖:

波形圖:

功能:

當切換的時鐘存在倍頻關係時,分別插入一個下降沿觸發的觸發器以確保控制訊號僅在時鐘低電平時起作用。

問題:

當DFF1輸入的變化非常接近CLK1的下降沿時,可能會導致DFF1的亞穩態問題;DFF0同理。

為什麼可以用於倍頻時鐘之間的切換?

非同步時鐘切換的時序電路

HDL程式碼:

module clock_mux(
    input        clk0, clk1,
    input        rst_n,
    
input select, output out_clock ); reg inter0_p, inter0_n; reg inter1_p, inter1_n; always @(posedge clk0 or negedge rst_n) if(!rst_n) inter0_p <= 0; else inter0_p <= (select && !inter1_n); always @(negedge clk0 or negedge rst_n) if(!rst_n) inter0_n <= 0; else inter0_n <= inter0_p; always @(posedge clk1 or negedge rst_n) if(!rst_n) inter1_p <= 0; else inter1_p <= (select && !inter0_n); always @(negedge clk1 or negedge rst_n) if(!rst_n) inter1_n <= 0; else inter1_n <= inter1_p; assign out_clock = (clk0 && inter0_n) || (clk1 && inter1_n); endmodule

電路圖:

 

波形圖:

功能:

通過為每個時鐘源新增一個額外級的正邊沿觸發觸發器來提供針對亞穩態性的保護,CLK0的上升沿取樣到訊號到下降沿傳遞至CLK1的正邊沿觸發器,並在CLK0下降沿後CLK1第一個上升沿之後的下降沿輸出。(不是很理解)