關於FPGA異步時鍾采樣--結繩法的點點滴滴


.典型方法

 

   典型方法即雙鎖存器法,第一個鎖存器可能出現亞穩態,但是第二個鎖存器出現亞穩態的幾率已經降到非常小,雙鎖存器雖然不能完全根除亞穩態的出現(事實上所有電路都無法根除,只能盡可能降低亞穩態的出現),但是基本能夠在很大程度上減小這種幾率。最后的一個D觸發器和邏輯電路組成的是一個采沿(上升沿,修改一下就能采集下降沿)電路,即當第二個鎖存器的輸出中出現1個上升沿,那么最后的邏輯輸出就會產生1個clock的高電平脈沖

.結繩法

 1.結繩法1:利用數據的邊沿作時鍾(例子中上升沿)。(可以將脈沖無限延長,直到可以采集到數據,然后復位,要考慮產生數據的頻率)。

  實例1

 

 

 說明:這種結繩法的原理是,數據作為Din_clkA,即當數據有上升沿(0->1)時,寄存器1的輸出將會穩定在高電平,此時等待clkB采樣,當clkB完成采樣后,寄存器4會輸出高電平,若此時Din_clkA為高電平,那么即可完成復位,開始下一次采樣等待。

       這里需要注意的是當數據來臨(即上升沿)時,clkB域需要等待3個clkB才會在寄存器4輸出並完成輸入端的復位,所以Din如果變化較快

        即持續時間短於3個clkB,也就是clkA頻率大於clkB的1/3,那么這時Din的變化將無法被采樣到,因為clkB域需要3個clkB才能

        完成采樣,並且此時Din必須是低電平才能復位,並且復位后的0也要延遲3個clkB才能到達輸出端.

       因此說,在慢時鍾采樣快時鍾的時候,結繩法適合采樣數據較少(即脈沖間隔較大)的控制信號。即脈沖間隔Ta>3Tb;即等待3個clkB時鍾后,完成復位,才允許下一個輸入脈沖。

       

實例2


    說明:與實例1的區別是,這種復位更迅速,不需要等到clkA為低電平,即可完成復位。復位后,經過3個clkB,寄存器2~4相繼復位

 2結繩法2:利用數據作為異步復位,置位信號。(適合將不足時鍾寬度的脈沖擴展1周期)

 實例1:輸入高脈沖(clka域),輸出高脈沖(clkb域)

 

     說明:當clkB因為太慢,沒有采到din_clkA時,din_clkA的高電平脈沖會異步置位,即寄存器1從clkA的上升沿開始到clkB的下一個上升沿之間輸出為高,寄存器2采樣到高電平,並持續1個clkB,高電平持續時間為1個clkB多一點;

           當clkB足夠快,其上升沿采到了din_clkA時,置位作用從clkA的上升沿開始,跨越了clkB的上升沿,那么輸出高電平持續了2個clkB還多一點,因為寄存器1持續了1個周期多一點。

            

實例2:輸入高脈沖(clka域),輸出低脈沖(clkb域)

 

    說明:同上

實例3:輸入低脈沖(clka域),輸出低脈沖(clkb域)

 

    說明:同上

實例4:輸入低脈沖(clka域),輸出高脈沖(clkb域)

 

    說明:同上 

3結繩法3:輸入作為數據輸入,同樣也是檢測高有效后,輸出一直為高,異步時鍾域可以采集到數據后再復位。
因為沒有將輸入作為時鍾,或者作為異步set,reset,所以這類方便比較常用。

參考代碼:

//================================================================================
// Created by         : Ltd.com
// Filename           : sync_clk1_clk2.v
// Author             : Python_Wang
// Created On         : 2009-02-27 22:47
// Last Modified      : 2009-02-28 09:09
// Description        : 
//                      
//                      
//================================================================================
module sync_clk1_clk2(
  clk1                       ,
  rst_n1                     ,
  clk2                       ,
  rst_n2                     ,
  data_clk1_i                ,
  data_clk2_o              
);
input        clk1            ;
input        rst_n1          ;
input        clk2            ;
input        rst_n2          ;
input        data_clk1_i     ;
output       data_clk2_o     ;

reg          data_clk1_q1    ;
reg          data_clk1_q2    ;

reg          data_clk2_q1    ;
reg          data_clk2_q2    ;
reg          data_clk2_q3    ;
reg          data_clk2_q4    ;
reg          data_clk2_q5    ;

wire         data_clk1       ;

assign  data_clk1 = data_clk1_i | ( !data_clk2_q5 & data_clk1_q1) ;

always@(posedge clk1 or negedge rst_n1)
begin
  if(!rst_n1) begin
    data_clk1_q1  <= #1 'b0;
    data_clk1_q2  <= #1 'b0;
  end
  else begin
    data_clk1_q1  <= #1 data_clk1   ;
    data_clk1_q2  <= #1 data_clk1_q1;
  end
end

always@(posedge clk2 or negedge rst_n2)
begin
  if(!rst_n2) begin
    data_clk2_q1  <= #1 'b0;
    data_clk2_q2  <= #1 'b0;
    data_clk2_q3  <= #1 'b0;
  end
  else begin
    data_clk2_q1  <= #1 data_clk1_q1;
    data_clk2_q2  <= #1 data_clk2_q1;
    data_clk2_q3  <= #1 data_clk2_q2;
  end
end

always@(posedge clk1 or negedge rst_n1)
begin
  if(!rst_n1) begin
    data_clk2_q4  <= #1 'b0;
    data_clk2_q5  <= #1 'b0;
  end
  else begin
    data_clk2_q4  <= #1 data_clk2_q2;
    data_clk2_q5  <= #1 data_clk2_q4;
  end
end

assign data_clk2_o = data_clk2_q2 & ~data_clk2_q3 ;

endmodule


仿真:

4.結繩法3:利用握手協議:(可以將脈沖無限延長,直到可以采集到數據,然后復位,要考慮產生數據的頻率)。

 

               Pulse2Toggle                             Synchronization                    Toggle2Pluse

 

 

               Toggle2Pluse                             Synchronization                      Pluse2Toggle       


         說明:        結繩模塊(Pluse2Toggle): 負責延長待采樣信號

                           同步模塊(Synchronization):負責雙觸發器鎖存

                           解繩模塊(Toggle2Pluse):  負責將長信號轉換成脈沖信號 

    

 

參考代碼:

//================================================================================
// Created by         : Ltd.com
// Filename           : handover.v
// Author             : Python_Wang
// Created On         : 2009-02-19 19:31
// Last Modified      : 2009-02-20 08:38
// Description        : 
//                      
//                      
//================================================================================
module handover(
rst_n                        ,
ClkA                         ,
Req_ClkA                     ,
Ack_ClkA                     ,
ClkB                         ,
Dvld_ClkB                   
);
input        rst_n           ;
input        ClkA            ;
input        Req_ClkA        ;
input        ClkB            ;
output       Ack_ClkA        ;
output       Dvld_ClkB       ;
reg          Dvalid_ClkB     ;
reg          Q_Dvalid_ClkB   ;


reg          Dvalid_ClkA     ;
always@(posedge ClkA) 
begin
  if(!rst_n) begin
    Dvalid_ClkA <= #1 1'b0;
  end
  else if(Req_ClkA) begin
    Dvalid_ClkA <= #1 ~Dvalid_ClkA ;
  end
end


reg          Q1_ClkB         ;
reg          Q2_ClkB         ;
reg          Q3_ClkB         ;
always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Q1_ClkB <= #1 'b0;
    Q2_ClkB <= #1 'b0;
    Q3_ClkB <= #1 'b0;
  end
  else begin
    Q1_ClkB <= #1 Dvalid_ClkA ;
    Q2_ClkB <= #1 Q1_ClkB     ;
    Q3_ClkB <= #1 Q2_ClkB     ;
  end
end

wire Req_ClkB = Q2_ClkB ^ Q3_ClkB ;


always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Dvalid_ClkB   <= #1 'b0;
    Q_Dvalid_ClkB <= #1 1'b0;
  end
  else if(Req_ClkB) begin
    Dvalid_ClkB   <= #1 ~Dvalid_ClkB ;
    Q_Dvalid_ClkB <= #1 Dvalid_ClkB  ;
  end
end

always@(posedge ClkB) 
begin
  if(!rst_n) begin
    Q_Dvalid_ClkB <= #1 1'b0;
  end
  else begin
    Q_Dvalid_ClkB <= #1 Dvalid_ClkB  ;
  end
end


reg          Q1_ClkA         ;
reg          Q2_ClkA         ;
reg          Q3_ClkA         ;
always@(posedge ClkA) 
begin
  if(!rst_n) begin
    Q1_ClkA <= #1 'b0 ;
    Q2_ClkA <= #1 'b0 ;
    Q3_ClkA <= #1 'b0 ;
  end
  else begin
    Q1_ClkA <= #1 Dvalid_ClkB ;
    Q2_ClkA <= #1 Q1_ClkA     ;
    Q3_ClkA <= #1 Q2_ClkA     ;
  end
end

assign  Ack_ClkA = Q2_ClkA ^ Q3_ClkA ;
assign  Dvld_ClkB = Dvalid_ClkB & ~Q_Dvalid_ClkB;

endmodule

仿真:

另外對於為了提高速度和准確度的握手操作中,可以將設置一定的握手模塊(n>2(clk1+clk2)/Trd),流水操作

 

結繩就是將單脈沖延長,以方便采集到數據。

結繩的方法歸結為2類:

1.利用脈沖的邊沿做時鍾;

2.利用脈沖的電平(部分場合要求最小脈沖寬度)做選擇器或者異步復位,置位。

 

另外的關鍵點就是什么時候結繩結束(采集到了數據就要讓對方回到初始狀態),

這里的操作也有2種方法:

1.利用采集到的脈沖做異步復位,置位。

2.利用采集到的脈沖再次結繩采集做握手響應信號。

 

處理的時候應該選擇對應的方法。


免責聲明!

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



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