verilog异步复位位同步释放为什么能消除亚稳态

博客访问: 475805
博文数量: 112
博客积分: 3532
博客等级: 中校
技术积分: 1313
注册时间:
IT168企业级官微
微信号:IT168qiye
系统架构师大会
微信号:SACC2013
分类: 嵌入式
&同步复位sync异步复位async特点复位信号只有在时钟上升沿到来时才能有效。无论时钟沿是否到来,只要复位信号有效,就进行复位。Verilog描述always@(posedge CLK)always@(posedge CLK , negedge Rst_n)优点1)利于仿真器仿真。2)因为只有在时钟有效电平到来时才有效,所以可以滤除高于时钟频率的毛刺。3)可以使所设计的系统成为100%的同步时序电路,有利于时序分析。1)设计相对简单。2)因为大多数目标器件库的dff都有异步复位端口,因此采用异步复位可以节省资源。3)异步复位信号识别方便,而且可以很方便的使用FPGA的全局复位端口GSR。缺点1) 复位信号的有效时长必须大于时钟周期,才能真正被系统识别并完成复位任务。同时还要考虑,诸如:clk skew,组合逻辑路径延时,复位延时等因素。2) 由于大多数的逻辑器件的目标库内的DFF都只有异步复位端口,所以,倘若采用同步复位的话,综合器就会在寄存器的数据输入端口插入组合逻辑,这样就会耗费较多的逻辑资源。1)复位信号容易受到毛刺的影响。2)在复位信号释放(release)的时候容易出现问题。具体就是说:若复位释放刚好在时钟有效沿附近时,很容易使寄存器输出出现亚稳态,从而导致亚稳态。总结推荐使用异步复位,同步释放的方式,而且复位信号低电平有效。&2:推荐的复位方式所谓推荐的复位方式就是上文中所说的:“异步复位,同步释放”。这就结合了双方面的优点,很好的克服了异步复位的缺点(因为异步复位的问题主要出现在复位信号释放的时候,具体原因可见上文)。其实做起来也并不难,我推荐一种我经常使用的方式吧:那就是在异步复位键后加上一个所谓的“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};endendmodule大家可以看到,这就是一个dff,异步复位信号直接接在它的异步复位端口上(低电平有效),然后数据输入端rff1一直为高电平‘1’。倘若异步复位信号有效的话,触发器就会复位,输出为低,从而复位后继系统。但是,又由于这属于时钟沿触发,当复位信号释放时,触发器的输出要延迟一个时钟周期才能恢复成‘1’,因此使得复位信号的释放与时钟沿同步化。此外,还有一种方法更为直接,就是直接在异步复位信号后加一个D触发器,然后用D触发器的输出作为后级系统的复位信号,也能达到相同的效果。这里就不多说了。&3:多时钟系统中复位的处理方法这是一个很实际的问题,因为在较大型的系统中,一个时钟驱动信号显然不能满足要求,一定会根据系统的要求用多个同源时钟(当然也可以是非同源了)去驱动系统的不同部分。那么在这样的多时钟系统中,复位键怎么设置?它的稳定与否直接关系到了整个系统的稳定性,因此要格外注意(在我看来,复位信号在同步时序系统中的地位和时钟信号一样重要)。下面就说一下具体的处理方法,当然所遵循的原则就仍应该是上文的“异步复位,同步释放”: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};endendmodule&第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};endendmodule顶层模块的源程序: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_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
阅读(6606) | 评论(0) | 转发(1) |
相关热门文章
给主人留下些什么吧!~~
请登录后评论。代码很简单,就是一个计时器,设置了一个8位的定时计时器counter(也可以是更多的位),复位的时候counter清0,复位释放时counter在CLK作用下开始自加1。
ssssalways @(posedge clk or negedge rst_n)
&& if(!rst_n) counter&= 8'b0;
&& else begin
&&&&&& counter&=counter+1'b1;
&&&&&& rst_sync&=
如果正常复位的话,counter[7:0]的8个触发器都会在复位释放后从0开始计数,但如果异步复位导致寄存器处于亚稳态,触发器的输出端Q7:Q0就处于一个不确定的状态,可能有的是0,有的是1,就像下图一样,这样子当下一个CLK到来的时候,counter[7:0]就不是从0开始自加1,而是有可能从0-255的任意一个数开始加1。
显而易见,如果后级模块需要靠这个counter精确定时序,肯定会产生错误。
如果只有一个触发器,其输出端Q做下一级模块的启动标志位,复位时Q=0,在复位释放时处于亚稳态,本应该输出还为0,但如果错误的输出1,导致下一级模块启动,再接着会导致后级出现更多的问题。&
?复位亚稳态的解决
复位亚稳态的问题看来都是因为触发器输出端处于不确定状态导致的,而解决思路就是使其复位释放时输出处于确定状态,其实就是使用异步复位同步释放的办法。
从网上的设计来看主要有两种电路:
input&&&&&&&& CLK,RSTn;
output&&&&&&& rstn_r2;
reg&&&&&&&&&& rstn_r1,rstn_r2;
always@(posedge CLK or negedge RSTn)
&&& if(!RSTn) rstn_r1&=1'b0;
&&& else rstn_r1&=1'b1;
always@(posedge CLK or negedge RSTn)
&&& if(!RSTn) rstn_r2&=1'b0;
&&& else rstn_r2&=rstn_r1;
其综合出来的RTL视图为:
上图使用rstn_r2作为后级的复位输出,为什么它能实现正常复位呢,我开始时百思不得其解,因为我犯了两个错误:
1错误地认为对于单级的异步复位,即使在RST释放时处于当前时钟的上升沿而导致触发器输出亚稳态,比如触发器要输出1但是因为亚稳态输出0,但是到下一个CLK不就输出1了吗?
&&这种分析没有考虑周全,如果一个边沿检测寄存器 (触发器)作为下一个的标志位,要求在复位时为0,复位释放后如果边沿检测输入没有下降沿则要求输出为0,只有在有下降沿输入时其触发器输出才为1,而如果触发器因为亚稳态在复位释放时就输出为1,则会错误置边沿检测标志位为1,导致后级认为发生了边沿下降。
2错误地把理想状态和实际状态混到一起了,我认为rstn_r2复位释放上升到1的期间正好在CLK上升沿,那么这个给后一级的复位也会处于亚稳态。
&&其实不是这样的,rstn_r2复位释放上升1的期间正好在CLK上升沿是理想状态下的时序,理想状态下这样完全可以正常让后级复位,因为就算是单级的异步复位在理想状态时,如果CLK和RSTn上升沿完全重合也可以正常复位(这是从RTL仿真看出来的),让我们来看看实际状态的时序图。
异步复位信号RSTn在任意时间释放,
假设正好在CL1的上升沿释放,则触发器rstn_r1处于亚稳态,在CLK=1时错误输出为0;
直到CLK2来到后正确检测到RSTn=1才使rstn_r1正确输出1,rstn_r1要比CLK延迟Tco1,此时rstn_r2因为非阻塞赋值还是为0;
CLK3到来时正确检测到rstn_r1为1,所以rstn_r2正确输出为1,rstn_r2要比CLK延迟Tco2,如果理想状态下rstn_r2和CLK是同时上升的,但是在实际状态下触发器输出总比CLK延迟Tco时间,所以这个rstn_r2作为下一级的复位端不会和当前CLK同时上升,因此不会出现亚稳态,下一级的复位释放要到CLK4来到才能释放。
这样就保证了复位释放时触发器处于稳定状态。
?电路2:先把RSTn和时钟同步一下
input&&&&&&&& d,CLK,RSTn;
output&&&&&&&
reg&&&&&&&&&& q,
always@(posedge CLK)
&&& if(!RSTn) rstn&=1'b0;
&&& else rstn&=1'b1;
always@(posedge CLK or negedge rstn)
&&& if(!rstn) q&=1'b0;
&&& else q&=d;
其综合出来的RTL视图如下:
上图首先用触发器把RSTn同步一下,采用触发器输出端rstn作为下一级的复位端,时序图如下;
CLK0时,复位还没结束,RSTn,rstn,q都还处于复位状态;
CLK1时,RSTn复位释放,对于触发器rstn其输入是处于亚稳态,按照错误触发就是rstn输出为0;
则CLK2时RSTn已经稳定,rstn经过Tco1延时后输出正常为1,当然这时候的CLK2已经在上升沿之后不能检测rstn,而rstn作为触发器q的复位端在CLK3到来之前就已经保持稳定,即处于CLK3的Tsu和Th之外;
所以CLK3来到时触发器q能正确复位。
&&& 从上面的两个例子可以看出只要使用同步器把RSTn同步,就可以使RSTn在释放时输出的rstn端落在CLK的Tsu和Th之外,保证CLK采样时处于稳定状态。
旗下网站:
与非门科技(北京)有限公司 All Rights Reserved.
京ICP证:070212号
北京市公安局备案编号: 京ICP备:号本文转自 1. 应用背景 1.1&&&&&&&& 亚稳态发生原因 &&&&& 在FPGA系统中,如果数据传输中不满足触发器的Tsu和Th不满足,或者复位过程中复位信号的释放相对于有效时钟沿的恢复时间(recovery time)不满足,就可能产生亚稳态,此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端在0和1之间处于振荡状态,而不是等于数据输入端D的值。这段时间称为决断时间(resolution time)。经过resolution time之后Q端将稳定到0或1上,但是稳定到0或者1,是随机的,与输入没有必然的关系。
1.2&&&&&&&& 亚稳态发生场合 &&&&& 只要系统中有异步元件,亚稳态就是无法避免的,亚稳态主要发生在异步信号检测、跨时钟域信号传输以及复位电路等常用设计中。
1.3&&&&&&&& 亚稳态危害 &&&&& 由于产生亚稳态后,寄存器Q端输出在稳定下来之前可能是毛刺、振荡、固定的某一电压值。在信号传输中产生亚稳态就会导致与其相连其他数字部件将其作出不同的判断,有的判断到“1”有的判断到“0”,有的也进入了亚稳态,数字部件就会逻辑混乱。在复位电路中产生亚稳态可能会导致复位失败。怎么降低亚稳态发生的概率成了FPGA设计需要重视的一个注意事项。
2. 理论分析 2.1&&&&&&&& 信号传输中的亚稳态 &&&& 在同步系统中,输入信号总是系统时钟同步,能够达到寄存器的时序要求,所以亚稳态不会发生。亚稳态问题通常发生在一些跨时钟域信号传输以及异步信号采集上。
它们发生的原因如下:
(1)在跨时钟域信号传输时,由于源寄存器时钟和目的寄存器时钟相移未知,所以源寄存器数据发出数据,数据可能在任何时间到达异步时钟域的目的寄存器,所以无法保证满足目的寄存器Tsu和Th的要求;
(2)在异步信号采集中,由于异步信号可以在任意时间点到达目的寄存器,所以也无法保证满足目的寄存器Tsu和Th的要求;
当数据在目的寄存器Tsu-Th时间窗口发生变化,也即当数据的建立时间或者保持时间不满足时,就可能发生亚稳态现象。如图3.1所示。
图3.1& 亚稳态产生示意图
&&&& 由图可知,当产生亚稳态后Tco时间后会有Tmet(决断时间)的振荡时间段,当振荡结束回到稳定状态时为“0”或者“1”,这个是随机的。因此,会对后续电路判断造成影响。
2.2&&&&&&&& 复位电路的亚稳态 2.2.1&&& 异步复位电路 在复位电路设计中,复位信号基本都是异步的,常用异步复位电路Verilog描述如下:
always @(posedge clk or negedge rst_n)
&&&&&& if(!rst_n) a &= 1’b0;
&&&&&& else&&&&&&&& a &=
综合出来复位电路模型如图3.2所示:
图3.2& 异步复位电路模型
&&&&& 如图3.3所示,为复位电路复位时序图。如果异步复位信号的撤销时间在Trecovery(恢复时间)和Tremoval(移除时间)之内,那势必造成亚稳态的产生,输出在时钟边沿的Tco后会产生振荡,振荡时间为Tmet(决断时间),最终稳定到“0”或者“1”,就会可能造成复位失败。
图3.3& 异步复位时序
2.2.2&&& 同步复位电路的亚稳态 &&&& 在复位电路中,由于复位信号是异步的,因此,有些设计采用同步复位电路进行复位,并且绝大多数资料对于同步复位电路都认为不会发生亚稳态,其实不然,同步电路也会发生亚稳态,只是几率小于异步复位电路。
如下面verilog代码对同步复位电路的描述。
always @(posedge clk)
&&&&&& if(!rst_n) a &= 1’b0;
&&&&&& else&&&&&&&& a &=
综合出硬件电路如图3.4所示。
图3.4& 同步复位电路
&&&&& 在此,我们不讨论同步复位的消耗资源问题,只讨论同步复位的亚稳态产生情况。
&&&&& 当输入端Din为高电平,而且复位信号的撤销时间在clk的Tsu和Th内时候,亚稳态就随之产生了。如图3.5时序所示,当复位撤销时间在clk的Tsu和Th内,输入数据为“1”,通过和输入数据相与后的数据也在clk的Tsu和Th内,因此,势必会造成类似异步信号采集的亚稳态情况。
图3.5& 同步复位电路时序图
2.3&&&&&&&& 亚稳态产生概率以及串扰概率 &&&&& 在实际的FPGA电路设计中,常常人们想的是怎么减少亚稳态对系统的影响,很少有人考虑怎么才能减少亚稳态发生几率,以及亚稳态串扰的概率问题。
2.3.1&&& 亚稳态发生概率 &&&&& 由上面分析得知,系统亚稳态发生的都是由于clk的Tsu和Th不满足,又或者是复位信号的移除和恢复时间不满足。常用FPGA器件的Tsu+Th约等于1ns,复位移除和恢复时间相加约等于1ns。
&&&&& 当异步信号不是一组数据,或者信号量较少,那就需要对异步信号进行同步处理,例如对一个异步脉冲信号进行采集,只要脉冲信号变化发生在时钟Tsu和Th窗口内,那就很可能会产生亚稳态,亚稳态产生的概率大概为:
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& 概率 = (建立时间 + 保持时间)/ 采集时钟周期&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& (公式3-1)
&&&&& 由公式3-1可以看出,随着clk频率的增加,亚稳态发生的几率是增加的。
&&&&& 例如,为系统采用100M时钟对一个外部信号进行采集,采集时钟周期为10ns,那采集产生亚稳态的概率为:1ns/10ns = 10%
&&&&& 同理采用300M时钟对一个外部信号进行采集,那产生亚稳态的概率为:1ns/3.3ns = 30%
&&&&& 如果采用三相相位差为120°的时钟对一个外部信号进行采集,那产生亚稳态的概率接近90%
&&&& 所以在异步信号采集过程中,要想减少亚稳态发生的概率:
& (1) 降低系统工作时钟,增大系统周期,亚稳态概率就会减小;
& (2) 采用工艺更好的FPGA,也就是Tsu和Th时间较小的FPGA器件;
2.3.2&&& 亚稳态的串扰概率 &&&& 使用异步信号进行使用的时候,好的设计都会对异步信号进行同步处理,同步一般采用多级D触发器级联处理,如图3.6所示,采用三级D触发器对异步信号进行同步处理。
图3.6& 三级寄存器同步
&&&&& 这种模型大部分资料都说的是第一级寄存器产生亚稳态后,第二级寄存器稳定输出概率为90%,第三极寄存器稳定输出的概率为99%,如果亚稳态跟随电路一直传递下去,那就会另自我修护能力较弱的系统直接崩溃。接下来我们分析这种串扰的概率问题。
&&&& 如图3.7所示为一个正常第一级寄存器发生了亚稳态,第二级、第三极寄存器消除亚稳态时序模型。
图3.7 三级寄存器消除亚稳态
&&&& 由上图可以看出,当第一个寄存器发生亚稳态后,经过Tmet的振荡稳定后,第二级寄存器能采集到一个稳定的值。但是为什么第二级寄存器还是可能会产生亚稳态呢?
&&&& 由于振荡时间Tmet是受到很多因素影响的,所以Tmet时间又长有短,所以当Tmet时间长到大于一个采集周期后,那第二级寄存器就会采集到亚稳态。如图3.8所示。
图3.8& 二级寄存器亚稳态
&&&&& 由上图可知,第二级也是一个亚稳态,所以在这种情况下,亚稳态产生了串扰,从第一级寄存器传到了第二级寄存器,同样也可能从第二级寄存器串扰到第三级寄存器。这样会让设计逻辑判断出错,产生亚稳态传输,可能导致系统死机奔溃。
2.3.3&&& 亚稳态振荡时间Tmet &&&&& 亚稳态震荡时间Tmet关系到后级寄存器的采集稳定问题,Tmet影响因素包括:器件的生产工艺、温度、环境以及寄存器采集到亚稳态离稳定态的时刻等。甚至某些特定条件,如干扰、辐射等都会造成Tmet增长。
3. 应用分析 有亚稳态产生,我们就要对亚稳态进行消除,常用对亚稳态消除有三种方式:
(1)&&&&&& 对异步信号进行同步处理;
(2)&&&&&& 采用FIFO对跨时钟域数据通信进行缓冲设计;
(3)&&&&&& 对复位电路采用异步复位、同步释放方式处理。
3.1.1&&& 对异步信号进行同步提取边沿 在异步通信或者跨时钟域通信过程中,最常用的就是对异步信号进行同步提取边沿处理。对一个异步信号进行提取上升沿通常采用程序清单 4.1所示。
程序清单 4.1 双极寄存器提取边沿
input&&&&& sig_
wire&&&&&&& sig_nsyn_p;
reg[1:0]&& sig_nsyn_r;
always @(posedge clk or negedge rst_n)
&&&&&& if(!rst_n) sig_nsyn_r &= 2’d0;
&&&&&& else&&&&&&&& sig_nsyn_r &= { sig_nsyn_r [0], sig_nsyn };
assign&&&& sig_nsyn_p = sig_nsyn_r[0] & ~sig_nsyn_r[1];
&&&&&& 这种边沿提取方式对于一个稳定的系统是不合适的,例如:当第一级寄存器采集到亚稳态,那势必造成sig_nsyn_p输出亚稳态,这样就会对采用sig_nsyn_p的信号进行判断的电路造成影响,甚至判断出错误的值。
根据3.3.1小节的亚稳态产生概率,如果在100M时种下那第一级寄存器产生亚稳态的概率约为10%,随着系统采集频率升高,那产生亚稳态的概率也会随之上升。因此,在进行异步信号跨频提取边沿时候,一般采用多进行一级寄存器消除亚稳态,可能在系统稳定性要求高的情况下,采用更多级寄存器来消除亚稳态,如程序清单 4.2所示,即为采用4级寄存器消除亚稳态,相应的边沿信号产生的时间就晚了两个时钟周期。
程序清单 4.2 多级寄存器提取边沿信号
input&&&&& sig_
wire&&&&&&& sig_nsyn_p;
reg[3:0]&& sig_nsyn_r;
always @(posedge clk or negedge rst_n)
&&&&&& if(!rst_n) sig_nsyn_r &= 2’d0;
&&&&&& else&&&&&&&& sig_nsyn_r &= { sig_nsyn_r [2::0], sig_nsyn };
assign&&&& sig_nsyn_p = sig_nsyn_r[2] & ~sig_nsyn_r[3];
3.1.2&&& FIFO进行异步跨频数据处理 当数据流从一个时钟域到另一个时钟域的时候,绝大多数情况下都采用FIFO来作为中间缓冲,采用双时钟对数据缓冲,就可以避免亚稳态的发生。
3.1.3&&& 异步复位,同步释放 对于复位情况下的亚稳态,常常是由于恢复时间和移除时钟不满足造成的,因此,最常用的处理方式是采用异步复位、同步释放。常用电路模型如所示。采用第二级寄存器输出作为全局复位信号输出。
程序清单 4.3& 异步复位处理
wire&&&&&&& sys_rst_n;
reg [1:0]& rst_r;
always @(posedge clk or negedge rst_n)
&&&&&& if(!rst_n) rst_r &= 2’d0;
&&&&&& else&&&&&&&& rst_r &= {rst_r[0], 1’b1};
assign&&&& sys_rst_n = rst_r[1];
通过上面三种方式处理异步信号、异步数据、以及异步复位可有效的提高系统的稳定性。减少亚稳态的产生。
阅读(...) 评论()关于个人理解的&异步复位,同步释放&
&&&&&&&&其实异步复位的话,优点就是可以直接用EDA工具综合库DFF的异步复位端,相对同步复位来说又简单又省逻辑资源,但其致命缺点就是复位结束也就是释放的时刻恰在时钟上升沿的建立时间和保持时间之间时无法决定现在的复位状态是1还是0,造成亚稳态。
&&&&&&&&&试想下,如果这样的复位信号应用在一个大的系统中,复位信号路径到每一个模块乃至到每一个寄存器的偏斜都会不同,如果恰在时钟上升沿时刻附近必然引起诸多问题。
&&&&&&&&因此最好全局复位信号送出之前做一个&异步复位,同步释放&的处理。
&&&&&&&&下面是常见两种方式:
方式一:(自己看来应该是&异步复位同步化&)
always @ (posedge clk)
&&&&&&&&&rst_nr
&= rst_n;&&&&&&&&&&&&&&&&&//现将异步复位信号用同步时钟打一拍
always @ (posedge clk or negedge
&&&&&&&&&if(!rst_nr)
b &= 1'b0;
&&&&&&&&&else
方式二:(自己看来才是&异步复位,同步释放&)
pllrst1,pllrst2;
always @(posedge clk or negedge
&&&&if(!rst_n)
begin pllrst1 &= 1'b1;
&&&&&&&&&&&&&&&&&&&&&&&&&
pllrst2 &= 1'b1; end
begin pllrst1 &= 1'b0;
&&&&&&&&&&&&&&&&&
pllrst2 &= pllrst1; end
assign pllrst =
pllrst2;&&&&&&
//锁相环复位信号
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。FPGA异步复位同步释放解析
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&&&&&&&
&&& input&&&&&&& reset_n;
&&& input&&&&&&&
&&& input&&&&&&&
&&& output&&&&&&&
&&& output&&&&&&&
&&& 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) & &&&//“异步复位同步释放”的复位模块
&&&&&&& if (!reset_n)
&&&&&&&&&&& begin
&&&&&&&&&&&&&&& reg3&&& &= 1'b0;
&&&&&&&&&&&&&&& reg4&&& &= 1'b0;
&&&&&&&&&&& end
&&&&&&& else
&&&&&&&&&&& begin
&&&&&&&&&&&&&&& reg3&&& &= 1'b1;
&&&&&&&&&&&&&&& reg4&&& &= reg3;
&&&&&&&&&&& end
&&& always @ (posedge clk or&negedge rst_n) &&//功能模块,注意rst_n是沿变驱动。
&&&&&&& if (!rst_n)
&&&&&&&&&&& begin
&&&&&&&&&&&&&&& reg1&&& &= 1'b0;
&&&&&&&&&&&&&&& reg2&&& &= 1'b0;
&&&&&&&&&&& end
&&&&&&& else
&&&&&&&&&&& begin
&&&&&&&&&&&&&&& reg1&&& &=
&&&&&&&&&&&&&&& reg2&&& &=
&&&&&&&&&&& end
综合后的RTL图表如下:
下面对上面的图进行解说。我们看到,真正驱动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这个异步复位的端口实现了同步复位的功能,而同步复位信号效果更好,对毛刺抑制能力强,这就是“异步复位同步释放”的意义。所以让异步复位端口实现同步复位功能,这才是“异步复位同步释放的本质”!
关注微信公众号

我要回帖

更多关于 同步复位 异步复位 的文章

 

随机推荐