跨时钟域传输总结(包含verilog代码|Testbench|仿真结果)

本文详细介绍了跨时钟域传输的原理和方法,包括单比特传输中的慢到快、快到慢策略,如延迟打拍和握手协议,并提供了Verilog代码示例。对于多比特传输,由于时序问题,不能直接使用二级同步器,而应采用MUX同步器法或异步FIFO。异步FIFO作为一种通用解决方案,适用于快慢时钟间的双向传输,能有效处理数据流的高速传输需求。

在这里插入图片描述

一、单比特CDC传输

1.1 慢到快

快时钟域相比慢时钟域采样速度更快,也就是说从慢时钟域来到快时钟域的信号一定可以被采集到。既然快时钟一定可以采集到慢时钟分发的数据,那么考虑的问题就只剩下如何保证采样到的信号质量!最常用的同步方法是双级触发器缓存法,俗称延迟打拍法。信号从一个时钟域进入另一个时钟域之前,将该信号用两级触发器连续缓存两次,可有效降低因为时序不满足而导致的亚稳态问题。
具体如下图所示:来自慢时钟clk1的信号在clk2被多次采样(信号在clk1持续一个时钟周期,在clk2持续三个时钟周期),如果只需要在clk2持续一个时钟周期,可以采用边沿检测即可得到signal4;

在这里插入图片描述

1.2 快到慢

慢时钟域相比快时钟域采样速度更慢,也就是说从快时钟域来到慢时钟域的信号极有可能被漏采。一般要求在接收时钟域中采样信号要保持三个时钟边沿的时间(也就是1.5倍的采样时钟周期)才会避免出现漏采。也就是快到慢跨时钟域的核心是如何延长信号长度!

对于电平信号而言(一般电平信号持续时间足够长),信号长度可以得到保证,所以正常采用两级同步器采样即可。

对于脉冲信号而言(一般脉冲信号持续时间很短),长度难以得到保证,需要对信号进行延长。目前,常用延长方法有两种:

  • 一是开环(无反馈)延长,在知道两个时钟频率比的情况下,可以采用“快时钟域脉宽扩展+慢时钟域延迟打拍”的方法进行同步。

  • 二是闭环(有反馈)延长,信号延长的恢复位置由反馈信号决定,此方法实质是通过相互握手的方式对窄脉冲信号进行脉宽扩展,这也是我们常说的“握手协议”。

然而,除了“握手协议”以外其他两种方法都是有缺陷、有限制的,具体如下图所示:
在这里插入图片描述

在这里插入图片描述

可以看到无论是电平还是脉冲信号使用起来都是有限制的,因为它们采用的都是无反馈的开环设计(详细可查看博文跨时钟传输——单比特)。采用闭环的反馈设计可以避免这些问题,具体流程如下:

在这里插入图片描述

  1. 快时钟域对脉冲信号进行检测,检测为高电平时输出高电平信号req。
  2. 慢时钟域对快时钟域的信号req进行延迟打拍采样。因为此时的脉冲信号被快时钟域保持拉高状态,延迟打拍肯定会采集到该信号。
  3. 慢时钟域确认采样得到高电平信号req_r2后,拉高反馈信号ack再反馈给快时钟域。
  4. 快时钟域对反馈信号ack进行延迟打拍采样得到ack_r0。如果检测到反馈信号为高电平,证明慢时钟域已经接收到有效的高电平信号,信号恢复原来状态。
    在这里插入图片描述
    在这里插入图片描述

1.3 单比特“握手协议”verilog代码

verilog代码

//单比特快到慢“握手协议”
module cdc_sbit_handshake(
    input 		aclk,	//快时钟
    input 		arst_n,	//快时钟域复位信号
    input 		signal_a,//快时钟域信号
    input 		bclk,	//慢时钟
    input 		brst_n,	//慢时钟域复位信号
    output 		signal_b//慢时钟域输出信号
    );
                             
//慢时钟域信号展宽直至反馈信号回来再恢复
reg   req;//寄存慢时钟域展宽信号
reg   ack_r0;//反馈信号
always@(posedge aclk or negedge arst_n) begin
    if(!arst_n) begin
        req <= 1'b0;
    end
    else if(signal_a) begin
        req <= 1'b1;	//信号展宽
    end
    else if(ack_r0) begin
        req <= 1'b0; 	//反馈信号到来时恢复
    end
end

//展宽信号跨时钟同步至慢时钟域
reg   req_r0;
reg   req_r1; 
reg   req_r2;                          
always@(posedge bclk or negedge brst_n) begin
    if(!brst_n)begin
        {
   
   req_r2,req_r1,req_r0} <= 3'b0;
    end
    else begin        
        {
   
   req_r2,req_r1,req_r0} <=  {
   
   req_r1,req_r0,req};
    end
end

//生成反馈信号并同步至快时钟域
reg   ack;                          
always@(posedge aclk or negedge arst_n) begin
    if(!arst_n) begin
        {
   
   ack_r0,ack} <= 2'b0;
    end
    else begin
        {
   
   ack_r0,ack} <=  {
   
   ack,req_r1}; 
    end
end

//信号上升沿检测,让输出持续一个慢时钟周期
assign signal_b = ~req_r2 & req_r1;

endmodule

Testbench

`timescale 1ns/1ps	//仿真时间单位1ns 仿真时间精度1ps
module cdc_sbit_handshake_tb;

//信号申明
reg	 	aclk;
reg	 	arst_n;
reg	 	signal_a;
reg		bclk;
reg		brst_n;
wire	signal_b;

//例化
cdc_sbit_handshake u_cdc_sbit_handshake(
    .aclk	(aclk),
    .bclk	(bclk),
    .arst_n	(arst_n),
    .brst_n	(brst_n),
    .signal_a	(signal_a),
    .signal_b	(signal_b)
    );

//快时钟域慢时钟生成
always #5  aclk =~ aclk;
always #15 bclk =~ bclk;

//初始信号赋值与激励
initial begin
    signal_a = 0;
    aclk = 0;
    bclk = 0;
    arst_n = 1;
    brst_n = 1;
    #15;
    arst_n = 0;
    brst_n = 0;
    #15;
    arst_n = 1;
    brst_n = 1;
    signal_a = 1;
    #10;
    signal_a = 0;

end

endmodule 

仿真结果

在这里插入图片描述

二、多比特CDC传输

  • 多比特为能不能使用二级同步器传输?使用格雷码也不行吗?什么情况下可以使用同步器加格雷码跨时钟传输?

先给结论:多比特信号不能用二级同步器跨时钟传输,哪怕使用格雷码大部分情况也不行,只有在格雷码自增或自减顺序变化才可以跨时钟传输。对于多比特数据,在进行传输时候会因为时序问题导致所有寄存器不会同时翻转(不是不翻转,是不同时翻转!),所以容易在跨时钟传输的时候出现中间态。使用格雷码可以避免这种现象,但是当格雷码不是按计数顺序变化(非顺序变化相当于每次变化不止一位),这同样是不允许的,因为格雷码每次只有一位发生变化的前提是,数据是递

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值