一个简单的异步复位的例子 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 检测...