第一次接触这个词是在小梅哥的FPGA课程上,当时讲的是按键的亚稳态。现在仔细想想,按键也好,传输信号也好,复位信号也好,本质上都是信号传输的亚稳态,分析起来的方法大差不差,干就完了!
1 前言
1.1 亚稳态发生原因
先来一段比较传统的解释:
在FPGA系统中,如果数据传输中不满足触发器的建立时间和保持时间,或者复位过程中复位信号的释放相对于有效时钟沿的恢复时间和移除时间不满足,就可能产生亚稳态。此时触发器输出端Q在有效时钟沿之后比较长的一段时间处于不确定的状态,在这段时间里Q端在0和1之间处于振荡状态,而不是等于数据输入端D的值。
当然,我也知道这样的解释不够通俗,大家看个乐子就好。主要还是第二节再详细解释。
1.2 亚稳态发生场合
只要系统中有异步信号,亚稳态就是无法避免的,亚稳态主要发生在异步信号检测、跨时钟域信号传输以及复位电路等常用设计中。
2 亚稳态分析
2.1 信号传输中的亚稳态
在同步系统中,输入信号总是系统时钟同步,所以亚稳态不会发生。而在异步系统中,各个信号无法达到同步,当数据在寄存器Tsu-Th(建立时间-保持时间)窗口发生变化,就可能发生亚稳态现象。这里以两级寄存器为例,说明亚稳态现象。
2.1.1 状态一
如下图所示,当输入信号在clk的Tsu-Th窗口变化,寄存器难以判断输入信号是0是1,在Tco(寄存器的输入输出耗时)后,有一段不稳定的状态。这个状态时常时短,当为下图中的长短时,它在下一个clk上升沿到来之前稳定,不影响后续输出判断。这样的亚稳态是影响最轻的亚稳态。
2.1.2 状态二
下图是第二种情况。Tmet结束后,误判输入输出了0。在下一个clk上升沿才检查到错误,变为1,导致第二级触发器的信号也延迟了一个周期。这种情况则比上一种严重一些。
1.由于输出延迟了一个周期改变,如果sig信号在此之前就变回0,我们就错过了这次信号的判断机会;
2.延迟一个周期虽说信号仍得到传输,但总归是延迟了,会存在其他问题。
2.1.3 状态三
图三则是最严重的情况。由于Tmet持续时间过长,影响了下一个clk时钟的信号传输,Reg1也接收到了非0非1信号,发生了亚稳态,亚稳态进行了传输。
PS:按键的消抖程序中状态机会卡应该就是这种情况。本来两级寄存器判断边沿状态(前两种状态分别能在第二个clk,第三个clk判断到Reg[1:0] = 01),但是状态三丢失了这个状态。
2.2 亚稳态发生概率
2.2.1 单级亚稳态发生概率
由前文分析得知,亚稳态发生的原因主要是sig和clk的冲突。常用FPGA器件的Tsu+Th约等于1ns。只要信号变化发生在Tsu-Th窗口内,那就很可能会产生亚稳态,亚稳态产生的概率大概为:
概率 = (建立时间 + 保持时间) / 采集时钟周期 概率= (建立时间 + 保持时间)/ 采集时钟周期 概率=(建立时间+保持时间)/采集时钟周期
可以看出,随着clk频率的增加,亚稳态发生的几率是增加的。
例如,为系统采用100M时钟对一个外部信号进行采集,采集时钟周期为10ns,那采集产生亚稳态的概率为:1ns/10ns = 10%;采用300M时钟对一个外部信号进行采集,那产生亚稳态的概率为:1ns/3.3ns = 30%
所以在异步信号采集过程中,要想减少亚稳态发生的概率:
(1) 降低系统工作时钟,增大系统周期,亚稳态概率就会减小;
(2) 采用工艺更好的FPGA,也就是Tsu和Th时间较小的FPGA器件;
2.2.2 亚稳态的串扰概率
假设单级亚稳态概率假设是10%。这样,第二级接收到亚稳态信号的概率为30%,如果有第三级,接收到亚稳态的概率就变成10%*10% = 1%。多级寄存器能显著减少亚稳态概率。
3 消除亚稳态
有亚稳态产生,我们就要对亚稳态进行消除。常用的亚稳态消除方式有两种(未考虑复位的亚稳态消除方式):
(1) 对异步信号进行同步处理;
(2) 采用FIFO对跨时钟域数据通信进行缓冲设计;
3.1 对异步信号进行同步提取边沿
在异步通信或者跨时钟域通信过程中,最常用的就是对异步信号进行同步提取边沿处理。对一个异步信号进行提取上升沿通常采用如下代码:
// An highlighted block
input sig_nsyn;
output 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的信号进行判断的电路造成影响,甚至判断出错误的值。
因此,在进行异步信号跨频提取边沿时候,一般采用多进行一级寄存器减轻亚稳态,可能在系统稳定性要求高的情况下,采用更多级寄存器来消除亚稳态,代码如下所示。
// An highlighted block
input sig_nsyn;
output 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.2 FIFO进行异步跨频数据处理
当数据流从一个时钟域到另一个时钟域的时候,绝大多数情况下都采用FIFO来作为中间缓冲,采用双时钟对数据缓冲,就可以避免亚稳态的发生。