總結“異步復位,同步釋放”


  復位的功能是很有必要的,讓一切正在處於工作狀態的器件的狀態恢復到初始態,可以起到重新開始工作的作用。復位有上電復位和按鍵復位兩種常見方式。

  先說一下按鍵復位

  一開始,我們在設計按鍵復位的邏輯功能時,第一反應就是利用D觸發器的異步清零端(clr端),這種方式稱為異步復位,代碼和RTL圖如下:

1 always@(posedge clk or negedge rst_n)
2 begin
3     if(rst_n == 1'b0)
4         q <= 1'b0;
5     else
6         q <= 1'b1;
7 end                                                                    

 

  

 

 

 

 

 

 

 

 

  采取異步復位的方式的優點是不需要額外的資源,直接使用寄存器自帶的異步清零端即可。缺點是存在亞穩態狀態。

  1. 當clk上升沿到來時,rst_n正好由高電平變為低電平(處於復位狀態),這時rst_n具有優先級,寄存器直接進行初始態。

  2. 當clk上升沿到來時,rst_n正好由低電平變為高電平(處於置位狀態),這時寄存器是認為rst_n為1,鎖存此刻的值a,輸出前一個時鍾周期的b呢,還是認為rst_n為0,該開始初始化了呢(打架了,造成了亞穩態)

 

  那這種方式存在問題,我們再來看看同步復位的方式,代碼和RTL圖如下:

  

1 always@(posedge clk) 2 begin
3     if(rst_n == 1'b0)
4         q <= 1'b0;
5     else
6         q <= 1'b1;
7 end

  

  1. 當clk上升沿到來時,rst_n正好由高電平變為低電平(處於復位狀態),此刻寄存器僅受clk的控制,認為采樣到的是rst_n的高電平,繼續輸出已存數值,下一個時鍾周期才認為rst_n是低電平,進行初始化。

  2. 當clk上升沿到來時,rst_n正好由低電平變為高電平(處於置位狀態),此刻寄存器僅受clk的控制,認為采樣到的是rst_n的低電平,繼續初始化,下一個時鍾周期才認為rst_n是高電平,輸出響應的值。

   但是采取同步復位的方式的雖然能減小亞穩態的發生,但是需要額外的資源。

 

  異步復位和同步復位都有優缺點,將兩者相互結合,互補一下,便出現了“異步復位,同步釋放”的方式,很好的解決了兩者的不足。代碼和RTL圖如下: 

 1 module sys_ctrl(
 2     input                clk,
 3     input         rst_n,
 4     output    reg    sys_rst_n
 5 );
 6 
 7 reg    rst_1;
 8 
 9 always@(posedge clk or negedge rst_n)
10 begin
11     if(!rst_n == 1'b0)
12         rst_1 <= 1'b0;
13     else
14         rst_1 <= 1'b1;
15 end
16 
17 always@(posedge clk or negedge rst_n)
18 begin
19     if(rst_n == 1'b0)
20         sys_rst_n <= 1'b0;
21     else
22         sys_rst_n <= rst_1;
23 end
24 
25 
26 endmodule    

  

  這樣就既利用了異步復位的清零端進行復位,不需要額外開支資源,又利用了同步復位的釋放優點,將異步復位的釋放電平延遲1個時鍾周期,然后再將延遲后的釋放電平信號作為系統復位信號,避免了釋放時亞穩態的發生。

  下面說一下上電復位

  系統在每次上電復位初始化時,需要消耗很多方面的時間,大體如下:

  1. 電源等芯片的轉換時間

  2. FPGA的啟動到穩定的時間

  3. 外圍電路的啟動時間

  所以,為了保證FPGA上電復位后更加的穩定,可以在上電開始后,進行一定的延遲時間來保證FPGA可以達到穩定的狀態。綜合以上代碼如下:

  

 1 module test(
 2     input      clk,
 3     input      rst_n,
 4     output reg   sys_rst_n
 5 );
 6 
 7 parameter    RST_TIME = 24'd2_500_000;                //50ms
 8 
 9 reg        rst_1;
10 reg    [23:0]  cnt_rst;
11 
12 always@(posedge clk or negedge rst_n)
13 begin
14     if(rst_n == 1'b0)
15         cnt_rst <= 24'd0;
16     else
17         if(cnt_rst < RST_TIME)
18             cnt_rst <= cnt_rst +1'b1;                    
19         else
20             cnt_rst <= cnt_rst;
21 end
22 
23 always@(posedge clk or negedge rst_n)
24 begin
25     if(rst_n == 1'b0)begin
26         rst_1 <= 1'b0;
27         sys_rst_n <= 1'b0;
28     end
29     else begin
30         if(cnt_rst == RST_TIME)begin
31             rst_1 <= 1'b1;
32             sys_rst_n <= rst_1;
33         end
34         else begin
35             rst_1 <= 1'b0;
36             sys_rst_n <= 1'b0;
37         end
38     end
39 end
40 
41 endmodule

  

 


免責聲明!

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



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