Asynchronous & Synchronous Reset

发布时间 2023-06-23 16:07:38作者: superego_zhang

第1章 复位的目的

复位信号在数字电路里面的重要性仅次于时钟信号。对一个芯片来说,复位的主要目的是使芯片电路进入一个已知的,确定的状态。主要是触发器进入确定的状态。在一般情况下,芯片中的每个触发器都应该是可复位的。在某些情况下,当在高速应用程序中使用流水线触发器(移位寄存器触发器)时,为了实现更高的性能设计,可能会从某些触发器中消除复位。这种类型设计需要在复位激活期间,运行预先确定数量的时钟周期,以使ASIC处于已知的状态。

1.1 为什么需要复位

使电路从确定的初始状态开始运行

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

中间复位:有时候,要求电路从初始状态开始执行电路的功能,要对电路进行复位,让它从最初的状态开始运行。

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

如果电路发生了异常,比如状态不正常,中断异常,firmware程序跑飞,这个时候就可以对电路进行复位,让它从错误的状态回到一个正常的状态。

电路仿真时需要电路具有已知的初始值

在仿真的时候,信号在初始状态是未知状态。

数字系统一般分为数据通路和控制通路,数据通路一般是对输入的数据进行处理,控制通路则是对运行的情况进行操作。

数据通路

在实际电路中,只要输入是有效数据(开始的时候可能不是有效的),输出后的状态也是确定的;在仿真的时候,也是输入数据有效了,输出也就确定了。也就是说,初始不定态对数据通路的影响不明显。

控制通路

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

1.2 不需要复位的情况

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

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

第2章 同步复位

2.1 同步复位的实现方式

同步复位的前提是,复位信号只会在时钟的有效边沿去影响或者复位flip-flop。Reset可以作为组合逻辑的一部分送给FF的D端。这种情况下,编码方式必须是if/else 优先级的方式,而且reset只能放在if条件下,其他组合逻辑放到else逻辑下。

正确的方式去构建同步复位FF的verilog代码如下:

module sync_resetFFstyle (output reg q,

                          input d,

                          clk,

                          rst_n);

   

    always @(posedge clk)

        if (!rst_n) q <= 1'b0;

        else        q   <= d;

endmodule

 

如果没有严格遵守这种方式,会有两个问题:

一些仿真器中,基于逻辑方程,逻辑可能组织复位到达触发器。这只是一个仿真问题,不是硬件问题。但是复位的一个主要目的,就是仿真的时候将电路置于一个已知的确定状态。

由于复位树的高扇出,复位信号可能是一个相对于时钟周期的“延迟到达信号”,尽管复位将从复位缓冲区树中进行缓冲,但明智的做法是限制复位到达本地逻辑后必须经过的逻辑量。就是说必须对复位信号少做逻辑。

下面的列子是一个同步复位的,带进位的计数器,它的电路图如下:

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;    // sync reset

    else if (ld)    {co,q} <= d;    // sync load

    else    {co,q} <= q + 1'b1; // sync increment

endmodule

图1 Loadable counter with synchronous reset

图2 Loadable counter with synchronous reset style 2

 

同步复位的有一个问题就是,综合工具不能很好的把reset信号和其他的信号区分开。比如上面的电路也可能被综合成另外的电路。

图1和图2是完全相同的。唯一的区别是图2的reset信号被提前到了MUX之前。通过rst_n拉低,可以强制MUX的两个分支的输入为0,但是如果ld是未知的(X),并且MUX模型是悲观的,则会保持未知(X)不会被复位。注意,这只是在仿真过程中出现的问题! 实际的电路可以工作正确并将其重置为0。

Synopsys提供编译器指令sync_set_reset,该指令告诉综合工具给定信号是同步reset(or set)。合成工具将这个信号“拉”到尽可能接近触发器,防止这种初始化问题的发生:

// synopsys sync_set_reset "rst_n"

这个命令只会影响综合,不会影响逻辑行为,所以推荐在同步复位每个模块都加上这个信号。

另外,可以在读取RTL之前将合成变量hdlin_ff_always_sync_set_reset设置为-true,这样就可以得到相同的结果,而不需要在代码本身中执行任何指令。

2.2 同步复位的优点和缺点

2.2.1 优点

同步复位会综合成更小的触发器,特别当reset生成逻辑电路作为触发器D输入,但是这种情况下组合逻辑电路的数量变多,所以总的门电路节省不是那么显著。

同步复位确保电路100%是同步的。

同步复位确保复位只发生在时钟有效边沿,对小的复位毛刺来说,时钟就像滤波器。

在一些设计中,复位必须由内部条件产生。同步复位能过滤时钟间逻辑等式的毛刺。

通过使用同步复位和预先确定的时钟数量作为复位过程的一部分。可以在复位缓冲树中使用触发器,来帮助将缓冲树的时序保持在一个时钟周期以内。

2.2.2 缺点

不是所有的库都有自带同步reset的FF, 但是可以通过把reset当作数据输入来解决;

同步复位需要一个脉冲延伸器保证复位脉冲足够宽能够被有效时钟沿采集到;特别是在多时钟设计中;

同步复位电路必须要有一个时钟来复位。如果用门控时钟来省电,那么没有时钟的时候就不能复位;

如果电路中有三态总线,那么上电时必须用异步复位,如果用同步复位,reset必须能够复位三态信号的enable信号。

 

Asynchronous reset for output enable

 

Synchronous reset for output enable

第3章 异步复位

3.1 异步复位的实现

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

 

module async_resetFFstyle (output reg q,

                           input    d,

                           clk,

                           rst_n);

    // @(posedge clk, negedge rst_n)

    always @(posedge clk or negedge rst_n)

        if (!rst_n) q <= 1'b0;

        else    q       <= d;

endmodule

 

3.2 优点

异步复位的最大优点是,vendor库里面有异步复位FF,这样datapath就十分干净。不用把reset与数据做逻辑,这样复位路径上就不会有额外的延时,也不会受外部信号的干扰。

异步复位的进位计数器如下:

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;    // async reset

    else if (ld)    {co,q} <= d;    // sync load

    else    {co,q} <= q + 1'b1; // sync increment

endmodule

 

综合后的电路如下:

 

可以看到,reset路径上十分干净,直接由外部pin来控制,不受其他信号影响。

异步复位的另一个优点是电路reset和时钟无关,不管有没有时钟,都可以reset。好处是可以实时复位,也可以加在门控时钟里面。门控时钟是低功耗设计的重要方法。

异步复位不需要加入综合指令,综合工具就能自动识别。

3.3 缺点

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

如下图所示,异步复位信号复位解除时是和时钟信号完全异步的。

这种情况下由两个问题:复位恢复时间(reset recovery) 违例和复位解除(reset removal) 违例发生在不同的触发器的不同时钟周期

 

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

 

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

换句话来说,如果你想让某个时钟沿起作用,那么你就应该在“恢复时间”之前是异步控制信号变无效,如果你想让某个时钟沿不起作用,那么你就应该在“解除时间”过后使控制信号变无效。如果你的控制信号在这两种情况之间,那么就没法确定时钟沿是否起作用或不起作用了,也就是说可能会造成寄存器处于不确定的状态。而这些情况是应该避免的。所以恢复时间和去除时间是应该遵守的。

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

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

既然同步复位和异步复位都有问题,那么到底应该怎么复位呢?能不能即有同步复位和异步的优点,而没有同步复位和异步复位的缺点呢?小孩子才做选择,成年人就是我都要。所以解决方案就是:异步复位同步释放。

第4章 异步复位同步释放

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

规则:每个异步复位的电路,必须包含一个复位同步器。代码和电路如下:

 

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

 

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

当异步复位信号撤销时,用来同步的第二个寄存器输入的数据仍然是0,因此第二个寄存器是不会出现亚稳态的。第一个寄存器虽然可能出现亚稳态,即使其出现了亚稳态,这个亚稳态还需要通过第二个寄存器,这时第二个寄存器就起到了打拍的作用。也就是说,第二级的亚稳态只可能是上一级寄存器传播过来的,但是这个亚稳态经过第二级寄存器后,其大概率已经稳定下来了,就算稳定下来不为1,也就相当与复位信号多持续了一个周期而已。因此我们可以看出,使用异步复位同步释放时,异步复位撤销后是需要额外等待一个时钟周期的,否则会激励可能会被复位信号覆盖掉。

 

第5章 异步复位的抖动或毛刺

由于异步复位和时钟无关,任何一个毛刺都可以引起复位。这是一个reset源的问题。下面的电路可以过滤毛刺,主要原理是把输入源与上它的延时来消除毛刺。

但是这并不是一个很完美的设计,主要原因是delay单元的实现,因为不同温度不同制程下,delay值可能会不同。

有的库里面包含Delay宏,有的没有;没有的话就需要手动增加delay或者插buffer,同时增加约束让delay不被综合掉。

同时rst_n 输入也必须是一个史密斯触发器pad,进一步消除抖动。

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

参考:Asynchronous & Synchronous Reset Design Techniques - Part Deux

    https://zhuanlan.zhihu.com/p/110866597