一、什么是亚稳态
亚稳态是指触发器无法在某个规定时间内达到一个可确认的状态。当一个触发器进入亚稳态时,既无法预测该单元的输出电平,也无法预测何时输出才能稳定在某个正确的电平上。在这段时间里,触发器输出一些中间级电平,或者可能处于振荡状态,并且这种无用的输出电平可以沿信号通道上的各个触发器级联式传播下去。
二、不产生亚稳态
以下为不产生亚稳态的情况
三、亚稳态及产生原因
四、处理亚稳态的方法
引言
亚稳态产生的概率 = (建立时间 + 保持时间)/ 采集时钟周期 。
1、降低系统时钟频率
WHY:时钟频率降低,采样时钟周期增大,亚稳态产生的概率降低。
2、用反应更快的FF。
WHY: 建立时间和保持时间更小。
3、 引入同步机制,防止亚稳态传播(可以采用多级触发器寄存打拍)。
WHY:多级触发器为什么能降低亚稳态?
(1)第一级寄存器产生亚稳态后,如果直接输出很可能将亚稳态传递下去导致系统崩溃;而添加了第二级D触发器后,相当于多给了寄存器一个时钟周期的时间恢复稳定,因此出现亚稳态的几率就会大大减小。
(2)证明:举例,假设Tsu+Thd=1ns,触发器的采样时钟周期是10s,第一级触发器产生亚稳态的概率是10%,第二级触发器产生亚稳态的概率是10%,则两级触发器产生亚稳态的概率是10%x10%=0.01,则第三级触发器信号输出稳定的概率是1-1%=99%。
第一级触发器产生亚稳态,且Tmet1大于一个时钟周期,故亚稳态出现了串扰。传递到第二级触发器。
两级触发器代码编写
input signal;
reg signal_r1;
reg signal_r2;
wire signal_rising;
wire signal_down;
always@(posedge clk or negedge rst)
if(!rst)
signal_r1<= 1'b0;
else
signal_r1<= signal;
always@(posedge clk or negedge rst)
if(!rst)
signal_r2<= 1'b0;
else
signal_r2<= signal_r1;
assign signal_rising = ((signal_r1 == 1'b1)&&(signal_r2 == 1'b0))? 1:0; //检测上升延
assign signal_down = ((signal_r1 == 1'b0)&&(signal_r2 == 1'b1))? 1:0; //检测下降延
//-----------便捷方法如下----------
input signal;
reg [3:0] sig_nsyn_r; //信号异步移位
wire signal_rising;
wire signal_down;
always@(posedge clk or negedge rst)
begin
if(!rst)
sig_nsyn_r <= 2’d0;
else
sig_nsyn_r <= { sig_nsyn_r [0], sig_nsyn };
end
assign signal_rising = ~sig_nsyn_r[3] & sig_nsyn_r[2];
assign signal_down = sig_nsyn_r[3] & ~sig_nsyn_r[2];
4、采用FIFO对跨时钟域数据通信进行缓冲设计
WHY : 当数据流从一个时钟域到另一个时钟域的时候,绝大多数情况下都采用FIFO来作为中间缓冲,采用双时钟对数据缓冲,就可以避免亚稳态的发生。
FIFO在进行寻址时,采用的是格雷码编码。
跨时钟域进行同步之前,可以先将二进制转换为格雷码表示,相对于二进制,格雷码在进行跨时钟域转换时,产生亚稳态的概率更小,格雷码是一种非权重码,每次变化位数只有一位,这就有效的避免了在跨时钟域情况下亚稳态问题发生的概率。举个例子,二进制的7(0111)跳转到8(1000),4位都会发生变化,所以发生亚稳态的概率就比较大。而格雷码的跳转就只有一位(从0100--1100,仅第四位发生变化)会发生变化,有效地减小亚稳态发生的可能性。
5、改善时钟质量,用边沿变化快速的时钟信号。
WHY: 触发器是时钟边沿敏感,时钟边沿变化快速,越接近理想时钟边沿,更容易降低亚稳态发生的概率。
查询资料:
https://www.cnblogs.com/linjie-swust/archive/2012/01/07/YWT.html
https://www.youtube.com/watch?v=kz9NWmc2N6w
https://www.youtube.com/watch?v=U6AFsAovPJQ