时序逻辑异时钟域造成D触发器亚稳态问题及解决方法

时序逻辑输出分析

1.找时钟
2.确定触发沿,确定上升沿还是下降沿
3.看输入 看时钟沿前(保持的信号值)输入
4.得输出 得到延迟一拍的输出

亚稳态

D触发器响应需要满足建立时间和保持时间要求,及数据必须在一个时间窗口内保持稳定,

亚稳态就是不能满足该时间窗要求而产生的现象,通常出现在可能有信号在时钟跳变沿变化时。
造成该情况一般有:

  • 时序不满足
  • 不同时钟域信号
  • 按键、外部芯片读写

根据信号类型,分为单比特和多比特信号,
根据时钟域,分为由快时钟到慢时钟,由慢时钟到快时钟

当时钟不匹配时,就要进行同步化(做异步处理),否则就可能出现亚稳态,从而造成整个设计不稳定。

单bit信号,如控制信号

1、快时钟域到慢时钟域

因为快时钟域的脉冲信号pulse_a信号的保持时间小于慢时钟域clk_b的时钟周期,快时钟域的脉冲信号容易被慢时钟域的捕获沿漏掉,一般操作是扩宽脉冲信号

 module  Sync_Pulse(
                                         input              clk_a,
                                         input              clk_b,
                                         input              rst_n,
                                         input              pulse_a_in,
                                         output           pulse_b_out,
                                         output           b_out
                                          );
  /**************************************************************************************/
  reg                          signal_a;
  reg                          signal_b;
  reg                          signal_b_s;
  reg                          signal_b_ss;
  reg                          signal_b_a1;
  reg                          signal_b_a2;

//在时钟域clk_a下,生成展宽信号signal_a
    always @ (posedge clk_a or negedge rst_n)
        begin
            if (rst_n == 1'b0)
                signal_a <= 1'b0;
            else if (pulse_a_in)            //检测到到输入信号pulse_a_in被拉高,则拉高signal_a
                signal_a <= 1'b1;
            else if (signal_b_a2)           //检测到signal_b1_a2被拉高,则拉低signal_a
                signal_a <= 1'b0;
            else;
        end
//在时钟域clk_b下,采集signal_a生成signal_b

always@(posedge clk_b or negedge rst_n)begin
            if(rst_n == 1'b0)begin
                signal_b <= 0;
           end
           else begin
               signal_b <= signal_a;
           end
end
//多级触发器将clk_b抓到的signal_b信号打两拍输出
always@(posedge clk_b or negedge rst_n)begin
       if(rst_n == 1'b0)begin
       signal_b_s  <= 1'b1;
       signal_b_ss <= 1'b1;
       end
       else begin
       signal_b_s  <= signal_b;
       signal_b_ss <= signal_b_s;
       end
end
//在时钟域clk_a下,采集signal_b_s,用于反馈来拉低展宽信号signal_a
always@(posedge clk_a or negedge rst_n)begin
  if(rst_n == 1'b0)begin
      signal_b_a1 <= 1'b0;
      signal_b_a2 <= 1'b0;
  end
  else begin    //对signal_b_s打两拍,因此处涉及到跨时钟域
      signal_b_a1 <= signal_b_s;
      signal_b_a2 <= signal_b_a1;
  end
end
assign   pulse_b_out = signal_b_s & (~signal_b_ss);
assign   b_out            = signal_b_s;

endmodule

2、慢时钟域到快时钟域
在这里插入图片描述
正常捕获就可以。

引入同步机制,防止亚稳态传播
在这里插入图片描述
verilog描述

always@(posedge clk_a or negedge rst_n) begin
	if(rst_n==0) begin
		a<=0;
		a1<=0;
		a2<=0;	
	end
	else begin
		a<=dout_b;
		a1<=a;
		a2<=a1;
	end
end
assign  pules_out = a1;
assign pules_a_pos = a1& (~a2); //输出信号的上升沿检测
assign pules_a_neg = a2& (~a1); //下降沿检测

a1可以使用

多bit信号

1 如数据流,使用异步FIFO/RAM

在这里插入图片描述
异步FIFO内部已经做了异步握手处理,rdempty/wrempty做了异步处理

2 使用时钟使能信号,如少量发送可控的数据流

保证在使能信号有效时,数据保持
在这里插入图片描述

注:

  1. 全局时钟的跳变沿最可靠。
  2. 来自异步时钟域的输入需要寄存一次以同步化,再寄存一次以减少亚稳态带来的影响。(打两拍)
  3. 不需要用到跳变沿的来自同一时钟域的输入,没有必要对信号进行寄存。
  4. 需要用到跳变沿的来自同一时钟域的输入,寄存一次即可。
  5. 需要用到跳变沿的来自不同时钟域的输入,需要用到3个触发器,前两个用以同步,第3个触发器的输出和第2个的输出经过逻辑门来判断跳变沿

行为描述

10计数器
判断 begin end 内不是串行,电路执行时候只执行一句

always@(posedge clk or negedge rst_n) begin
	if (rst_n==0) begin
		cnt<=0;
	end
	else if (cnt==9) begin
		cnt<=0;
	end
	else begin
		cnt<=cnt+1;
	end
end

ref
https://blog.csdn.net/emperor_strange/article/details/82491085

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值