zoukankan      html  css  js  c++  java
  • FPGA同步复位,异步复位以及异步复位同步释放实例分析

    参考了网上很多关于复位的介绍,很乱,也有错误,下面是自己的一些整理,有误之处,还望大家不吝指出。

     

    同步复位,异步复位以及异步复位同步释放实例分析

    1.1      同步复位

    1.1.1      同步复位介绍

    同步复位就是指复位信号只有在时钟上升沿到来时,才能有效。否则,无法完成对系统的复位工作。

    1.1.2      同步复位优点

    Ø  同步复位的优点大概有3条:

    1)       有利于仿真器的仿真。

    2)       可以使所设计的系统成为100%的同步时序电路,这便大大有利于时序分析,而且综合出来的fmax一般较高。

    3)       因为他只有在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的毛刺。

    1.1.3      同步复位缺点

    Ø  同步复位的缺点:

    1)       复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑,诸如:组合逻辑路径延时,复位延时等因素。

    2)       由于大多数的逻辑器件的目标库内的DFF都只有异步复位端口,所以,倘若采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样就会耗费较多的逻辑资源。

    3)       同步复位依赖于时钟,如果电路中的时钟信号出现问题,无法完成复位

    1.1.4      同步复位实例

    来看一个简单的同步复位的D触发器,Verilog代码如下:

    module d_ff (
            clk,
            rst_n,
            datain,
            dataout
        );
        input        clk;
        input        rst_n;
        input        datain;
        ouput        dataout;
       reg            dataout;
        always @ (posedge clk)
        begin
            if (!rst_n)
               dataout    <= 1'b0;
            else
               dataout    <= datain;
        end
    endmodule

    综合后的RTL图表如下:

     

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

    QuartusII软件自带的综合工具使用选择器实现了同步功能,但是这不是确定的,有的综合工具综合成与门,如下图:

     

     

    1.2        异步复位

    1.2.1      异步复位介绍

     

    异步复位是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。

    1.2.2      异步复位优点

    Ø  异步复位的优点也有三条:

    1)       大多数目标器件库的dff都有异步复位端口,因此采用异步复位可以节省资源。

    2)       设计相对简单。

    3)       异步复位信号识别方便,而且可以很方便的使用FPGA的全局复位端口GSR。

    4)       复位信号不依赖于时钟

    1.2.3      异步复位缺点

    Ø  异步复位的缺点:

    1)     在复位信号释放(release)的时候容易出现问题。具体就是说:复位信号释放的随机性,可能导致时序违规,使电路处于亚稳态,倘若复位释放时恰恰在时钟有效沿附近,就很容易使寄存器输出出现亚稳态,从而导致亚稳态。

    2)  复位信号释放的随机性,可能导致时序违规,使电路处于亚稳态,如下图。

     

     

    1.2.4      异步复位实例

    来看一个简单的异步复位的D触发器,Verilog代码如下:

    moduleprac (
            clk,
            rst_n,
            datain,
            dataout
        );
        input        clk;
        input        rst_n;
        input        datain;
        output        dataout;
       reg            dataout;
        always @ (posedge clk or negedge rst_n)
        begin
            if (!rst_n)
               dataout    <= 1'b0;
            else
               dataout    <= datain;
        end
    endmodule

    综合后的RTL图表如下:

     

    我们可以看到FPGA的寄存器都有一个异步的清零端(CLR),在异步复位的设计中这个端口一般就是接低电平有效的复位信号rst_n。即使说你的设计中是高电平复位,那么实际综合后会把你的复位信号反向后接这个CLR端。

    下面以一个两级寄存器异步复位的例子说明异步复位的缺点:

    always @ (posedge clk or negedge rst_n)

           if(!rst_n)b <= 1'b0;

           elseb <= a;

          

    always @ (posedge clk or negedge rst_n)

           if(!rst_n)c <= 1'b0;

           elsec <= b;    

     

           正常情况下,clk的上升沿c更新为b,b更新为a。一旦进入复位,b,c都清零;但是我们不能确定复位信号rst_n会在什么时候结束。如果结束于b_reg0和c_reg0的{launch edge –stup,launchedge+hold}时间只外,那么一切都会正常。但如果恰恰相反,会出现什么情况呢? rst_n的上升变化出现在了clk上升的建立保持时间上,此时clk检测到的rst_n的状态就会是一个亚稳态(是0是1不确定)。从代码里我们看到如果此时b_reg0和c_reg0认为rst_n为0,那么依然保持复位清零,而如果认为rst_n为1,那么就跳出复位。因为此时的rst_n的不确定性,就可能出现4种情况,即b_reg0和c_reg0都复位或者都跳出复位,再或者一个复位一个跳出复位。那么后者就会造成了系统工作不同步的问题,在这个简单的两级异步复位实例中这种危害表现的并不明显,但是我们试想一个大的工程项目里众多的寄存器出现如此情况又会是如何一番景象呢?

           上面的分析似乎都让人意识到同步复位和异步复位都不可靠,那么如何将两者结合,取长补短呢。

    1.3      异步复位同步释放

    1.3.1      异步复位同步释放介绍(Asynchronous Reset Synchronous Release)

    这种复位方式在文献中还有一种称谓:Synchronized AsynchronousReset,这种称谓应该在国外的技术人员中比较流行。

    所谓异步复位和同步释放,是指复位信号是异步有效的,即复位的发生与clk无关。后半句“同步释放”是指复位信号的撤除(释放)则与clk相关,即同步的。

    1.3.2      异步复位同步释放实现原理

    如图第一个方框内是异步复位和同步释放电路。有两个D触发器构成。第一级D触发器的输入时VCC,第二级触发器输出是可以异步复位,同步释放后的复位信号。

    异步复位:显而易见,rst_async_n异步复位后,rst_sync_n将拉低,即实现异步复位。

    同步释放:这个是关键,看如何实现同步释放,即当复位信号rst_async_n撤除时,由于双缓冲电路的作用,rst_sync_n复位信号不会随着rst_async_n的撤除而撤除。

    假设rst_async_n撤除时发生在clk上升沿,如果不加此电路则可能发生亚稳态事件,但是加上此电路以后,假设第一级D触发器clk上升沿时rst_async_n正好撤除,则D触发器1输出高电平“1”,此时第二级触发器也会更新输出,但是输出值为前一级触发器clk来之前时的Q1输出状态。显然Q1之前为低电平,顾第二级触发器输出保持复位低电平,直到下一个clk来之后,才随着变为高电平。即同步释放。

     

    module reset_gen( 
    output rst_sync_n, 
    input clk, rst_async_n);

    reg rst_s1, rst_s2;
    wire rst_sync_n ;
    always @ (posedge clk, posedge rst_async_n)

    if (rst_async_n) begin 
    rst_s1 <= 1'b0;
    rst_s2 <= 1'b0;
    end
    else begin
    rst_s1 <= 1'b1;
    rst_s2 <= rst_s1;
    end

    assign rst_sync_n = rst_s2; 
    endmodule

    1.3.3      异步复位同步释放实例

    1)       实例1

    Verilog代码如下:

    moduleprac (
            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)
        begin
            if (!rst_n)
                begin
                   reg1    <= 1'b0;
                   reg2    <= 1'b0;
                end
            else
                begin
                   reg1    <= dataa;
                   reg2    <= datab;
                end
        end
    endmodule

    综合后的RTL图表如下:

     

     

    2)       实例2

    Verilog代码如下:

    module Reset_Synchronizer(outputreg rst_n, input clk, asyncrst_n);

    reg rff1;

    always @ (posedge clk ,negedge asyncrst_n) begin

    if (!asyncrst_n)

    {rst_n,rff1} <= 2'b0;

    else

          {rst_n,rff1}<= {rff1,1'b1};

    end

    endmodule

    大家可以看到,这就是一个dff,异步复位信号直接接在它的异步复位端口上(低电平有效),然后数据输入端rff1一直为高电平‘1’。倘若异步复位信号有效的话,触发器就会复位,输出为低,从而复位后继系统。但是,又由于这属于时钟沿触发,当复位信号释放时,触发器的输出要延迟一个时钟周期才能恢复成‘1’,因此使得复位信号的释放与时钟沿同步化。

    3)       误区

    网上也有很多人把下面的方法作为异步复位、同步释放,实际上是错误的:

    always @ (posedgeclk)

           rst_nr <= rst_n;             //现将异步复位信号用同步时钟打一拍

     

    always @ (posedgeclk or negedge rst_nr)

           if(!rst_nr) b <= 1'b0;

           else b <= a;

          

    always @ (posedgeclk or negedge rst_nr)

           if(!rst_nr) c <= 1'b0;

           else c <= b;    

    这种方法是将异步复位转化为同步复位,释放也是同步的。实质上,就是同步复位、同步释放。

    1.4      多时钟系统中复位的处理方法

    这是一个很实际的问题,因为在较大型的系统中,一个时钟驱动信号显然不能满足要求,一定会根据系统的要求用多个同源时钟(当然也可以是非同源了)去驱动系统的不同部分。那么在这样的多时钟系统中,复位键怎么设置?它的稳定与否直接关系到了整个系统的稳定性,因此要格外注意(在我看来,复位信号在同步时序系统中的地位和时钟信号一样重要)。下面就说一下具体的处理方法,当然所遵循的原则就仍应该是上文的“异步复位,同步释放”:

    1.non-coordinated resetremoval:顾名思义,就是同一个系统中的多个同源时钟域的复位信号,由彼此独立的“reset synchronizer”驱动。当异步复位信号有效时,各时钟域同时复位,但是复位释放的时间由各自的驱动时钟决定,也是就说:时钟快的先释放,时钟慢的后释放,但是各复位信号之间没有先后关系。

    2.sequence coordinatedreset removal:这是相对于上述方式来说的,也就是说各时钟域的复位信号彼此相关,各个部分系统虽然也同时复位,但是却分级释放。而分级的顺序可由各个“reset synchronizer”的级联方式决定。可以先复位前级,再复位后级,也可以反过来。反正方式很灵活,需要根据实际需要而定。

    用程序表示如下:

     

    例子:三级复位系统,系统中的时钟分别为1M,2M,11M:

    第一级Reset_Sychronizer程序:

    module Reset_Synchronizer(output reg rst_n,

    input  clk, asyncrst_n);

    reg rff1;

    always @ (posedge clk ,negedge asyncrst_n)

    begin

        if (!asyncrst_n)

    {rst_n,rff1} <= 2'b0;

          else

    {rst_n,rff1} <={rff1,1'b1};

    end

    endmodule

     

    第2,3级的Reset_Sychronizer程序:

    module Reset_Synchronizer2 (outputreg rst_n,

    input  clk, asyncrst_n,d);

    reg rff1;

     

    always @ (posedge clk ,negedge asyncrst_n)

    begin

    if (!asyncrst_n)

    {rst_n,rff1} <= 2'b0;

    else

    {rst_n,rff1} <={rff1,d};

    end

    endmodule

    顶层模块的源程序:

    include"Reset_Synchronizer.v"

    include"Reset_Synchronizer2.v"

    module AsynRstTree_Trans (input  Clk1M,Clk2M,Clk11M,SysRst_n,

                                             outputSysRst1M_n,SysRst2M_n,SysRst11M_n

    );

    Reset_SynchronizerRst1M(.clk(Clk1M),. asyncrst_n(SysRst_n),.rst_n(SysRst1M_n));

     

    Reset_Synchronizer2Rst2M(.clk(Clk2M),.d(SysRst1M_n),.asyncrst_n(SysRst_n),.rst_n(SysRst2M_n));

     

    Reset_Synchronizer2Rst11M(.clk(Clk11M),.d(SysRst2M_n),.asyncrst_n(SysRst_n),.rst_n(SysRst11M_n));

     

    endmodule

     

  • 相关阅读:
    postman的几个问题
    服了这个所谓北大青鸟官方学员社区论坛
    Gatling实战(三)
    Gatling实战(二)
    Gatling实战(一)
    httplib和urllib2常用方法
    jmeter的新增函数说明
    windows版jmeter的body data如何用 作为“换行”
    linux下oracle服务启动关闭
    linux下ORACLE监听日志的正确删除步骤
  • 原文地址:https://www.cnblogs.com/youngforever/p/3104709.html
Copyright © 2011-2022 走看看