為什麼要非同步復位,同步釋放
一個簡單的非同步復位的例子
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正常情況下,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
|