做個假設(shè):需要將100M時鐘下的脈沖同步到1M的時鐘域下,如果按照打拍的方式,需要延展100拍后再進行跨時鐘域才能保證信號能在1M時鐘域正確采到,這種設(shè)計方法未免太愚蠢而又浪費資源。
本篇介紹兩種可以同時處理快到慢、慢到快所有時鐘頻率的脈沖同步設(shè)計電路情況。
- 脈沖同步
- 電平同步
脈沖同步

sync_pluse.jpg
注:
* 藍(lán)色為 A 時鐘域的寄存器;
* 紅色為 B 時鐘域的寄存器;
實現(xiàn)說明
- 該模塊關(guān)鍵寄存器是signal_a,在A時鐘域下,捕獲到i_plus_a的脈沖,轉(zhuǎn)化為電平反轉(zhuǎn)傳輸?shù)紹時鐘域,等待B時鐘域捕獲到有電平變化,signal_a再清0,等待下一個脈沖輸入。
HDL代碼
module sync_pulse
(
//A clock domain
input clk_A ,
input rst_n_A ,
//B clock domain
input clk_B ,
input rst_n_B ,
//input plus(A)
input i_puls_a ,
//output plus(B)
output reg o_puls_b
);
//------------------------------ Reg & Wire --------------------------
reg signal_a ; // A clock domain
reg signal_b1_a1 ; // A clock domain
reg signal_b1_a2 ; // A clock domain
reg signal_b ; // B clock domain
reg signal_b_b1 ; // B clock domain
reg signal_b_b2 ; // B clock domain
//-------------------------------- logic -----------------------------
always @(posedge clk_A or negedge rst_n_A)
begin
if(!rst_n_A)
signal_a <= 1'b0;
else if(i_puls_a == 1'b1)
signal_a <= 1'b1;
else if(signal_b1_a2 == 1'b1)
signal_a <= 1'b0;
end
always @(posedge clk_B)
begin
signal_b <= signal_a ;
signal_b_b1 <= signal_b ;
signal_b_b2 <= signal_b_b1 ;
end
always @(posedge clk_A)
begin
signal_b1_a1 <= signal_b_b1 ;
signal_b1_a2 <= signal_b1_a1;
end
always @(posedge clk_B or negedge rst_n_B)
begin
if(!rst_n_B)
o_puls_b <= 1'b0;
else if(signal_b_b1 && !signal_b_b2)
o_puls_b <= 1'b1;
else
o_puls_b <= 1'b0;
end
endmodule
電平同步
以上的思想是脈沖跨時鐘域,其實也可以通過電平跳轉(zhuǎn)的方法跨時鐘域:

sync_pluse.png
- 在A時鐘域檢測脈沖上升沿,然后通過改變電平Z狀態(tài)的方式傳送給B時鐘域,然后通過檢測電平Z狀態(tài)是否發(fā)生變化來判斷A時鐘域是否有脈沖。
- 電平同步比脈沖同步更節(jié)省資源,電路更加簡單,效果也不比脈沖同步差。
來源:馬哥 - Marin
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。