zoukankan      html  css  js  c++  java
  • (原创)同步复位与异步复位

    一、同步复位与异步复位

    1、同步复位与异步复位含义:

    同步复位:顾名思义,同步复位就是指复位信号只有在时钟上升沿到来时,才能有效。否则,无法完成对系统的复位工作。用Verilog描述如下:          

     always @ (posedge clk) begin                

     if (!Rst_n)                  

       ...

     end

    异步复位:它是指无论时钟沿是否到来,只要复位信号有效,就对系统进行复位。用Verilog描述如下:

    always @ (posedge clk or negedge Rst_n) begin

      if (!Rst_n)                

        ...                 

    end

    2、同步复位与异步复位优缺点:

    1、总的来说,同步复位的优点大概有3条:

       a、有利于仿真器的仿真。

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

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

       他的缺点也有不少,主要有以下几条:

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

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

          多的逻辑资源。

    2、对于异步复位来说,他的优点也有三条,都是相对应的       

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

       b、设计相对简单,受时序影响较小。  

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

       缺点:

       a、在复位信号释放(release)的时候容易出现问题。具体就是说:倘若复位释放时恰恰在时钟有效沿附近,就很容易使寄存器输出出现亚稳态,从而导致亚稳态。

       b、复位信号容易受到毛刺的影响。

    3、总结:

        所以说,一般都推荐使用异步复位,同步释放的方式,而且复位信号低电平有效。这样就可以两全其美了。

    ----------------------------------------------------------------------------------------------------------------------------------------------------

     

    二、异步复位,同步释放:推荐的复位方式

     

    异步复位,同步释放:很好的克服了异步复位的缺点(因为异步复位的问题主要出现在复位信号释放的时候,具体原因可见上文)。其实做起来也并不难,我推荐一种我经常使用的方式吧:那就是在异步复位键后加上一个所谓的“reset synchronizer”,这样就可以使异步复位信号同步化,然后,再用经过处理的复位信号去作用系统,就可以保证比较稳定了。reset sychronizer的Verilog代码如下:

    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

       大家可以看到,这就是一个dff,异步复位信号直接接在它的异步复位端口上(低电平有效),然后数据输入端rff1一直为高电平‘1’。倘若异步复位信号有效的话,触发

    器就会复位,输出为低,从而复位后继系统。但是,又由于这属于时钟沿触发,当复位信号释放时,触发器的输出要延迟一个时钟周期才能恢复成‘1’,因此使得复位信号的

    释放与时钟沿同步化。  

    此外,还有一种方法更为直接,就是直接在异步复位信号后加一个D触发器,然后用D触发器的输出作为后级系统的复位信号,也能达到相同的效果。如下:

    module Reset_Synchronizer(output reg rst_n,  input  clk, asyncrst_n);  

    reg rst_n_p;

    always @ (posedge clk,negedge asyncrst_n) begin    

      if (!asyncrst_n) 

        rst_n_p<=1'b0;

      else

        rst_n_p<=rst_n_p;

    end

    always @ (posedge clk) begin    

      if (!asyncrst_n) 

        rst_n_p<=1'b0;

      else

        rst_n <= rst_n_p;

    end

    endendmodule

     

    ----------------------------------------------------------------------------------------------------------------------------------------------------

     

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

     

    这是一个很实际的问题,因为在较大型的系统中,一个时钟驱动信号显然不能满足要求,一定会根据系统的要求用多个同源时钟(当然也可以是非同源了)去驱动系统的不同

    部分。那么在这样的多时钟系统中,复位键怎么设置?它的稳定与否直接关系到了整个系统的稳定性,因此要格外注意(在我看来,复位信号在同步时序系统中的地位和时钟

    信号一样重要)。下面就说一下具体的处理方法,当然所遵循的原则就仍应该是上文的“异步复位,同步释放”:

    1.non-coordinated reset removal:

    顾名思义,就是同一个系统中的多个同源时钟域的复位信号,由彼此独立的“reset synchronizer”驱动。当异步复位信号有效时,各时钟域同时复位,但是复位释放的时间

    由各自的驱动时钟决定,也是就说:时钟快的先释放,时钟慢的后释放,但是各复位信号之间没有先后关系。

     

    2.sequence coordinated reset 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(output reg 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,output SysRst1M_n,SysRst2M_n,SysRst11M_n);  

    Reset_Synchronizer Rst1M(.clk(Clk1M),.asyncrst_n(SysRst_n),.rst_n(SysRst1M_n));  

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

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

    endmodule

    作者:tdyizhen1314

            (现从事LED行业,专注于户外大型LED显示屏控制系统的研发,希望与大家一起交流,共同进步)

    邮箱: 495567585@qq.com  

            td.logic@hotmail.com

  • 相关阅读:
    mac-常用命令
    react-redux-数据流
    ##通讯录阶段重要代码
    ##DAY15——UICollectionView
    ##DAY14——StoryBoard
    通讯录——单例
    通讯录——选择图片
    ##DAY13——可视化编程之XIB
    ##DAY12 UITableViewCell自定义
    ##DAY10 UITableView基础
  • 原文地址:https://www.cnblogs.com/tdyizhen1314/p/2628883.html
Copyright © 2011-2022 走看看