1. 程式人生 > 其它 >跨時鐘域傳輸:快到慢

跨時鐘域傳輸:快到慢

慢時鐘域採集從快時鐘域傳輸來的訊號時,需要根據訊號的特點來進行同步處理。對於單 bit 訊號,一般可根據電平訊號和脈衝訊號來區分。
電平訊號同步
同步邏輯設計中,電平訊號是指長時間保持不變的訊號。保持不變的時間限定,是相對於慢時鐘而言的。只要快時鐘的訊號保持高電平或低電平的時間足夠長,以至於能被慢時鐘在滿足時序約束的條件下采集到,就可以認為該訊號為電平訊號。既然電平訊號能夠被安全的採集到,所以從快時鐘域到慢時鐘域的電平訊號也採用延遲打拍的方法做同步。
脈衝訊號同步
同步邏輯設計中,脈衝訊號是指從快時鐘域輸出的有效寬度小於慢時鐘週期的訊號。如果慢時鐘域直接去採集這種窄脈衝訊號,有可能會採集不到。◆假如這種脈衝訊號脈寬都是一致的,在知道兩個時鐘頻率比的情況下,可以採用“快時鐘域脈寬擴充套件+慢時鐘域延遲打拍”的方法進行同步。◆如果有時窄脈衝訊號又表現出電平訊號的特點,即有時訊號的有效寬度大於慢時鐘週期而能被慢時鐘採集到,那麼對此類訊號再進行脈衝擴充套件顯然是不經濟的。此時,可通過“握手傳輸”的方法進行同步。
假設脈衝訊號的高電平期間為有效訊號期間,其基本原理如下。(1) 快時鐘域對脈衝訊號進行檢測,檢測為高電平時輸出高電平訊號 pulse_fast_r。或者快時鐘域輸出訊號時,不要急於將訊號拉低,先保持輸出訊號為高電平狀態。(2) 慢時鐘域對快時鐘域的訊號 pulse_fast_r 進行延遲打拍取樣。因為此時的脈衝訊號被快時鐘域保持拉高狀態,延遲打拍肯定會採集到該訊號。(3) 慢時鐘域確認取樣得到高電平訊號 pulse_fast2s_r 後,再反饋給快時鐘域。(4) 快時鐘域對反饋訊號 pulse_fast2s_r 進行延遲打拍取樣。如果檢測到反饋訊號為高電平,證明慢時鐘域已經接收到有效的高電平訊號。如果此時快時鐘域自身邏輯不再要求脈衝訊號為高電平狀態,拉低快時鐘域的脈衝訊號即可。此方法實質是通過相互握手的方式對窄脈衝訊號進行脈寬擴充套件。
利用握手訊號進行同步處理的 Verilog 模型描述如下。
//同步模組工作時鐘大約為 25MHz 的模組
//非同步資料對來自工作時鐘為 100MHz 的模組module pulse_syn_fast2s #( parameter PULSE_INIT = 1'b0 ) ( input rstn, input clk_fast, input pulse_fast, input clk_slow,   output               pulse_slow);
wire clear_n ; reg pulse_fast_r ;
/**************** fast clk ***************/ //(1) 快時鐘域檢測到脈衝訊號時,不急於將脈衝訊號拉低 always@(posedge clk_fast or negedge rstn) begin if (!rstn) pulse_fast_r <= PULSE_INIT ; else if (!clear_n) pulse_fast_r <= 1'b0 ; else if (pulse_fast) pulse_fast_r <= 1'b1 ;
   end
reg [1:0] pulse_fast2s_r ; /************ slow clk *************/ //(2) 慢時鐘域對訊號進行延遲打拍取樣 always@(posedge clk_slow or negedge rstn) begin if (!rstn) pulse_fast2s_r <= 3'b0 ; else pulse_fast2s_r <= {pulse_fast2s_r[0], pulse_fast_r} ; end   assign pulse_slow = pulse_fast2s_r[1] ;
reg [1:0] pulse_slow2f_r ; /********* feedback for slow clk to fast clk *******/ //(3) 對反饋訊號進行延遲打拍取樣 always@(posedge clk_fast or negedge rstn) begin if (!rstn) pulse_slow2f_r <= 1'b0 ; else pulse_slow2f_r <= {pulse_slow2f_r[0], pulse_slow} ; end //控制快時鐘域脈衝訊號拉低   assign clear_n = ~(!pulse_fast && pulse_slow2f_r[1]) ;
endmodule

testbench 描述如下。
`timescale 1ns/1ps
module test ; reg clk_100mhz, clk_25mhz ; reg rstn ;
initial begin clk_100mhz = 0 ; clk_25mhz = 0 ; rstn = 0 ; #11 rstn = 1 ; end always #(10/2) clk_100mhz = ~clk_100mhz ;   always #(45/2)   clk_25mhz   = ~clk_25mhz ;
reg [7:0] cnt ; reg pulse_sig ; always @(posedge clk_100mhz or negedge rstn) begin if (!rstn) begin cnt <= 'b0 ; end else begin cnt <= cnt + 1'b1 ; end end
//窄脈衝生成部分 always @(posedge clk_100mhz or negedge rstn) begin if (!rstn) begin pulse_sig <= 1'b0 ; end else if (cnt == 5 || cnt == 40 || cnt == 42 || cnt >= 75 && cnt <= 81 || cnt == 85 || cnt == 87 ) begin pulse_sig <= 1'b1 ; end else begin pulse_sig <= 1'b0 ; end end
pulse_syn_fast2s u_fast2s_pulse( .rstn (rstn), .clk_fast (clk_100mhz), .pulse_fast (pulse_sig), .clk_slow (clk_25mhz),      .pulse_slow       ());
initial begin forever begin #100; if ($time >= 10000) $finish ; end   end
endmodule // test

模擬結果如下,由圖可知:(1) 快時鐘域單個窄脈衝訊號被慢時鐘域採集到,但是同步後的訊號延遲較長,脈衝寬度較大。訊號延遲是因為延遲打拍和反饋清零決定的,無法避免。脈寬問題,可以通過對慢時鐘域的訊號再進行打拍邊沿檢測的方法進行處理。(2) 兩個窄脈衝訊號同步後的訊號脈寬與單個窄脈衝沒有差異,也就是說,同步電路漏掉了第二個窄脈衝的檢測。這也屬於握手傳輸處理同步問題的特點,當快時鐘域的脈衝訊號變化速率過快時,該方法不能分辨相鄰的脈衝。(3) 當多個寬窄脈衝訊號相鄰較近時,雖然該同步方法不能分辨多個脈衝訊號,但同步後的訊號脈寬可能會相對大一些。
多位寬資料同步
當多位寬資料進行同步時,如果該資料各 bit 位都可以看作電平訊號,即相對一段時間內各 bit 位資料均可以保持不變以至於能被慢時鐘採集到,可以消耗一些觸發器資源對多位寬資料進行簡單的延遲打拍同步。但如果資料變化速率過快,就不能再使用延遲打拍取樣的方法。因為此時資料各 bit 位不再是電平訊號,變化的時間也參差不齊,用非同步時鐘進行打拍取樣,可能會採集到因路徑延遲不停而導致的錯誤資料,即時序上存在 violation。解決此類非同步問題常用的方法是採用非同步 FIFO (First In First Out)。具體請參考下一節:《4.4 FIFO 設計》。