stephenkung

FPGA异步复位同步释放解析

0
阅读(6264)
FPGA开发中,一种最常用的复位技术就是“异步复位同步释放”,这个技术比较难以理解,很多资料对其说得并不透彻,没有讲到本质,但是它又很重要,所以对它必须理解,这里给出我的看法。
讲到这个之前,我们要先熟悉recovery time和removal time的概念。如下图:

对于异步复位而言,假设是低电平有效,那么很容易碰到的情况就是我在释放该信号的时候,发现它的释放沿居然跟时钟跳变沿太接近了!这会导致D触发器处于亚稳态。我们知道,上图的reset_n信号是接D触发器的直接复位端的。如果两个跳变沿过于接近,那么D触发器就有可能发现自己该采样了,但是复位信号还没取消呢!采还是不采就不能确定。所以,我们要求reset_n信号释放的时候,必须远离clock上升沿recovery time +removal time这么大的时间区域,其中clock上升沿之前的必须远离的那段时间叫做recovery time,上升沿之后必须远离的那段时间叫做removel time。简单的讲,两者不能同时跳变,或者接近同时跳变

 

为了避免释放的时候造成亚稳态问题,提出了“异步复位,同步释放”的解决办法。所谓异步复位,就是复位信号可以直接不受时钟信号影响,在任意时刻只要是低电平就能复位(假如约定低电平复位),也就是说,复位信号不需要和时钟同步。而同步释放就很有意思了,它的意思是让复位信号取消的时候,必须跟时钟信号同步,也就是说正好跟时钟同沿。这就奇怪了!因为之前我们刚讲,要避免复位释放沿跟时钟沿同步。这里为什么就可以了呢?

我们先看一个异步复位同步释放的代码,Verilog代码如下:

module prac (

        clk,
        reset_n,
        dataa,
        datab,
        outa,
        outb
    );
    input        clk;
    input        reset_n;
    input        dataa;
    input        datab;
    output        outa;
    output        outb;
    reg            reg1;
    reg            reg2;
    reg            reg3;
    reg            reg4;
    assign    outa    = reg1;
    assign    outb    = reg2;
    assign    rst_n    = reg4;
    always @ (posedge clk or negedge reset_n)      //“异步复位同步释放”的复位模块
    begin
        if (!reset_n)
            begin
                reg3    <= 1'b0;
                reg4    <= 1'b0;
            end
        else
            begin
                reg3    <= 1'b1;
                reg4    <= reg3;
            end
    end


    always @ (posedge clk or negedge rst_n)   //功能模块,注意rst_n是沿变驱动。
    begin
        if (!rst_n)
            begin
                reg1    <= 1'b0;
                reg2    <= 1'b0;
            end
        else
            begin
                reg1    <= dataa;
                reg2    <= datab;
            end
    end
endmodule

综合后的RTL图表如下:


ScreenShot004

下面对上面的图进行解说。我们看到,真正驱动reg2和reg1等功能模块工作的复位信号其实是rst_n信号,而rst_n信号则是异步复位端reset_n经过reg3和reg4两级寄器之后的产生的新的复位信号。其中reset_n为异步复位,而rst_n则是经过同步释放得到的新的复位驱动信号。rst_n将与时钟沿同步,所以它本质上是同步复位信号。

 

这样,通过reg3和reg4两级锁存,就把reset_n从一个异步复位端口,加工成了一个输出同步复位rst_n的模块。

 

reg3的输入端永远接“1”,所以某时刻,正常情况下,reg3和reg4都输出“1”。假设在某时刻,reset_n信号被拉为低电平,这将导致reg3直接复位,输出为“0”,而此时reg4需要下一个时钟周期才会变成“0”;而且reg4是在时钟沿作用下采样,所以reg4从“1”跳变为“0”的时刻一定跟时钟沿是同步的,这就得到了一个同步释放的结果。而reg2和reg1都是时钟沿驱动,所以这种同步释放的rst_n将可以有效的驱动后面的复位,不会造成亚稳态效应

 

我们看到,其实最后我们也就是实现了同步复位的功能,那我们为什么不直接使用同步复位来写呢?原因在于,很多模块本身不具有同步复位端口,但是基本都支持异步复位,所以使用异步复位更加节省资源,如果一定要实现同步复位,那么会生成更多组合逻辑。比如图中所有寄存器的CLR端口其实就是异步复位端口。而通过上面多加了reg4触发,我们让CLR这个异步复位的端口实现了同步复位的功能,而同步复位信号效果更好,对毛刺抑制能力强,这就是“异步复位同步释放”的意义。所以让异步复位端口实现同步复位功能,这才是“异步复位同步释放的本质”