数字电路中跨时钟域问题CDC-----2(单比特数据传输)

本文深入探讨了数字电路设计中的跨时钟域问题,详细解释了亚稳态的产生原因及解决方法,并通过示例代码展示了从慢时钟域到快时钟域以及从快时钟域到慢时钟域的同步过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

说实话,在最开始学习到这个打两拍的时候,内心的声音是:“这TM??????这么简单就可以了吗?凭什么第二级的输出就没有亚稳态了?” 相信有很多同学也和我当初有同样的困惑。在这里我们要再次回顾一下metastable(在上一个章节提到过这个问题的概念以及产生原因)产生的原因。第一级flop产生metastable的原因是flop里面没有及时锁住该锁的值,所以我们无法直接使用第一级flop的Q来直接用于bclk时钟域。但是要注意,我们之前说过,第一级flop的Q会最终稳定下来的,而且在绝大多数时候,可以在一个bclk周期内稳定下来,这样第二级flop的D输入就是一个稳定的值,进而第二级flop的Q是满足clk-to-q的,没有亚稳态的产生。在这里插入图片描述


提示:如果不进行跨时钟域数据同步的化可能会出现下列时序图的影响。在这里插入图片描述

一、跨时钟域问题是什么?

跨时钟域问题是在数字电路中经常需要遇到的实际问题,下边列举了几个跨时钟域的问题以及解决方案。
在这里插入图片描述

二、一般解决思路以及步骤

1.慢时钟域到快时钟域

在这里插入图片描述

代码如下(示例):clk_b —>>>> clk_a使用两级寄存器进行直接同步(前提情况是脉冲信号在前一个时钟域中是由触发器产生并不是组合逻辑产生)

reg [1:0] signal_r;
//-------------------------------------------------------
//
always @(posedge clk or negedge rst_n)begin
	if(rst_n == 1'b0)begin
		signal_r <= 2'b00;
	end
	else begin
		signal_r <= {signal_r[0], signal_in};
	end
end
assign signal_out = signal_r[1];

2.快时钟域到慢时钟域

代码如下(示例):解决这个问题的思路一般都是在
1将快的时钟域中的信号进行展宽
2对展宽的信号在慢的时钟域2级同步
3在慢时钟域中产生反馈信号来对快的展宽信号进行拉低处理

module Sync_Pulse (
                  clk_a,        
                  clk_b,   
                  rst_n,            
                  pulse_a_in,   
                 
                  pulse_b_out,  
                  b_out 
                  );
/****************************************************/
 
    input               clk_a;
    input               clk_b;
    input               rst_n;
    input               pulse_a;
    
    output              pulse_b_out;
    output              b_out;      
    
/****************************************************/  
 
    reg                 signal_a;
    reg                 signal_b;
    reg                 signal_b_r1;
    reg                 signal_b_r2;
    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)
                signal_b <= 1'b0;
            else
                signal_b <= signal_a;
        end
    //多级触发器处理
    always @ (posedge clk_b or negedge rst_n)
        begin
            if (rst_n == 1'b0) 
                begin
                    signal_b_r1 <= 1'b0;
                    signal_b_r2 <= 1'b0;
                end
            else 
                begin
                    signal_b_r1 <= signal_b;        //对signal_b打两拍
                    signal_b_r2 <= signal_b_r1;
                end
        end
    //在时钟域clk_a下,采集signal_b_r1,用于反馈来拉低展宽信号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_a1 <= signal_b_r1;     //对signal_b_r1打两拍,因为同样涉及到跨时钟域   
                    signal_b_a2 <= signal_b_a1;
                end
        end
 
    assign  pulse_b_out =   signal_b_r1 & (~signal_b_r2);
    assign  b_out       =   signal_b_r1;
 
endmodule

总结

奥里给就完事了,下次讲解多比特的跨时钟域问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值