本文主要是介绍数字电路时序学习:(一)亚稳态,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
书籍《硬件架构的艺术:数字电路的设计方法与技术》
(一) 亚稳态
1.1 概念
-
由于违反触发器的建立时间和 保持时间 而产生的
-
在时钟的上升沿的窗口内,数据发生变化,输出未知或称为亚稳的
- 亚稳态窗口
亚稳态窗口 - 窗口越大,进入亚稳态的概率越高
1.2 危害
-
输出产生毛刺
-
暂时保持不稳定状态而且需要较长时间才回到稳定状态
-
一般需要1~2个时间周期才能返回稳态
1.3 MTBF
-
意义:故障率的倒数
M T B F = e ( t τ / τ ) W f c f d (1.1) MTBF =\frac {e(t_\tau/\tau)} {W f_c~f_d} \\\tag{1.1} MTBF=Wfc fde(tτ/τ)(1.1) -
说明
- t τ t_\tau tτ:允许超出器件正常传输延迟时间的解析时间
- τ \tau τ : 触发器的亚稳态(解析)的时间常数
- W W W:亚稳态窗口
- f c f_c fc :时钟频率
- f d f_d fd : 异步信号边沿频率
-
详细:略
1.4 出现场景
-
只要违背了建立时间和保持时间,亚稳态就会出现:
- 输入信号是异步信号
- 时钟偏移/摆动(上升/下降时间)高于容限值
- 信号在两个不同频率或者相同频率但是相位和偏移不同的时钟域下工作
- 组合延迟使触发器的数据输入在亚稳态窗口内发生改变
-
亚稳态不能根除,只能减小其发生的概率
1.5 避免亚稳态的方法
1.5.1 时钟周期足够长
- 如果对于性能不要求得情况下,可以将确保时钟周期足够长
- **时钟周期 > 准稳态得解析时间 **
- 方法简单,但是不实用
1.5.2 使用多级同步器
- 第一个完整的时钟周期解决亚稳态的问题
-
注意:
一个异步信号不应该被两个或多个同步器所同步,这样会产生多级同步器输出产生不同信号的风险
-
代码:两级同步器为例(常用)
俗称:“打两拍”
//两级同步器
module demo(input wire sys_clk,input wire sys_rst_n,input wire date_in,output reg date_out
),reg date_in_reg0;reg date_in_reg1;always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)date_in_reg0 <= 1'b0;elsedate_in_reg0 <= date_in;endalways @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)date_in_reg1 <= 1'b0;elsedate_in_reg1 <= date_in_reg0;endassign date_out = date_in_reg1 ;endmodule
-
优化方案:时钟倍频的多级同步器
-
方案局限性:使用上面“打两拍”的局限性很明显,需要花费比较长的时间去响应异步输入信号
-
解决方法: 对输入的时钟进行倍频作为两个同步触发器的时钟输入
用PLL对时钟进行倍频
带有时钟倍频电路的多级同步器 -
代码如下:
//两级同步器 module demo(input wire sys_clk,input wire sys_rst_n,input wire date_in,output reg date_out ),reg date_in_reg0;reg date_in_reg1;always @(posedge sys_clk_2x or negedge sys_rst_n) beginif(!sys_rst_n)date_in_reg0 <= 1'b0;elsedate_in_reg0 <= date_in;endalways @(posedge sys_clk_2x or negedge sys_rst_n) beginif(!sys_rst_n)date_in_reg1 <= 1'b0;elsedate_in_reg1 <= date_in_reg0;endassign date_out = date_in_reg1;pll pll_inst(.clk_in (sys_clk ),.c0 (sys_clk_2x ));endmodule
-
1.5.3 同步器的类型
1. 高频 → \rightarrow → 低频
法一:
-
电路图
描述:第一级触发器的输入
D
与 V c c V_{cc} Vcc相连,同时时钟信号是异步输入信号。另外两个触发器由系统时间(clk
)控制。一共短脉冲让q1
变成高电平,这个高电平经过两个时钟(clk
)沿后从sync_out
输出 -
时序图
-
代码
module demo (input wire sys_clk, input wire sys_rst_n,input wire clk_h, //高速时钟,本demo中没有用到input wire clk_l, //低速时钟,即图中clkinput wire async_in,output reg sync_out);//------------------------wire & reg-------------------// //reg1 复位信号 高电平复位 低电平正常工作 wire reg1_clr;reg q1; reg q2;//-------------------------mian------------------------// //reg_clr信号 assign reg1_clr = (!async_in) && sync_out; //reg1 always @(posedge async_in or posedge reg1_clr) beginif(reg1_clr == 1'b1)q1 <= 1'b0;elseq1 <= 1'b1; //即图中VCC end//reg2 always @(posedge clk_l) beginq2 <= q1; end//sync_out输出 always @(posedge clk_l) beginsync_out <= q2; endendmodule
法二:
-
思想:
由于是高频 → \rightarrow →低频,可能存在高频时钟域的信号,低频时钟域的时钟采集不到
于是,需要对高频时钟域的信号机型展宽,从而让低频时钟域的信号采集得到
注意:
signal_b
反馈到高频时钟域也是跨时钟域,同样需要进行处理 -
方法:
脉冲信号
pluse_a
在clk_h
下展宽,变成电平信号signal_a
,再向clk_l
传递,当确认clk_l
已经“看见”信号同步过去之后,再清掉signal_a
。其实现方式还是**“采集-打两拍-同步”**的 -
代码
module demo(input wire clk_h, input wire clk_l, input wire sys_rst_n, input wire pulse_a_in, output wire pulse_b_out, output wire b_out );//---------------- wire & reg ---------------------//reg signal_a;reg signal_b;reg signal_b_r1;reg signal_b_r2;reg signal_b_a1;reg signal_b_a2;//---------------- mian --------------------------////在时钟域clk_h下,生成展宽信号signal_aalways @(posedge clk_h or negedge sys_rst_n) beginif(!sys_rst_n)signal_a <= 1'b0;else if(pulse_a_in == 1'b1) //检测到到输入信号pulse_a_in被拉高,则拉高signal_asignal_a <= 1'b1;else if(signal_b_a2 == 1'b1) //检测到signal_b1_a2被拉高,则拉低signal_asignal_a <= 1'b0;elsesignal_a <= signal_a;end//在时钟域clk_l下,采集signal_a,生成signal_balways @ (posedge clk_l or negedge sys_rst_n)beginif (!sys_rst_n)signal_b <= 1'b0;elsesignal_b <= signal_a;end//多级触发器处理(此处为两级)always @ (posedge clk_l or negedge sys_rst_n)beginif (!sys_rst_n) beginsignal_b_r1 <= 1'b0;signal_b_r2 <= 1'b0;endelse beginsignal_b_r1 <= signal_b; //对signal_b打两拍signal_b_r2 <= signal_b_r1;endend//在时钟域clk_a下,采集signal_b_r1,用于反馈来拉低展宽信号signal_aalways @ (posedge clk_h or negedge sys_rst_n) beginif (!sys_rst_n) beginsignal_b_a1 <= 1'b0;signal_b_a2 <= 1'b0;endelse beginsignal_b_a1 <= signal_b_r1; //对signal_b_r1打两拍,因为同样涉及到跨时钟域 signal_b_a2 <= signal_b_a1;endendassign pulse_b_out = signal_b_r1 & (~signal_b_r2);assign b_out = signal_b_r1;endmodule
2. 低频 → \rightarrow → 高频
-
低频信号到高频信号不存在采集不到信号的问题,于是,可以直接采用打两拍的方法进行检测
-
代码
// 代码直接采用多级同步器的代码
-
一种特殊的情况——低频域的输出信号是由组合逻辑生成的
(assign)
-
电路图
说明:
- 时钟域1为低频时钟域,时钟域2为高频时钟域
Data_in
是由组合逻辑生成的,即assign
- 时钟域2阴影部分表示的是多级同步器
-
代码
module demo(input wire clk_l,input wire clk_h,input wire sys_rst_n,input wire date_in,output reg date_out );reg date_l;reg date_h_0; reg date_h_1;//组合逻辑的信号先经过低时钟域的时钟的同步 always @(posedge clk_l or negedge sys_rst_n) beginif(!sys_rst_n)date_l <= 1'b0;elsedate_l <= date_in; end//高时钟域下对date_in同步 always @(posedge clk_h or negedge sys_rst_n) beginif(!sys_rst_n) begindate_h_0 <= 1'b0;date_h_1 <= 1'b0;endelse begindate_h_0 <= date_l;date_h_1 <= date_h_0;end endassign date_out <= date_h_1;endmodule
-
1.6 总结——减小亚稳态
明确:亚稳态是无法避免的,只能减小亚稳态发生的概率
以下为几种减小亚稳态发生概率的方法
- 采用同步器
- 采用响应更快的触发器(缩短亚稳态窗口 T w T_w Tw)
- 采用亚稳态硬化触发器(专为高带宽设计并且减小为时钟域输入电路而优化的采样时间)
- 采用级联触发器作为同步器
- 如果一共触发器发生亚稳态失败的概率为 P P P,则 N N N个触发器的亚稳态失败的概率为 P N P^N PN
- 减小采样速率
- 避免使用 d V / d t dV/dt dV/dt低的时候输入信号
这篇关于数字电路时序学习:(一)亚稳态的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!