| |
下面是一个异步复位危害的例子,这是我自己想了好久才想出来的,不对的地方请高手指出。
代码很简单,就是一个计时器,设置了一个8位的定时计时器counter(也可以是更多的位),复位的时候counter清0,复位释放时counter在CLK作用下开始自加1。
ssssalways @(posedge clk or negedge rst_n)
if(!rst_n) counter<= 8'b0;
else begin
counter<=counter+1'b1;
rst_sync<=counter;
end
如果正常复位的话,counter[7:0]的8个触发器都会在复位释放后从0开始计数,但如果异步复位导致寄存器处于亚稳态,触发器的输出端Q7:Q0就处于一个不确定的状态,可能有的是0,有的是1,就像下图一样,这样子当下一个CLK到来的时候,counter[7:0]就不是从0开始自加1,而是有可能从0-255的任意一个数开始加1。
显而易见,如果后级模块需要靠这个counter精确定时序,肯定会产生错误。
如果只有一个触发器,其输出端Q做下一级模块的启动标志位,复位时Q=0,在复位释放时处于亚稳态,本应该输出还为0,但如果错误的输出1,导致下一级模块启动,再接着会导致后级出现更多的问题。
复位亚稳态的问题看来都是因为触发器输出端处于不确定状态导致的,而解决思路就是使其复位释放时输出处于确定状态,其实就是使用异步复位同步释放的办法。
从网上的设计来看主要有两种电路:
input CLK,RSTn;
output rstn_r2;
reg rstn_r1,rstn_r2;
always@(posedge CLK or negedge RSTn)
if(!RSTn) rstn_r1<=1'b0;
else rstn_r1<=1'b1;
always@(posedge CLK or negedge RSTn)
if(!RSTn) rstn_r2<=1'b0;
else rstn_r2<=rstn_r1;
其综合出来的RTL视图为:
上图使用rstn_r2作为后级的复位输出,为什么它能实现正常复位呢,我开始时百思不得其解,因为我犯了两个错误:
1错误地认为对于单级的异步复位,即使在RST释放时处于当前时钟的上升沿而导致触发器输出亚稳态,比如触发器要输出1但是因为亚稳态输出0,但是到下一个CLK不就输出1了吗?
——这种分析没有考虑周全,如果一个边沿检测寄存器 (触发器)作为下一个的标志位,要求在复位时为0,复位释放后如果边沿检测输入没有下降沿则要求输出为0,只有在有下降沿输入时其触发器输出才为1,而如果触发器因为亚稳态在复位释放时就输出为1,则会错误置边沿检测标志位为1,导致后级认为发生了边沿下降。
2错误地把理想状态和实际状态混到一起了,我认为rstn_r2复位释放上升到1的期间正好在CLK上升沿,那么这个给后一级的复位也会处于亚稳态。
——其实不是这样的,rstn_r2复位释放上升1的期间正好在CLK上升沿是理想状态下的时序,理想状态下这样完全可以正常让后级复位,因为就算是单级的异步复位在理想状态时,如果CLK和RSTn上升沿完全重合也可以正常复位(这是从RTL仿真看出来的),让我们来看看实际状态的时序图。
异步复位信号RSTn在任意时间释放,
假设正好在CL1的上升沿释放,则触发器rstn_r1处于亚稳态,在CLK=1时错误输出为0;
直到CLK2来到后正确检测到RSTn=1才使rstn_r1正确输出1,rstn_r1要比CLK延迟Tco1,此时rstn_r2因为非阻塞赋值还是为0;
CLK3到来时正确检测到rstn_r1为1,所以rstn_r2正确输出为1,rstn_r2要比CLK延迟Tco2,如果理想状态下rstn_r2和CLK是同时上升的,但是在实际状态下触发器输出总比CLK延迟Tco时间,所以这个rstn_r2作为下一级的复位端不会和当前CLK同时上升,因此不会出现亚稳态,下一级的复位释放要到CLK4来到才能释放。
这样就保证了复位释放时触发器处于稳定状态。
input d,CLK,RSTn;
output q;
reg q,rstn;
always@(posedge CLK)
if(!RSTn) rstn<=1'b0;
else rstn<=1'b1;
always@(posedge CLK or negedge rstn)
if(!rstn) q<=1'b0;
else q<=d;
其综合出来的RTL视图如下:
上图首先用触发器把RSTn同步一下,采用触发器输出端rstn作为下一级的复位端, 时序图如下;
CLK0时,复位还没结束,RSTn,rstn,q都还处于复位状态;
CLK1时,RSTn复位释放,对于触发器rstn其输入是处于亚稳态,按照错误触发就是rstn输出为0;
则CLK2时RSTn已经稳定,rstn经过Tco1延时后输出正常为1,当然这时候的CLK2已经在上升沿之后不能检测rstn,而rstn作为触发器q的复位端在CLK3到来之前就已经保持稳定,即处于CLK3的Tsu和Th之外;
所以CLK3来到时触发器q能正确复位。
从上面的两个例子可以看出只要使用同步器把RSTn同步,就可以使RSTn在释放时输出的rstn端落在CLK的Tsu和Th之外,保证CLK采样时处于稳定状态。