FPGA——复位设计

复位设计

一、异步复位与同步复位

          FPGA设计中常见的复位方式即异步复位与同步复位。在没有关注亚稳态之前,很多人也是多也是对这个不太在意,只有在遇到了亚稳态的危害之后才会关注异步复位和同步复位的区别。在没有关注这个问题之前,相信很多人都是用的异步复位,所谓异步复位,指的是复位信号和系统时钟信号的触发可以在任何时刻,二者相互独立。

1、异步复位实例

下面给出异步复位的一段代码:

always @(posedge clk or negedge rst_n)
    if(!rst_n) b <= 1'b0;
    else b<= a;

上面的代码进行综合后得到下面的电路图。可以看到FPGA的寄存器都有一个异步的清零端口(CLR),在异步复位的设计中,这个端口一般接低电平的复位信号 rst_n ,即使设计中是高电平复位,实际综合后也会把复位信号反向后接到这个CLR端。

FPGA——复位设计_第1张图片

                                                        异步复位RTL视图 

2、同步复位实例

下面给出同步复位的一段代码:

always @ (posedge clk)
    if(!rst_n) b<= 1'b0;
    else b<= a;

下图是上面代码综合后的RTL视图,和异步复位相比,同步复位没有用到寄存器的CLR端口,综合出来的实际电路只是把复位信号rst_n作为输入逻辑的使能信号,那么这样的同步复位势必会额外增加FPGA内部资源的消耗。

FPGA——复位设计_第2张图片

        那么,异步复位和同步复位到底谁更有优势呢?只能说各有优点。FPGA寄存器有支持异步复位专用的端口,采用异步复位无需增加额外的资源,但是异步复位也存在着隐患。异步时钟域的亚稳态问题同样存在于异步复位信号和系统时钟信号之间。同步复位在时钟的上升沿触发时进行系统是否复位的判断,这降低了亚稳态出现的概率(只是降低,不可能完全消除)。他的缺点在于需要消耗更多的器件资源,无法利用专有的复位端口(CLR)。

       再通过下面两级寄存器的异步复位的例子来说明异步复位存在的隐患。

always @ (posedge clk or negedge rst_n)
    if (!rst_n) b<= 1'b0;
    else b <= a;

always @ (posedge clk or negedge rst_n)
    if (!rst_n) c<= 1'b0;
    else c <= b;

下图是上面的代码综合后的RTL电路图。

FPGA——复位设计_第3张图片

正常情况下,在CLK的上升沿将c更新位b,b更新位a。一旦进入复位,b、c都清零。但是并不能确定复位信号会什么时候结束,如果结束于b_reg0和c_reg_0的建立时间和保持时间之外,那么一切都会正常。但是如果恰恰相反,复位信号rst_n的撤销(由低电平变为高电平)出现在clk锁存数据的建立时间或者保持时间内,此时检测到rst_n的状态就会是一个亚稳态(不确定是0还是1)。这些危害是由于异步信号之间变化的随机性带来的。

二、异步复位、同步释放

前面的分析似乎都让人意识到异步复位与同步复位的危害。下面介绍一种更为可靠的异步复位、同步释放的双缓冲电路。该电路由两个同一时钟沿出发的层叠寄存器组成,该时钟必须和目标寄存器是一个时钟域。

input    clk; //系统时钟信号
input    rst_n;//输入复位信号,低有效
output   rst_nr2;异步复位,同步释放输出

reg    rst_nr1,rst_nr2;

//两级层叠复位信号产生,低电平复位

always @(posedge clk or negedge rst_n)
    if(!rst_n) rst_nr1 <= 1'b0;
    else    rst_nr1 <=1'b1;

always @(posedge clk or begedge rst_n)
    if(rst_n) rst_nr2 <=1'b0;
    else rst_nr2 <= rst_nr1;

c此段代码综合出来的RTL电路图如下:

FPGA——复位设计_第4张图片

如此一来,即解决了同步复位的资源消耗问题,由解决了异步复位的亚稳态问题,其根本思想,也是将异步信号同步化。

使用:直接将 rst_nr2 作为系统的复位信号使用即可。

 

参考文献:《深入浅出玩转FPGA》 

你可能感兴趣的:(FPGA设计)