异步复位实例:
1 module async_rst ( 2 input din, 3 input clk, 4 input rst_n, 5 6 output reg dout 7 ); 8 9 always @ (posedge clk or negedge rst_n) 10 begin 11 if (!rst_n) 12 dout <= 1'b0; 13 else 14 dout <= din; 15 end 16 17 endmodule
同步复位实例:
1 module sync_rst ( 2 input din, 3 input clk, 4 input rst_n, 5 6 output reg dout 7 ); 8 9 always @ (posedge clk) 10 begin 11 if (!rst_n) 12 dout <= 1'b0; 13 else 14 dout <= din; 15 end 16 17 endmodule
异步复位与同步复位比较:
同步复位更耗资源,异步复位存在亚稳态。
异步复位产生亚稳态实例:
1 module async_rst_metastability ( 2 input din, 3 input clk, 4 input rst_n, 5 6 output reg dout1, 7 output reg dout2 8 ); 9 10 always @ (posedge clk or negedge rst_n) 11 begin 12 if (!rst_n) 13 dout2 <= 1'b0; 14 else 15 dout2 <= dout1; 16 end 17 18 always @ (posedge clk or negedge rst_n) 19 begin 20 if (!rst_n) 21 dout1 <= 1'b0; 22 else 23 dout1 <= din; 24 end 25 26 endmodule
正常情况下,clk上升沿到来时 dout1 将更新为 din ,dout2 将更新为 dout1 。一旦复位,dout1、dout2 都为 0 ,但是并不确定复位信号什么时候结束。如果 rst_n 的撤销时间(低电平变为高电平)出现在 clk 锁存数据的建立时间或者保持时间内,此时 clk 检测到 rst_n 的状态就会是一个亚稳态(不确定是 0 还是 1)。
由于此时 rst_n 的不确定性,可能出现四种情况,即 dout1~reg0 和 dout2~reg0 都复位或者都跳出复位,再或者一个复位一个跳出复位,那么后者就会造成系统工作不同步的问题。这个简单二级异步复位这种危害不明显,但是在大工程里隐患将非常大。
异步复位、同步释放实例:
1 module async_rst_sync_rel ( 2 input clk, 3 input rst_n, 4 5 output reg dout 6 ); 7 reg dout_reg; 8 9 always @ (posedge clk or negedge rst_n) 10 begin 11 if (!rst_n) 12 dout_reg <= 1'b0; 13 else 14 dout_reg <= 1'b1; 15 end 16 17 always @ (posedge clk or negedge rst_n) 18 begin 19 if (!rst_n) 20 dout <= 1'b0; 21 else 22 dout <= dout_reg; 23 end 24 25 endmodule
或者这么写:
1 module async_rst_sync_rel ( 2 input clk, 3 input rst_n, 4 5 output reg dout ); 6 7 reg dout_reg; 8 9 always @ (posedge clk or negedge rst_n) 10 begin 11 if (!rst_n) begin 12 dout_reg <= 1'b0; 13 dout <= 1'b0; 14 end 15 else begin 16 dout_reg <= 1'b1; 17 dout <= dout_reg; 18 end 19 end 20 21 endmodule
把 dout 作为复位信号。