理論上講,快時(shí)鐘域的信號(hào)總會(huì)采集到慢時(shí)鐘域傳輸來的信號(hào),如果存在異步可能會(huì)導(dǎo)致出現(xiàn)時(shí)序問題,所以需要進(jìn)行同步處理。 此類同步處理相對(duì)簡(jiǎn)單,一般采用為延遲打拍法,或延遲采樣法。
延遲打拍法
最常用的同步方法是雙級(jí)觸發(fā)器緩存法,俗稱延遲打拍法。 即,異步信號(hào)從一個(gè)時(shí)鐘域進(jìn)入另一個(gè)時(shí)鐘域之前,將該信號(hào)用兩級(jí)觸發(fā)器連續(xù)緩存兩次,可有效降低因?yàn)闀r(shí)序不滿足而導(dǎo)致的亞穩(wěn)態(tài)問題。 電路示意圖如下。
一般設(shè)計(jì)中使用兩級(jí)觸發(fā)器進(jìn)行緩存即可滿足設(shè)計(jì)時(shí)序需求。 大量實(shí)驗(yàn)研究表明,三級(jí)觸發(fā)器緩存可解決 99% 以上的此類異步時(shí)序問題。
兩級(jí)觸發(fā)器延遲打拍并檢測(cè)信號(hào)上升沿的 Verilog 描述如下:
module delay_clap(
input clk1, //異步慢時(shí)鐘
input sig1, //異步信號(hào)
input rstn, //復(fù)位信號(hào)
input clk2, //目的快時(shí)鐘域時(shí)鐘
output sig2); //快時(shí)鐘域同步后的信號(hào)
reg [2:0] sig2_r ; //3級(jí)緩存,前兩級(jí)用于同步,后兩節(jié)用于邊沿檢測(cè)
always @(posedge clk2 or negedge rstn) begin
if (!rstn) sig2_r <= 3'b0 ;
else sig2_r <= {sig2_r[1:0], sig1} ; //緩存
end
assign sig2 = sig2_r[1] && !sig2_r[2] ; //上升沿檢測(cè)
延遲采樣法
此方法主要針對(duì)多位寬的數(shù)據(jù)傳輸。
例如當(dāng)兩個(gè)異步時(shí)鐘頻率比為 5 時(shí),可以先用延遲打拍的方法對(duì)數(shù)據(jù)使能信號(hào)進(jìn)行 2 級(jí)打拍緩存,然后再在快時(shí)鐘域?qū)β龝r(shí)鐘域的數(shù)據(jù)信號(hào)進(jìn)行采集。
該方法主要思想是保證安全采集的時(shí)刻,而不用同步多位寬的數(shù)據(jù)信號(hào),可節(jié)省部分硬件資源。
利用打拍的方法進(jìn)行延遲采樣的 Verilog 模型描述如下。
//同步模塊工作時(shí)鐘為 100MHz 的模塊
//異步數(shù)據(jù)對(duì)來自工作時(shí)鐘為 20MHz 的模塊
module delay_sample(
input rstn,
input clk1,
input [31:0] din,
input din_en,
input clk2,
output [31:0] dout,
output dout_en);
//sync din_en
reg [2:0] din_en_r ;
always @(posedge clk2 or negedge rstn) begin
if (!rstn) din_en_r <= 3'b0 ;
else din_en_r <= {din_en_r[1:0], din_en} ;
end
wire din_en_pos = din_en_r[1] && !din_en_r[2] ;
//sync data
reg [31:0] dout_r ;
reg dout_en_r ;
always @(posedge clk2 or negedge rstn) begin
if (!rstn)
dout_r <= 'b0 ;
else if (din_en_pos)
dout_r <= din ;
end
//dout_en delay
always @(posedge clk2 or negedge rstn) begin
if (!rstn) dout_en_r <= 1'b0 ;
else dout_en_r <= din_en_pos ;
end
assign dout = dout_r ;
assign dout_en = dout_en_r ;
endmodule
該方法時(shí)序結(jié)果圖如下所示。
顯然,在 clk2 時(shí)鐘域,t2 時(shí)刻對(duì)數(shù)據(jù)進(jìn)行采樣緩存比 t1 時(shí)刻要安全的多。
但如果慢時(shí)鐘域沒有數(shù)據(jù)使能信號(hào) din_en, 或數(shù)據(jù)使能信號(hào)一直有效,此時(shí)在快時(shí)鐘域?qū)?shù)據(jù)使能信號(hào)上升沿進(jìn)行檢測(cè)的方法將會(huì)失效。 因?yàn)閿?shù)據(jù)使能信號(hào)一直有效,除了第一個(gè)數(shù)據(jù),快時(shí)鐘域?qū)o法檢測(cè)到后繼數(shù)據(jù)的傳輸時(shí)刻。
解決方法就是,在快時(shí)鐘域?qū)β龝r(shí)鐘信號(hào)的邊沿進(jìn)行檢測(cè)。
如果兩個(gè)時(shí)鐘的頻率相差較小,可能還需要對(duì)數(shù)據(jù)進(jìn)行延遲緩存,以保證采集到的是當(dāng)拍時(shí)鐘的數(shù)據(jù); 如果兩個(gè)時(shí)鐘的頻率相差較大,數(shù)據(jù)采樣時(shí)刻可以通過計(jì)數(shù)的方法獲得,而不用對(duì)數(shù)據(jù)進(jìn)行緩存。
利用計(jì)數(shù)延遲采樣的方法對(duì)慢時(shí)鐘邊沿進(jìn)行檢測(cè)的 Verilog 模型描述如下。
//同步模塊工作時(shí)鐘為 100MHz 的模塊
//異步數(shù)據(jù)對(duì)來自工作時(shí)鐘為 999KHz 的模塊
module delay_cnt_sample(
input rstn,
input clk1,
input [31:0] din,
input din_en,
input clk2,
output [31:0] dout,
output dout_en);
//4級(jí)緩存:3級(jí)用于打拍同步,一級(jí)用于邊沿檢測(cè)
reg [3:0] edge_r ;
always @(posedge clk2 or negedge rstn) begin
if (!rstn) edge_r <= 3'b0 ;
else edge_r <= {edge_r[3:0], clk1} ;
end
wire edge_pos = edge_r[2] && !edge_r[3] ;
//延遲計(jì)數(shù)器,檢測(cè)到慢時(shí)鐘上升沿時(shí)開始計(jì)數(shù)
reg [5:0] cnt ;
always @(posedge clk2 or negedge rstn) begin
if (!rstn) cnt <= 6'h3f ;
else if (edge_pos && din_en)
cnt <= 6'h0 ;
else if (cnt != 6'h3f) cnt <= cnt + 1'b1 ;
end
//數(shù)據(jù)同步
reg [31:0] dout_r ;
reg dout_en_r ;
always @(posedge clk2 or negedge rstn) begin
if (!rstn)
dout_r <= 'b0 ;
else if (din_en && cnt == 47) //大約在慢時(shí)鐘周期中間時(shí)刻采樣
dout_r <= din ;
end
//數(shù)據(jù)使能信號(hào)較數(shù)據(jù)采樣時(shí)刻延遲一個(gè)周期輸出
always @(posedge clk2 or negedge rstn) begin
if (!rstn) dout_en_r <= 1'b0 ;
else if (din_en && cnt==48)
dout_en_r <= 1'b1 ;
else dout_en_r <= 1'b0 ;
end
assign dout = dout_r ;
assign dout_en = dout_en_r ;
endmodule
頻率相差較大的數(shù)據(jù)同步采樣結(jié)果圖如下。
由圖可知,快時(shí)鐘采樣時(shí)刻在慢時(shí)鐘周期中央時(shí)刻左右,此時(shí)是非常安全的。
-
信號(hào)
+關(guān)注
關(guān)注
11文章
2804瀏覽量
77100 -
觸發(fā)器
+關(guān)注
關(guān)注
14文章
2003瀏覽量
61347 -
時(shí)鐘域
+關(guān)注
關(guān)注
0文章
52瀏覽量
9573 -
異步信號(hào)
+關(guān)注
關(guān)注
0文章
9瀏覽量
7031 -
時(shí)鐘采樣
+關(guān)注
關(guān)注
0文章
4瀏覽量
3376
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論