參考博文:https://blog.csdn.net/u014070258/article/details/90052426
在設計多時鍾系統中,需要切換時鍾源,這兩個時鍾可能是沒有關聯的(相位、頻率),或者他們為倍數關系。這兩種情況都有可能在開關時產生毛刺(glitch),而系統上的毛刺對系統來說是危險的,他可能能夠被一些寄存器捕獲為觸發邊沿,而其他寄存器忽略此毛刺。
時鍾切換的簡單實現
在這種情況下就會出現毛刺,產生這種問題的根本原因是切換控制信號相對於時鍾信號可以在任何時間里發生改變,本質是切換信號為異步信號。 任何時鍾的高電平狀態下的切換都需要避免。當兩個輸入時鍾之間是倍數關系時,插入下降沿觸發觸發器確保切換只發生在時鍾為低電平時候,引入輸出反饋確保另外一路的時鍾為低電平時候發生切換,
上述電路的缺點 沒有解決異步的問題,有可能會出現亞穩態問題,下面電路第一級通過鎖定數據來幫助穩定數據,然后將數據傳遞到下一級
ALTER推薦的時鍾切換電路圖
/***************************************************
*無毛刺切換時鍾,要點
* 1、clkx_synx 復位后為0
* 2、在高電平狀態下不切換時鍾
* 3、同步寄存器為posedge 觸發
* 4、最后一級為 negedge 觸發,確保切換發生在時鍾為低電平
****************************************************/
module clk_mux(
input rst,
input clk1,
input clk2,
input sel,
output m_clk
);
reg clk1_syn1;
reg clk1_syn2;
reg clk2_syn1;
reg clk2_syn2;
/*同步寄存器*/
always @(posedge clk1 or negedge rst)
if(!rst)
clk1_syn1 <= 1'b0;
else
clk1_syn1 <= sel & (~clk2_syn2);
always @(negedge clk1 or negedge rst)
if(!rst)
clk1_syn2 <= 1'b0;
else
clk1_syn2 <= clk1_syn1;
/*同步寄存器*/
always @(posedge clk2 or negedge rst)
if(!rst)
clk2_syn1 <= 1'b0;
else
clk2_syn1 <= (~sel) & (~clk1_syn2);
always @(negedge clk2 or negedge rst)
if(!rst)
clk2_syn2 <= 1'b0;
else
clk2_syn2 <= clk2_syn1;
assign m_clk = (clk1 & clk1_syn2) | (clk2 & clk2_syn2);
endmodule