作者:NingHeChuan
Get Smart About Reset: Think Local, Not Global。
对于复位信号的处理,为了方便我们习惯上采用全局复位,博主在很长一段时间内都是将复位信号作为一个I/O口,通过拨码开关硬件复位。后来也看了一些书籍,采用异步复位同步释放,对自己设计的改进。
不过自从我研读了Xilinx的White Paper后,让我对复位有了更新的认识。
One of the commandments of digital design states,"Thou shalt have a master reset for all flip-flops so that the test engineer will love you, and your simulations will not remain undefined for time eternal."
这句是用来装逼的。使用全局复位有利于我们仿真,所有的寄存器都是有初始值的,也可以在任意时刻让你的寄存器恢复初值,所以验证工程师很喜欢这样的设计,但是Xilinx建议的是尽量避免使用全局复位,这是为什么呢。
全局复位并不是好的处理方式
我们习惯上通常使用的复位有三种,
硬件开关:复位信号接一个拨码开关。
电源芯片:上电时候电源芯片产生,可以长时间维持,直到稳定。
控制芯片:控制芯片产生复位脉冲。
这些复位信号和FPGA内部信号的变化比起来是比较慢的。复位按钮最快也会到达毫秒级别,而FPGA内部信号都是纳秒级别的变化。全局复位的周期远大于系统时钟的周期,是完全可以保证所有的触发器被成功复位的。
但随着系统的频率越来越快,全局复位信号的释放形成一个高扇出的网络。
Fan-out即扇出,模块直接调用的下级模块的个数,如果这个数值过大的话,在FPGA直接表现为net delay较大,不利于时序收敛。因此,在写代码时应尽量避免高扇出的情况。
如图,全局复位的释放需要传输到不同的触发器。每一个触发器需要被释放复位,但是随着时钟频率的提高,加上复位路径网络的延迟,而且全局复位还是一个高扇出的网络,所以这对系统的时序是一个大挑战。
通常情况下,复位信号的异步释放,没有办法保证所有的触发器都能在同一时间内释放。触发器在A时刻接收到复位信号释放是最稳定的,在下一个时钟沿来临被激活,但是如果在C时刻接收到复位信号释放无法被激活,在B时刻收到复位信号释放,则会引起亚稳态。
随着系统时钟频率的提高,并不是所有的触发器都能在同一个时刻从复位状态被释放。
复位真的有那么重要吗?
白皮书上又说了,好的消息是99.9%的情况下,全局复位的异步释放并不会出现问题。所以大多数电路都可以正常工作。但是,如果你有了第一次就不能工作的电路,那你就是遇到那0.01%的情况,很不幸你的复位信号被在错误的时刻重置。(哈哈,皮)
在一些情况下,复位释放的时间并不重要。
当你的数据采用流水线操作的时候,复位释放的时间并不重要,因为不管你流水线后面的触发器复位释放后是否出错,只需要一些周期后,整个流水线就又会正常工作了。白皮书上还说,这样的复位也是没有意义的。
但是有一些情况下,复位的释放后是很重要的。
比如独热码状态机。如果表示独热码状态的第一个触发器比第二个触发器早释放了一个时钟周期,那状态机的状态机会跳转到一个无效的状态。如果所有的表示独热码的寄存器无法在同一个周期内被释放,那状态机肯定会跳转到一个无效的状态。还有一些例子,请读者自己看白皮书。
解决99.99%的情况
其实当Xilinx FPGA配置或重新配置时,所有的单元都会被初始化。白皮书称为master reset,因为这可比你复位一些D触发器要强得多,它甚至初始化了片内RAM。
Xilinx的器件也有嵌入处理的系列,软核或硬核。在程序执行第一条指令前,程序和数据区域已经定义好了。有了上电复位,还用专门消耗逻辑资源去复位触发器是没有意义的。
解决0.01%的方法
当然,白皮书也给出了处理复位的建议和方法。
Think Local, Not Global。异步复位,同步释放的方法。用内部定义复位信号的方法来复位触发器,而不是全都直接使用全局复位信号。当进行复位操作时,所有的触发器被预设为1。如上图,移位寄存器的最后一个触发器去操作模块内部定义的复位网络。当复位信号释放时,移位寄存器经过移位,当最后一个触发器由高电平变为低电平时,对本地的复位网络进行复位操作。也就是异步复位,同步释放。
复位的消耗的资源比你想象的要多
复位网络占用大量布线资源。
提高了布局布线时间。
使用器件的逻辑资源。
会使你的设计变得更大。
占用更多的逻辑资源肯定会影响你的性能。
具体请参阅白皮书。
总结
并不是所有部分的设计都需要复位,所以设计者在设计过程中应该准确判断需要被复位的部分,从而采用异步复位、同步释放的方法进行对复位的严格处理。
当我们在设计每一个部分的时候,都要内心问问自己,这个bit需要被复位吗?
那么怎样处理Xilinx FPGA中的复位呢?Xilinx的工程师也给出了解释和方法。
https://www.eetimes.com/document.asp?doc_id=1278998
http://xilinx.eetrend.com/d6-xilinx/article/2013-07/4343.html
简单总结就是,Xilinx的FPGA 应该尽量避免全局复位,有些部分的设计都可以不用复位,必需要复位的设计而采用 同步 高复位。
代码如下。设计中需要复位的部分,使用产生的sys_rst信号进行同步复位,而且是同步 高复位。再次贴出下图。
module Sys_Rst(
input clk,
input rst,
output sys_rst
);
reg rst_r0;
reg rst_r1;
always @(posedge clk or posedge rst)begin
if(rst)begin
rst_r0 <= 1'b1;
rst_r1 <= 1'b1;
end
else begin
rst_r0 <= 1'b0;
rst_r1 <= rst_r0;
end
end
assign sys_rst = rst_r1;
endmodule