一.概述
首先我们要区分同步复位信号和异步复位。
1.异步复位
复位信号和clk无关,是作为敏感参数放在参数列表中的,即作为触发条件使用。寄存器使能了CLR端(FDCE)。但是异步复位在释放时,如果释放时间正好在建立时间和保持时间之内,就会产生亚稳态。
异步复位使用的代码形式:
优点:
(1)和时钟不绑定。
缺点:
(1)复位信号容易受到毛刺的影响。
(2)复位释放时刻恰在亚稳态窗口内时,会导致亚稳态。
(3)关于资源这一点,同步复位会把复位吸收到逻辑资源里面,虽然消耗了逻辑资源,但是可以把触发器放在一个slice里面,反观异步复位,有和没有异步复位的寄存器不能被包装在一个Slice,不同异步复位的寄存器不能被包装在一个Slice。
1.1由异步复位释放产生的亚稳态
复位信号在时钟边沿之间的某个时间被释放。然后,信号传播到各个触发器。在每个触发器中,信号应该在激活时钟边沿的“建立时间”之前被释放。很明显,当时钟速率上升时,可用于分配复位信号释放的时间下降。考虑到复位信号是一个非常高的扇出网络,满足释放时间的要求是比较大的问题。
亚稳态的概率:The good news is that 99.99% of the time, the timing of the reset release really doesn't matter。
2. 同步复位
复位信号和clk有关,只在clk的边沿检测是否复位。复位和时钟有关,寄存器使能了R端(FDRE)。
同步复位使用的代码形式:
同步复位的生成:
The number of flip-flops in the chain determines the minimum duration of the reset pulse issued to the localized network. Eventually, the last flip-flop makes the transition from High to Low, and the localized reset is released synchronously with the clock. Flip-flops being reset can employ a synchronous set (FDS) or synchronous reset (FDR) leading to a fully synchronous design and easy timing specifications and analysis.
同步复位的生成对应代码:
优点:
(1)一般能够确保电路是百分之百同步的。
(2)确保复位只发生在有效时钟沿,可以作为过滤掉毛刺的手段。(有效避免亚稳态)。但如果这些毛刺出现在有效时钟沿附近,那么触发器可能会变为亚稳态。
缺点:
(1)复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位。
(2)由于大多数的厂商目标库内的触发器都只有异步复位端口,采用同步复位的话,就会耗费较多的逻辑资源。(xilinx 都一样)
Note:
大家很多时候都使用异步复位,同步释放的复位形式,注意异步复位,同步释放和概述中所说的同步复位是不一样的,概述中所说的同步复位可以理解为同步复位,同步释放。
异步复位,同步释放的方式即减少了逻辑资源的消耗,又减小了亚稳态产生的概率。
3.异步复位,同步释放
话不多说,代码如下:
异步复位,同步释放的复位的生成:
两个复位信号都是在同一时刻变为0,rst_nr1是用来把rst_n同步到clk时钟的,而rst_nr2是用来减小亚稳态产生的概率,rst_nr2其实就是把复位多延长了一拍。复位释放并不会对第二级触发器产生亚稳态影响。
Ever since the publication of our first resets paper[4], we have received numerous email
messages asking if the reset synchronizer has potential metastability problems on the second
flip-flop when reset is removed. The answer is that the reset synchronizer DOES NOT have reset
metastability problems. The analysis and discussion of related issues follows.
The first flip-flop of the reset synchronizer does have potential metastability problems because
the input is tied high, the output has been asynchronously reset to a 0 and the reset could be
removed within the specified reset recovery time of the flip-flop (the reset may go high too close
to the rising edge of the clock input to the same flip-flop). This is why the second flip-flop is
required.
The second flip-flop of the reset synchronizer is not subject to recovery time metastability
because the input and output of the flip-flop are both low when reset is removed. There is no
logic differential between the input and output of the flip-flop so there is no chance that the
output would oscillate between two different logic values.
摘自Clifford E. Cummings《Asynchronous & Synchronous Reset Design Techniques - Part Deux》
(1)只有当DFF的数据输入端口和数据输出端口,存在值不同的情况下,才会有recovery timing/removal timing问题。
(2)第1个dff的数据输入端口和数据输出端口,在异步复位释放的时刻,是1和0,所以会有竞争冒险,有概率产生亚稳态;
(3)第2个dff的数据输入端口和数据输出端口,在异步复位释放的时刻,是0和0,所以不存在竞争冒险,不会产生亚稳态。
二.有关复位初始化的问题
1.复位模块中有关信号没有全部复位
对于一种不规范的问题,如果在一个always块中不想对所有信号复位,那么就有两种写法,例如图一中不规范的写法,为了方便看,我们把规范的写法也贴了出来,如图二。
图一:不规范写法
图二:规范的写法
这会导致什么问题呢?我们将不规范的规范的进行对比,首先看下RTL原理图:
图三:不规范的代码对应的RTL图
图四:规范的代码对应的RTL图
可以看到不规范的写法会用到前两个寄存器的CE端(时钟使能端),而且用到了2个MUX(2选1),这在综合的时候其实就是对前两个触发器的CLR端接地,即不复位,然后让复位用一个LUT取反接到CE,也就是用一个LUT代替两个2选1MUX的功能。不规范的写法会导致资源增加。
我们再来看看对应的仿真图:
图五:不规范写法对应的仿真图
图六:规范写法对应的仿真图
两种写法对应的仿真是有区别的。
Note:
Xilinx建议一个always块中如果有复位,就必须把所有变量复位。
2.关于直接赋值和复位给初始值的区别
定义reg时直接赋值和复位时赋值是有区别的。
在讲这个以前,我们先谈配置阶段,就说一下什么是FPGA的配置(以7系列FPGA为例),可以参考UG470。
配置是指将特定应用的数据加载到器件内部存储器中的过程,即down或者烧录bit的过程。
整个配置流程:
step1:上电
step2:清除配置存储器。
step3:采样配置模式管脚,M2 M1 M0
step4-7:下载bit流(CRC校验,失败则终止配置)
step8:开始启动序列(状态机有8步)
(1)定义reg时赋初值
定义reg时赋初值即初始化INIT属性。在FPGA配置或重配置时的step4-7会将初始值赋值给有关寄存器。
(2)复位给初始值
在FPGA配置结束,由step8其中产生的DONE信号作为复位芯片的输入,从而产生一个200ms的复位信号(具体时间和复位芯片型号有关),该复位信号引脚再引入FPGA,完成异步复位的操作,这就是用户模式的复位,会将有关寄存器赋值为RTL代码中复位时的值。
值得一提的是,如果没有初始化INIT属性并且没有复位操作,那么默认INIT属性为0(但其实我发现在项目中如果不初始化INIT属性,那么有可能ila查看到的寄存器不为0,有的位为1)。这个值可以在综合的网表属性里面改动。如果既初始化INIT属性并且也有复位操作,这个时候寄存器的值是什么就看处于FPGA的配置阶段还是用户阶段了。
三.复位在工程中的使用
很多FPGA设计中都会涉及到多个时钟,使用器件内部的PLL或者MMCM会使得多个时钟的管理变得更加容易。当多个时钟都是用PLL/MMCM产生时,它们的系统复位信号采用如下设计:
①先用FPGA的外部输入时钟clk将FPGA的输入复位信号rst_n做异步复位、同步释放处理(注意采用反逻辑),然后这个复位信号输入PLL,同时将clk也输入PLL。设计的初衷是在PLL输出有效时钟之前,系统的其他部分都保持复位状态。
②PLL的输出locked信号在PLL有效输出前一直时低电平,PLL输出稳定有效之后才会拉高该信号,所以这里就把前面提到的FPGA外部输入复位信号rst_n和这个locked信号相与作为整个系统的复位信号。
③这个复位信号也需要让合适的PLL输出时钟异步复位、同步释放处理一下。也就是说,为了达到可靠稳定的复位信号,该设计中对复位信号进行了两次处理,分别是在PLL输出前和PLL输出后。
对应代码:
图一:工程中使用全局复位对应的代码
图二:全局复位的顶层模块图
四.XILINX推荐的复位使用建议
(1)我们知道BRAM和DSP内部都有一些可用的寄存器资源,比如BRAM的输出寄存器,DSP的流水线寄存器,但这些寄存器只具备同步复位或者置位的功能,举个BRAM的例子,如果你在定制IP核界面没有选输出寄存器选项,而你自己又定义了输出寄存器,这个时候vivado会把你定义的寄存器用BRAM中的输出寄存器来实现,但是如果你定义的寄存器用的是异步复位,那么此推断将不成立。会用Slice中的触发器资源实现,降低了器件资源的利用率。
(2)对于BRAM, SRL(移位寄存器)的输入端口,不建议用异步复位去驱动,这样可能会导致块中的数据损坏。
(3) 对于xilinx,无论是同步复位还是异步复位,复位信号都是高有效,如果采用低复位,还需要增加一个反相器。
(4) 赛灵思强烈建议您对所有同步元件进行相应的初始化。寄存器初始化完全可由所有主要的器件综合工具进行推断。这样可消除单纯为初始化而添加复位的需求,并且使RTL代码与功能仿真中实现的设计更紧密匹配,因为所有同步元件配置后都会从器件中的已知值启动。
(5)减少了其他连接的自由。可能降低系统性能,可能需要更高的设备速度等级。增加布线时间布局时间。占用设备逻辑资源。几乎肯定会影响设计的大小和性能。
总结:在使用复位信号时,考虑这个寄存器需不需要在运行过程中进行复位,如果只需要上电后复位一次,那只需在定义时写上初值即可,无需使用其他复位信号,但是如果是有反馈的电路需要加上复位(状态机),在Xilinx的FPGA中尽量使用高有效的复位信号,在使用复位时需采用异步复位同步释放或者同步复位的方式,且一个always块中的所有寄存器应被复位,避免使用异步复位。