当我们谈起复位的时候,我们谈些什么

写verilog代码的时候太习惯下面的代码了

always@(posedge clk or negedge rst_n)

if(!rst_n)

……

else

……

对于这样的异步复位觉得太理所当然了,但是没怎么想过原因。今天看到有些系统专门针对复位写的module,才发现复位其实还是有些东西没那么理所当然的。

最常见的应该就是如上的异步复位,随处可见。

还有就是同步复位,如下

always@(posedge clk)

if(!rst_n)

……

else

……

从理解上看,异步复位是独立于时钟的,即使时钟出现问题也能复位。同步复位是依赖于时钟的,只有在时钟沿才去检测复位信号,功能上就像load信号,称为loadable(cummings论文集)。

从结构上看,异步复位是简单的,因为触发器一般都是自带有复位信号的,采用复位信号节约硬件资源。同步复位会综合出额外的组合电路。浪费硬件资源。

从电路可靠性看,异步复位信号在释放的时候可能会产生亚稳态(meta-stability),因为复位释放是随机的,如果恰好在时钟上升沿附近,就容易产生亚稳态。系统中很多很多的复位信号,中间还有不同的延迟,有可能有些复位有些没有复位。而且异步复位容易受到下降时间很短的毛刺的影响,即不希望复位的时候复位。同步复位要求复位必须在一个周期以上。

“异步复位,同步释放(SynchronizedAsynchronous Reset)”是完美解决方案。这就结合了双方面的优点,很好的克服了异步复位的缺点(因为异步复位的问题主要出现在复位信号释放的时候)。

其实做起来也并不难:那就是在异步复位键后加上一个所谓的“reset synchronizer”,这样就可以使异步复位信号同步化,然后,再用经过处理的复位信号去作用系统,就可以保证比较稳定了。reset sychronizer的Verilog代码如下:

module sync_rst_gen(
sys_clk,
rst_n,
sync_rst_n
);
input sys_clk,
rst_n;
output sync_rst_n;

reg sync_rst_n1;
reg sync_rst_n;


always@(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
sync_rst_n1 <= 1'b0;
else
sync_rst_n1 <= 1'b1;
end

always@(posedge sys_clk or negedge rst_n)
begin
if(!rst_n)
sync_rst_n <= 1'b0;
else
sync_rst_n <= sync_rst_n1;

end

endmodule

当我们谈起复位的时候,我们谈些什么_第1张图片

你可能感兴趣的:(当我们谈起复位的时候,我们谈些什么)