FPGA設計中的異步復位、同步釋放思想


1.一個簡單的異步復位例子:

module test(
  input clk,
  input rst_n,
  input data_in,
  output reg out
);

always@(posedge clk or negedge rst_n)
  if(!rst_n)
    out <= 0;
  else
    out <= data_in;

endmodule

綜合結果如下:

 

 

我們可以看到,FPGA的寄存器都有一個異步清零端(CLR),在異步復位設計中,低電平有效的rst_n復位信號就可以直接連在這個端口上。(如果是高有效的復位,綜合時會把它取反后接在這個端口上)

 2.一個同步復位的例子:

module test(
  input clk,
  input rst_n,
  input data_in,
  output reg out
);

always@(posedge clk)
  if(!rst_n)
    out <= 0;
  else
    out <= data_in;

endmodule

 綜合結果如下:

我們可以看到,該電路中沒有用到寄存器的CLR端,而是把rst_n復位信號作為輸入邏輯的使能信號,那么這樣的同步復位勢必會額外增加FPGA內部的資源消耗。

3.那么,同步復位和異步復位到底孰優孰劣?

  實際上,同步復位和異步復位各有千秋。

  對於同步復位:

    優點:只在時鍾上升沿(或下降沿)判斷系統復位是否出現,降低了亞穩態的概率;

    缺點:就是之前說過的,額外增加了資源消耗;

  對於異步復位,它的優缺點剛好和同步復位相反。這里舉個例子來說明異步復位帶來的亞穩態問題:

module test(
    input clk,
    input rst_n,
    input a,
    output reg c
);
 
reg b;
always@(posedge clk or negedge rst_n)
       if(!rst_n) begin
            b <= 1'b0;
            c <= 1'b0;
       end
       else begin
            b <= a;
            c <= b;
        end         

endmodule      

綜合結果如下:

  正常情況下,clk的上升沿c更新為b,b更新為a。一旦進入復位,b,c都清零;但是我們不能確定復位信號rst_n會在什么時候結束。如果結束於b_reg0和c_reg0的{launch edge –stup,launch edge+hold}時間只外,那么一切都會正常。但如果恰恰相反,會出現什么情況呢? rst_n的上升變化出現在了clk上升的建立保持時間上,此時clk檢測到的rst_n的狀態就會是一個亞穩態(是0是1不確定)。從代碼里我們看到如果此時b_reg0和c_reg0認為rst_n為0,那么依然保持復位清零,而如果認為rst_n為1,那么就跳出復位。因為此時的rst_n的不確定性,就可能出現4種情況,即b_reg0和c_reg0都復位或者都跳出復位,再或者一個復位一個跳出復位。那么后者就會造成了系統工作不同步的問題,在這個簡單的兩級異步復位實例中這種危害表現的並不明顯,但是我們試想一個大的工程項目里眾多的寄存器出現如此情況又會是如何一番景象呢?

4.如何兼顧它們倆的優點,同時避免它們的缺點?

   答案是:異步復位,同步釋放!

module test(
  input clk,
  input rst_n,
  input a,
  output reg c
);
 
reg b,rst_nr;
always@(posedge clk)
    rst_nr <= rst_n;  
            
always@(posedge clk or negedge rst_nr)
         if(!rst_nr) begin
        b <= 1'b0;
        c <= 1'b0;
      end
     else begin
       b <= a; 
       c <= b;
     end
                    
endmodule

綜合結果如下:

如此一來,既解決了同步復位的資源消耗問題,也解決了異步復位的亞穩態問題。其根本思想,也是將異步信號同步化。

5.最終的改進型終極異步復位、同步釋放電路

代碼如下:

module test ( 
  input clk, 
  input rst_n, 
  output reg rst_out 
); 
reg R1; 
    
always@(posedge clk or negedge rst_n)
  if(!rst_n) begin
    R1 <= 1'b0;
    rst_out <= 1'b0;
  end
  else begin
    R1 <= 1'b1;  //這里寫成1,而不寫成rst_n,是因為根據實際綜合效果來看,這樣做更節省資源,具體原因參考同步復位
    rst_out <= R1;
  end

//可選
//wire rst_o;
//assign rst_o = rst_out;

endmodule

 綜合結果如下:(這個例子只是單純的復位電路,沒有功能電路

  加上此復位電路以后,假設第一級D觸發器clk上升沿時rst_n正好撤除,則D觸發器1輸出高電平“1”,此時第二級觸發器也會更新輸出,但是輸出值為前一級觸發器次clk來之前時的Q1輸出狀態。顯然Q1之前為低電平,顧第二級觸發器輸出rst_out保持復位低電平,直到下一個clk來之后,才隨着變為高電平。即同步釋放。

只做一級觸發器來同步,效果如何?

  第一級觸發器的輸出,永遠存在亞穩態的可能。亞穩態導致系統不會復位初始化到已知狀態。 
  當第一級觸發器采樣異步輸入之后,允許輸出出現的亞穩態可以長達一個周期,在這個周期內,亞穩態特性減弱。在第二個時鍾沿到來時,第二級同步器采樣,之后才把該信號傳遞到內部邏輯中去。第二級輸出是穩定且已被同步了的。如果在第二級采樣時保持時間不夠,第一級的輸出仍然處於很強的亞穩態,將會導致第二級同步器也進入亞穩態,但這種故障出現的概率比較小。

  一般情況下,兩級同步器總體的故障概率是一級同步器故障概率的平方。在大部分的同步化設計中,兩級同步器足以消除所有可能的亞穩態了。

 兩級觸發器做同步,是非總線信號的最常見異步處理方法。總線信號的異步處理方法,最常見的是異步fifo實現。

6.那么,到底什么情況下需要做“異步復位、同步釋放”處理?

答案:一般來說,同步系統,都使用異步復位。這是因為同步復位的電路實現,比異步復位的電路實現,要浪費更多電路資源。 

  未在本模塊時鍾域做過“異步復位,同步釋放”處理的復位信號,提供給本模塊做異步復位使用時,都需要做“異步復位,同步釋放”處理。常見於系統內兩部件不在同一時鍾域的情況下。

 

  工程實踐中,確實見過由於未做異步復位的同步處理,而出現大概率系統死機現象(復位的作用域是很大的)。

  通常對異步復位電路的時序分析稱為 恢復時間檢查移除時間檢查

 

 

想了解更多,可以參考該鏈接http://www.eefocus.com/coyoo/blog/13-12/301045_9c39f.html


免責聲明!

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



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