跨時鍾域同步3---多bit信號同步(延遲采樣法/慢到快)


一、有din_en信號&&頻率相差較小

假設兩個異步時鍾頻率比為 5, 我們可以先用延遲打拍的方法對數據使能信號進行 3 級打拍緩存以檢測其上升沿,此時得到的上升沿信號剛好在數據使能信號的中間時刻附近,然后就可以在快時鍾域對慢時鍾域的數據信號進行采集了。具體對數據使能信號打幾拍,需要根據快慢時鍾的頻率比來決定。

該方法的基本思想就是選擇合適的時刻(例如數據的中間時刻)去采集信號,而不用同步多位寬的數據信號,可節省硬件資源。

module delay_sample(
    input               rstn,
    input               clk1,
    input [7:0]         din,
    input               din_en,

    input               clk2,
    output [7:0]        dout,
    output              dout_en);

   //sync din_en
   reg din_en_r1 ;
   reg din_en_r2 ;
   reg din_en_r3 ;
   
   always @(posedge clk2 or negedge rstn) begin
     if (!rstn) begin
         din_en_r1 <= 0;
         din_en_r2 <= 0;
         din_en_r3 <= 0;
     end
     else begin
         din_en_r1 <= din_en;
         din_en_r2 <= din_en_r1;
         din_en_r3 <= din_en_r2;
     end    
   end

   //檢測din_en上升沿
   wire din_en_pos = din_en_r2 && !din_en_r3 ;

   
   reg [7: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

在這里插入圖片描述
由圖可知,快時鍾是在慢時鍾域的數據有效時間段的中間時刻左右對數據進行采樣的,這樣采到的數據非常的安全。

二、有din_en信號&&頻率相差較大

如果頻率相差較大,那在設計一個計數器,在din_en的上升沿附近開始計數,根據頻率比確定計數值到達多少時剛好處於din_en有效期的中間時刻附近,當計數到此值時對數據進行采樣即可。

三、無din_en或din_en一直拉高

如果慢時鍾域沒有數據使能信號 din_en, 或數據使能信號一直有效,此時在快時鍾域對數據使能信號進行上升沿檢測的方法將會失效。因為數據使能信號一直有效,除了第一個數據,快時鍾域將無法檢測到后繼數據的傳輸時刻。

解決方法就是,在快時鍾域對慢時鍾信號的邊沿進行檢測。如果兩個時鍾的頻率相差較小,可能還需要對數據進行延遲緩存,以保證采集到的是當拍時鍾的數據(因為當頻率相近時,第一個時鍾邊沿不容易被直接采樣到,可能到下一個數據有效期間才能被采樣到,所以應該將上一個數據延遲到此刻才能正確采樣);如果兩個時鍾的頻率相差較大,數據采樣時刻可以通過計數的方法獲得,而不用對數據進行緩存。

module delay_cnt_sample(
    input               rstn,
    input               clk1,
    input [7:0]         din,
    input               din_en,

    input               clk2,
    output [7:0]        dout,
    output              dout_en);

   reg clk1_r1 ;
   reg clk1_r2 ;
   reg clk1_r3 ;
   
   
   always @(posedge clk2 or negedge rstn) begin
     if (!rstn) begin
         clk1_r1 <= 0;
         clk1_r2 <= 0;
         clk1_r3 <= 0;
     end
     else begin
         clk1_r1 <= clk1;
         clk1_r2 <= clk1_r1;
         clk1_r3 <= clk1_r2;
     end    
   end

   wire clk1_pos = clk1_r2 && !clk1_r3 ;

   //delay counter
   reg [5:0] cnt ;
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)                
            cnt <= 0 ;
      //每檢測到新的慢時鍾上升沿並且din_en有效,那么就預示着新的數據到來了,就要重新計數了
      else if (clk1_pos && din_en)
            cnt <= 0 ;
      else if (cnt != 6'b111111)    
            cnt <= cnt + 1'b1 ;
      else
            cnt <= cnt ;
   end

   //sync data
   reg [7:0]            dout_r ;
   reg                  dout_en_r ;
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)
        dout_r         <= 'b0 ;
      else if (din_en && cnt == 33)
        dout_r         <= din ;
   end
   
   
   always @(posedge clk2 or negedge rstn) begin
      if (!rstn)        
            dout_en_r      <= 1'b0 ;
      else if (din_en && cnt == 33)
            dout_en_r      <= 1'b1 ;
      else              
            dout_en_r      <= 1'b0 ;
   end
   
   assign       dout    = dout_r ;
   assign       dout_en = dout_en_r ;

endmodule

在這里插入圖片描述
由圖可知,快時鍾是在慢時鍾域的數據有效時間段的中間時刻左右對數據進行采樣的,這樣采到的數據非常的安全。

三、總結

無論是考慮打拍需要打多少拍,還是計數需要計多少次,都需要根據快慢時鍾的實際頻率比來決定。大多數情況下,我們的目標是保證在數據有效時間段的中間時刻去采樣,這樣采出的數據才非常准確安全。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM