1. 同步复位和异步复位的写法:
//====== 同步复位 =======
always @(posedge clk)
if(rst)
..........
else if(....)
//====== 异步复位 =======
always @(posedge clk or posedge rst)
if(rst)
.........
else if(......)
2. 应该选哪个?
不清楚是什么原因,绝大部分初学者写的是异步复位。
关于这个问题,《深入浅出玩转FPGA》这本书有比较详细的描述,说得很对。
我不清楚Altera最新的FPGA怎么样,不过在以前的时候,Altera的FPGA内部是没有同步复位的,只有异步复位。所以,Altera强烈推荐异步复位也不足为奇了。我想Altera公司的软件和硬件应该做了一些特殊的处理,以防止我们下面讨论的亚稳态问题。
Xilinx的器件的FF,既可以异步复位,也可以同步复位,不过Xilinx公司推荐同步复位。
这里强烈推荐同步复位。
3. 为什么?
在异步复位的情况下,复位信号与时钟信号的相位不能确定,会造成亚稳态。
说简单点,寄存器是在时钟的上升沿变化的,这就要求输入寄存器的信号在时钟沿之后必须稳定一段时间,否则时钟沿也在变,输入数据也在变,就不清楚到底输出会变成什么了。
复位信号也会造成一连串信号的变化,因为复位信号的不确定,所以会造成这个问题。
Altera的FPGA应该在内部做了点什么以防止这个问题。据说,还是会偶尔发生这样的事情。
发生这样的问题的时候,情况是非常古怪的,你再Reset一次就好了。
4. 推荐的做法
推荐的做法,并不是直接使用Reset,而是异步复位-同步释放。
这种电路比较复杂,实际情况中有简化。
如果你的系统时钟是连续的话,你可以使用将Reset信号打两拍,然后上BUFG的方式。
你如果这样做了,Xilinx的工具会去分析Reset信号的时序,从而防止亚稳态的产生;你如果使用异步复位,工具是没法分析的!!
华为/中兴这样的公司,因为设计很大,加上写代码的人风格不统一,所以他们实际是在顶层里面专门建立一个复位模块,然后把异步复位时序化,这个就比较复杂了。但是总的来说,是同步的,所以不管你的子模块是写的异步复位还是同步复位,全部都变成同步的。 |