数字设计--复位

复位的目的

复位信号在数字电路里面的重要性仅次于时钟信号。对电路的复位往往是指对触发器的复位,也就是说电路的复位中的这个“电路”,往往是指触发器,这是需要注意的。有的电路需要复位信号,就像是有的电路需要时钟信号那样,而有的电路是不需要复位信号的。复位又分为同步复位异步复位,这两种各有优缺点。

为什么需要复位

  1. 复位可以使电路从确定的初始状态开始运行

上电的时候,为了避免上电后进入随机状态而使电路紊乱,这个时候就需要上电复位。

有时候,在运行时,要求电路从初始状态开始执行电路的功能(就比如处理完一些数据通过复位清空电路状态来处理下一个数据),要对电路进行复位,让它从最初的状态开始运行。

  1. 复位可以使电路从错误状态回到可以控制的确定状态

有的时候,你的电路发生了异常,比如说状态机跑飞了、系统供电炸了之类的,总之就是电路运行得不正常了,这个时候你就要对电路进行复位,让它从错误的状态回到一个正常的状态。

  1. 仿真的时候,需要电路具有已知的初始值

在仿真的时候,信号在初始状态是未知状态(也就是所谓的x,不过对信号初始化之后的这种情况除外,因为仿真的时候对信号初始化就使信号有了初始值,这就不是x了)。

对于数据通路(数字系统一般分为数据通路和控制通路,数据通路一般是对输入的数据进行处理,控制通路则是对运行的情况进行操作),在实际电路中,只要输入是有效数据(开始的时候可能不是有效的),输出后的状态也是确定的;在仿真的时候,也是输入数据有效了,输出也就确定了。也就是说,初始不定态对数据通路的影响不明显

对于控制通路,在实际电路中,只要控制通路完备(比如说控制通路的状态机是完备的),即使初始状态即使是不定态,在经过一定的循环后,还是能回到正确的状态上;然而在仿真的时候就不行了,仿真的时候由于初始状态为未知态,控制电路一开始就陷入了未知态;仿真跟实际电路不同,仿真是“串行”的,仿真时控制信号的初始不定态会导致后续的控制信号结果都是不定态,也就是说,初始的不定态对控制通道是致命的

不需要复位的情况

复位信号很重要,但是并不是每一部分的电路都需要复位电路,一方面是复位电路也消耗逻辑资源、占用芯片面积,另一方面是复位信号会增加电路设计的复杂性(比如要考虑复位的策略、复位的布局布线等等)

当某个电路的输出在任何时刻都可以不受到复位信号的控制就有正确的值时,比如说数据通路中的对数据进行处理的部分。举个例子,在某些情况下,当流水线的寄存器(移位寄存触发器)在高速应用中时,应该去掉某些寄存器的复位信号以使设计达到更高的性能,因为带复位的触发器比不带复位的触发器更复杂,反应也更慢。只有最开始的寄存器需要复位,后面的寄存器不需要复位,因为有前面数据的进入,不用复位也可以进入有效状态。

同步复位

同步复位的意思是当复位信号到达时不立刻复位,而是当遇到时钟上升沿时再复位,寄存器在下一个时钟沿到来之后被复位,时钟沿到来之前寄存器还是保持其之前的值,复位动作与时钟同步,或者说复位受到时钟信号的控制。

Reset可以作为组合逻辑的一部分送给FF的D端。在这种情况下,编码方式必须是if/else且具有优先级的方式,而且reset只能放在if条件下,其他组合逻辑放到else逻辑下。如果不这么写的话,rst的优先级放在后面,其他语句会阻塞rst的复位,导致最后不是想要的结果。

同步复位的例子

module sync_resetFFstyle(
    output reg q,
    input d,clk,rst_n
)
    always @(posedge clk)
        if(!rst_n)
            q <= 1'b0;
        else
            q<= d;
endmodule

同步复位与时钟的有效沿同步 ,always块的敏感列表里面只有时钟的上升沿。

综合出来的结果

image

rst_n作为选择信号控制着寄存器的输入。

当然也可能综合成

image

一个同步复位的例子

module ctr8sr(
    output reg [7:0] q,
    output reg co,
    input [7:0] d,
    input       ld,clk,rst_n
);

always @(posedge clk)
    if(!rst_n)
        {co,q} <= 9'b0;
    else if(ld)
        {co,q} <= d;
    else
        {co,1} <= q + 1'b1;
endmodule

综合出来

image

同步复位,复位信号被加到寄存器的输入端。

但有的时候还会综合成

image

综合成这种形式,在仿真时,如果ld为x,那么复位信号是无法到达寄存器,无法完成复位。但对于实际电路来说并不存在这个问题,因为实际电路没有所谓的“x”状态。

同步复位的优点

  1. 同步复位会综合成更小的触发器,特别当reset生成逻辑电路作为触发器D输入,但是这种情况下组合逻辑电路的数量变多,所以总的门电路节省不是那么显著,但在用到大量需要复位的寄存器的场景下,会使面积大幅下降。
  2. 同步复位确保电路100%是同步的。
  3. 同步复位确保复位只发生在时钟有效边沿,对小的复位毛刺来说,时钟就像滤波器,过滤掉毛刺。采用同步复位不代表着不受毛刺的影响,如果毛刺发生在时钟的有效沿附近,也会导致亚稳态,只能说采用同步复位可以减轻毛刺的影响。
  4. 在一些设计中,复位必须由内部条件产生(内部信号作为复位信号),这时复位信号可能存在毛刺,同步复位能过滤时钟间逻辑等式的毛刺。
  5. 通过使用同步重置和预先确定的时钟数量作为复位过程的一部分。可以在复位缓冲区树中使用触发器,来帮助将缓冲树的时序保持在一个时钟周期以内。有利于进行静态时序分析(同步复位相较于异步复位来收有利于静态时序分析)

同步复位的缺点

  1. 使用同步复位可能使综合工具无法分辨分辨复位信号和其他控制信号,导致进行复位的控制逻辑远离触发器,就像上面我们说的那样,最后综合出来可能会有两种形式,虽然这两种形式在实际电路上功能相同,但是在仿真时,就有可能无法实现我们想要的功能。
    解决方法:Synopsys提供编译器指令sync_set_reset,该指令告诉综合工具给定信号是同步reset(or set)。合成工具将这个信号“拉”到尽可能接近触发器,防止这种初始化问题的发生:// synopsys sync_set_reset "rst_n"这个命令只会影响综合,不会影响逻辑行为,所以推荐在同步复位每个模块都加上这个信号。另外,可以在读取RTL之前将合成变量hdlin_ff_always_sync_set_reset设置为-true,这样就可以得到相同的结果,而不需要在代码本身中执行任何指令。
  2. 不是所有的库都有自带同步reset的FF, 但是可以通过把reset当作数据输入来解决;
  3. 复位信号是一个脉冲,可能无法被时钟信号采到。同步复位需要一个脉冲延伸器,保证复位脉冲足够宽能够被有效时钟沿采集到;特别是在多时钟设计中;捕获到同步复位的方法可以采用脉冲捕捉电路,也可以将复位信号进行脉冲扩展,维持足够长的时间,这个可以通过一个小的计数器实现。
  4. 同步复位电路必须要有一个时钟来复位。如果用门控时钟来省电,那么没有时钟的时候就不能复位;
  5. 在总线控制中,系统上电复位的时候,我们要求不同芯片之间的总线工作在合理的状态上(比如处于高阻态或者输出);然而上电之后,由于系统时钟可能仍未正常工作,上电(同步)复位就可能无效,这个时候各个模块(芯片)就可能不会把总线接口设置为特定的状态,(当多个模块同时输出数据到总线上时)就可能导致电平冲突,严重的话会烧坏接口。如果电路中有三态总线,那么上电时必须用异步复位,如果用同步复位,reset必须能够复位三态信号的enable信号。

image

image

异步复位

异步复位触发器则是在设计触发器的时候加入了一个复位引脚,也就是说复位逻辑集成在触发器里面。(一般情况下)低电平的复位信号到达触发器的复位端时,触发器进入复位状态,直到复位信号撤离。

异步复位信号的优先级要高于时钟信号,当异步复位信号时钟同时有效时,异步复位信号会绕过时钟信号强制进行复位。

image

由于异步复位信号有效,寄存器立刻复位,与时钟信号无关,所以要在过程块的敏感列表中包含异步复位信号

module async_resetFFstyle(
output reg q,
input d,clk,rst_n
);

always @(posedge clk or negedge rst_n)
    if(!rst_n)
        q <= 1'b0;
    else
        q <= d;
endmodule

从上面可以看出,只要异步复位信号发生变化就会进入过程块,完成复位操作。

综合结果

image

一个异步复位的例子

module ctr8ar(
    output reg [7:0] q,
    output reg       co,
    input      [7:0] d,
    input            ld,rst_n,clk
);
always @(posedge clk or negedge rst_n)
    if(!rst_n)
        {co,q} <= 9'b0;
    else if(ld)
        {co,q} <= d;
    else
        {co,q} <= q + 1'b1;

endmodule

综合结果

image

异步复位的优点

  1. 异步复位的最大优点是,vendor库里面有异步复位FF, 这样datapath就十分干净。不用把reset与数据做逻辑,这样复位路径上就不会有额外的延时,也不会受外部信号的干扰。
  2. 异步复位的另一个优点是电路reset和时钟无关,不管有没有时钟,都可以reset。好处是可以实时复位,也可以加在门控时钟里面。门控时钟是低功耗设计的重要方法。
  3. 异步复位不需要加入综合指令,综合工具就能自动识别。不会出现综合出多种可能的情况。

异步复位的缺点

  1. 异步重置的最大问题是它们是异步的,在复位阶段和解复位阶段(复位撤离)都是异步的。复位阶段不是问题,解复位才是问题。如果在触发器的活动时钟边缘或附近释放异步复位,则触发器的输出可能变为亚稳态,这样电路的复位状态可能会丢失,解复位失败。

复位恢复时间(reset recovery time):解除复位信号时,复位边沿(当然是从有效变成无效的跳变时刻,通常是0->1那个时间点)与下一个有效时钟沿之间的这段时间对应建立时间

复位解除时间(reset removal time):解除复位信号时,复位边沿上一个有效时钟沿之间的这段时间。对应保持时间

怎么理解这两个时间呢?

对于寄存器来说,输出数据需要建立时间和保持时间。

如果我们想在一个时钟沿使寄存器输出有效数据(在这个时钟沿前解除复位),但是复位解除的时间离时钟的上升沿过于近,就会导致留给寄存器有效数据建立的时间过小,使寄存器的建立时间无法满足,会使寄存器的输出为亚稳态。

如果我们想在一个时钟沿时使寄存器无效(就是给复位掉),如果复位解除的时间离上一个时钟的上升沿很近,那么就留给寄存器保持复位状态的时间很小,使寄存器无法满足保持时间,那么就无法确定最后寄存器的输出到底复没复位(或者类比保持时间,如果在这段时间内复位解除,寄存器的输入端还是可以输入信号,如果剩余的时间满足了寄存器的保持时间,就有可能没有把这个寄存器复位掉,如果剩下的时间不满足寄存器的保持时间,最终将导致寄存器输出亚稳态)。

恢复时间(Recovery Time)是指异步控制信号(如寄存器的异步清除和置位控制信号)在“下个时钟沿”来临之前变无效的最小时间长度。这个时间的意义是,如果保证不了这个最小恢复时间,也就是说这个异步控制信号的解除与“下个时钟沿”离得太近(但在这个时钟沿之前),没有给寄存器留有足够时间来恢复至正常状态,那么就不能保证“下个时钟沿”能正常作用,也就是说这个“时钟沿”可能会失效。去除时间(Removal)是指异步控制信号(如寄存器的异步清除和置位控制信号)在“有效时钟沿”之后变无效的最小时间长度。这个时间的意义是,如果保证不了这个去除时间,也就是说这个异步控制信号的解除与“有效时钟沿”离得太近(但在这个时钟沿之后),那么就不能保证有效地屏蔽这个“时钟沿”,也就是说这个“时钟沿”可能会起作用。

另一种说法

对于这一个“维持”电路,在时钟沿变化附近,如果“reset”信号有效,那么,就会锁存住“reset”的值;如果reset信号释放,那么这个“维持”电路会去锁当时的D输入端的数据。因此,如果reset信号的“释放”发生在靠时钟沿很近的时间点,那么这个“维持”电路就可能既没有足够时间“维持”住reset值,也没有足够时间“维持”住D输入端的值,因此造成亚稳态,并通过最后一级与非门传到Q端输出。如果reset信号的“释放”时间能够晚一点点,也就是说,让“维持”电路有足够的时间去锁住“reset”的值,那么,我们就可以肯定输出为稳定的“reset”状态了。这一小段锁住“reset”值所需要的时间,就是寄存器的removal TIme要求。

异步复位的复位信号必须满足一定的恢复时间解除时间如果你想让某个时钟沿起作用,那么你就应该在“恢复时间”之前是异步控制信号变无效,如果你想让某个时钟沿不起作用,那么你就应该在“去除时间”过后使控制信号变无效,否则没法确定时钟沿是否起作用了,即判断不了到时是复位了还是没复位。D触发器如果不复位,那么输出就是输入的数据。

1). 不满足复位恢复时间或者撤离时间,可能会导致亚稳态问题。(注意是可能)因为如果输出本身就是复位后的值,即使当前时钟沿不能判断是否复位,输出也是复位值,这时候就不会产生亚稳态,因为已经是复位态了。

2). 不满足复位恢复时间或者撤离时间可能会导致不同FF复位状态不一致的问题。复位信号和时钟信号一样,通过复位网络到达各个触发器。复位网络具有非常大的扇出和负载,到达不同的触发器存在不同的延时不满足复位恢复或者解除时间的情况下,就有可能在不同的触发器的不同时钟周期内进行解复位。注意,这里的假设条件是复位树和时钟树已经做成立平衡状态,不再考虑复位树和时钟树没做好的情况。

  1. 当外部输入的异步复位信号产生毛刺时,任何满足触发器最小复位脉冲宽度的输入都有可能引起触发器复位,这问题是源头上的问题。

异步复位,同步释放

为了结合同步复位和异步复位的优点,同时克服它们各自的缺点,我们一般建议采用异步复位,同步释放的方式。

异步复位的同步释放电路也称为复位同步器

module async_resetFFstyle2(
    output reg rst_n,
    input      clk,asyncrst_n
);
reg rff1;
always @(posedge clk or negedge asyncrst_n)
    if(!asyncrst_n)
        {rst_n,rff1} <= 2'b0;
    else
        {rst_n,rff1} <= {rff1,1'b1}; 
endmodule

image

复位和解复位都是通过pad_rst_n来实现的,第一级FF的输入是拉成高(固定为“1”),第二级的FF用来消除解复位时可能带来的的亚稳态。

为什么两级FF就不会出现亚稳态呢?第一级FF输入是1, 输出的reset值是0,而reset又是异步的,如果reset的解除刚好在clock边沿附近,就会出现亚稳态。

但是加上了第二级FF就不会出现亚稳态。这是因为第二级的FF的输入比第一个FF延时了一个cycle,这样第一个FF在解复位时候,即使有亚稳态,那么也只是影响下一个周期的Q1输出,下一个周期Q1可能为0也可能为1,但是当前Q1还是为低(0), 因为这时第一个FF还是复位状态。这样第二个FF当前周期的输入是0,复位输出也是0,所以能不能复位成功都不会改变输出为0,即当前周期不会产生亚稳态。下一个周期的Q1输出虽然可能是0也可能是1,但是已经稳定,是一个确定的值,所以第二个FF输出也是稳定的值。

抖动和毛刺

由于异步复位和时钟无关,任何一个毛刺都可以引起复位,前面我们说过,这是一个reset源的问题。

解决问题的一个方法是采用下面的结构

image

通过对复位信号进行延时再相与得到确定的复位信号,这个方法虽然有效但是很"ugly",因为里面包含着延时部分,这个延时会受到电压,温度等的影响,这就会对整个系统增加了不确定性。

并不是所有的系统都需要增加防抖,要根据应用范围来判断。

复位树

复位树和时钟树一样应该引起重视,因为典型的数字电路中,reset的负载和clock的负载数量一般是相当的。不管是同步复位还是异步复位,对复位树都是有时序要求的。一个典型的复位树如下图所示:

image

时钟分布树和重置分布树之间的一个重要区别是时钟树需要紧密平衡分布重置之间的偏差(skew)。与时钟信号不同,只要与复位信号相关的延迟足够短,允许在一个时钟周期内传播所有复位负载,并且仍然满足所有目标寄存器和触发器的恢复时间,那么复位信号之间的偏差(skew)就不是关键。(虽然复位信号到达目的寄存器有先有后,但是只要能在一个时钟周期内完成整个系统的复位,满足恢复时间和解除时间就ok)

另外一个需要考虑的问题是,时钟树和复位树之间的关系。到底用那个时钟来驱动复位树的FF呢?如果能够用分支clock来驱动master reset的FF那最好了,但是在大多数情况下,没有足够的时间时钟脉冲遍历时钟树、时钟复位驱动触发器,然后让复位遍历复位树,所有这些都在一个时钟周期内完成。这种情况如下图所示:

image

为了能让reset到达所有逻辑的速度更快,更好的方式是用一个更早的clock来驱动reset ff,即用源时钟来驱动。必须进行Post layout timing分析,以保证复位同步器的FF不会出现setup/hold违例。通常情况下,两个tree之间详细的时序调整必须等到layout完成才能进行。电路结构如下图所示:

image

上述的复位树对同步复位树和异步复位树都是适用的。

同步复位树

对同步复位,一种技术是通过插入FF来实现复位树。这样的好处是,reset不需要在一个时钟周期内到达所有的FF。所以需要几个时钟才能把整个设计复位掉。每个模块都需要包含如下代码:(将复位信号采样打拍)

input reset_raw;

//synopsys sync_set_reset "reset"
always @(posedge clk)
    reset <= reset_raw;

同步复位数如下所示:

image

采用这种技术,同步复位信号可以像其他数据信号一样处理,设计中每个模块的timing分析都很容易,复位树的每个阶段都有合理的扇出。

异步复位树

对异步复位,是通过复位同步器来完成复位树的建立。即每个层级都加上一个异步复位同步器。如下图所示:

image

异步复位树和同步复位树有点相似,但是这里的异步复位同步器是两级的FF。这种异步复位树,复位时可以所有的FF都同时复位,但是解复位必须要几个cycle才能完成。

这种结构的问题就是,不同层级解复位的时间点可能是不一样的。如果设计要求整个芯片在同一个cycle来解复位,那么就需要对复位同步器做平衡设计,保证到达每个复位终点是同一个时钟。同步时钟树也存在这个问题。

多时钟域复位

对于多时钟域的设计,每个时钟域必须有自己单独的复位同步器和分布式复位树。这样才能保证reset能满足不用时钟域的reset recovery time。如下图所示:

image

对于多个时钟域的解复位顺序有两种情况:

  1. 大部分多时钟域的设计,解复位的顺序并没有特殊要求。即当前时钟域解复位的时间点,在另一个时钟域的精确时间点并不重要。通常来说,跨时钟域的设计,本身就会带来延时的不确定行。这种情况下,上面的单独建立不同时钟域的复位结构就足够了。
  2. 有些多时钟设计,复位解除必须按顺序进行。这种设计,可以使用优先级的复位结构如下所示:

image

这种结构,除了最高优先级的同步器输入是 tied 1, 其他的输入都是上一优先级的输出。在复位时同时复位,解复位时依次解复位。


参考
Reset信号 如何同步? - 知乎 (zhihu.com)
芯片设计进阶之路——Reset深入理解 - 知乎 (zhihu.com)
(9条消息) SOC中的复位电路_简单同学的博客-CSDN博客_soc复位设计
异步复位和同步释放电路的详细解释 - love小酒窝 - 博客园 (cnblogs.com)
(10条消息) 什么是recovery time和removal time?_IC小鸽的博客-CSDN博客_recovery time
(10条消息) 静态时序分析之恢复时间recovery time和撤销时间removal time_长苏的博客-CSDN博客_removal时间
(10条消息) 恢复和去除时间(Recovery and Removal Time)_gtkknd的博客-CSDN博客
异步复位信号亚稳态的原因与D触发器的Verilog描述 - 电子常识 - 电子发烧友网 (elecfans.com)

posted @ 2024-07-06 18:39  孤独野猪骑士  阅读(52)  评论(0编辑  收藏  举报