異步復位同步釋放---關於復位的問題

一個簡單的異步復位的例子 

複製代碼
1 module test 2 ( 3  input clk, 4  input rst_n, 5  input data_in, 6  output reg out 7 ); 8  always @ (posedge clk or negedge rst_n) 9 if(!rst_n) out <= 1'b0; 10   else out <= data_in; 11  endmodule
複製代碼

我們可以看到FPGA的寄存器都有一個異步的清零端(CLR),在異步復位的設計中這個端口一般就是接低電平有效的復位信號rst_n。

即使說你的設計中是高電平復位,那麼實際綜合後會把你的復位信號反向後接這個CLR端。

                  一個簡單的同步復位的例子 

複製代碼
1 module test 2 ( 3  input clk, 4 input rst_n, 5 input data_in, 6 output reg out 7 ); 8 always @ (posedge clk ) 9 if(!rst_n) out <= 1'b0; 10 else out <= data_in; 11 endmodule
複製代碼

   和異步復位相比,同步復位沒有用上寄存器的CLR端口,綜合出來的實際電路只是把復位信號rst_n作爲了輸入邏輯的使能信號。那麼,這樣的同步復位勢必會額外增加FPGA內部的資源消耗。 

 

       那麼同步復位和異步復位到底孰優孰劣呢? 

       只能說,各有優缺點。同步復位的好在於它只在時鐘信號clk的上升沿觸發進行系統是否復位的判斷,這降低了亞穩態出現的概率;它的不好上面也說了,在於它需要消耗更多的器件資源,這是我們不希望看到的。FPGA的寄存器有支持異步復位專用的端口,採用異步復位的端口無需額外增加器件資源的消耗,但是異步復位也存在着隱患。異步時鐘域的亞穩態問題同樣的存在與異步復位信號和系統時鐘信號之間。

 

 

再看下面一個兩級寄存器異步復位的例子

 

複製代碼
1 module test 2 ( 3 input clk, 4 input rst_n, 5 input a, 6 output reg c 7 ); 8 9 reg b; 10 always @ (posedge clk or negedge rst_n) 11 if(!rst_n) b <= 1'b0; 12 else b <= a; 13 14 always @ (posedge clk or negedge rst_n) 15 if(!rst_n) c <= 1'b0; 16 else c <= b; 17 18 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都復位或者都跳出復位,再或者一個復位一個跳出復位。那麼後者就會造成了系統工作不同步的問題,在這個簡單的兩級異步復位實例中這種危害表現的並不明顯,但是我們試想一個大的工程項目裏衆多的寄存器出現如此情況又會是如何一番景象呢?

       上面的分析似乎都讓人意識到同步復位和異步復位都不可靠,那麼如何將兩者結合,取長補短呢。

 

                    異步復位、同步釋放

 

複製代碼
1 module test 2 ( 3 input clk, 4 input rst_n, 5 input a, 6 output reg c 7 ); 8 9 reg b,rst_nr; 10 always @ (posedge clk) 11 rst_nr <= rst_n; 12 13 always @ (posedge clk or negedge rst_nr) 14 if(!rst_nr) b <= 1'b0; 15 else b <= a; 16 17 always @ (posedge clk or negedge rst_nr) 18 if(!rst_nr) c <= 1'b0; 19 else c <= b; 20 21 endmodule
複製代碼

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

最好的異步復位、同步釋放--------復位方法

 

複製代碼
library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity test is port( sys_clk : in std_logic; rst_in : in std_logic; rst_out : out std_logic ); end test; architecture behave of test is begin rst_pro : process(sys_clk,rst_in) begin if rst_in = '0' then rst_out <= '0'; elsif rising_edge(sys_clk) then rst_out <= '1'; end if; end process rst_pro; end behave;
複製代碼

對應的Verilog程序如下

複製代碼
1 module test 2 ( 3  input clk, 4  input rst_n, 5  output reg rst_out 6 ); 7 8 always @ (posedge clk,negedge rst_n) 9 if(!rst_n) 10 rst_out<=1'b0; 11   else 12 rst_out<=1'b1; 13  endmodule
複製代碼

要是代碼改成

複製代碼
1 module test 2 ( 3  input clk, 4 input rst_n, 5 output reg rst_out 6 ); 7 8 always @ (posedge clk,negedge rst_n) 9 if(!rst_n) 10 rst_out<=rst_n; 11 else 12 rst_out<=1'b1; 13 endmodule
複製代碼

那麼綜合出來的RTL電路

--------------------------------------------------------------

改進的最終復位電路如下----------------------------------------

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
module rst
(
  input clk,
  input rst_n,
  output reg rst_out
);
reg R1;
    
always @ (posedge clk,negedge rst_n)
     if(!rst_n)
         begin
             R1 <= 1'b0;
             rst_out <= 1'b0;
         end
     else
         begin
             R1 <= 1'b1;
             rst_out <= R1;
        end
endmodule

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章