异步时钟亚稳态 的解决方案——多bit信号

本文探讨了时钟偏斜引发的多比特信号采样问题,通过灰码循环编码和同步valid使能策略解决中间值问题。介绍了同步valid最小持续时间和间隔的重要性,以及异步FIFO在解决数据跨时钟域问题中的应用。

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


对于多bit而言,跨时钟域解决方法与异步时钟亚稳态 的解决方案——单bit信号是类似的,可以对照学习。

跨时钟域处理方法总结–最终详尽版跨时钟域处理–最终详尽版
FPGA 设计之 跨时钟域(三 - 多比特小结)
FPGA 设计之 跨时钟域(四 - 格雷码)
FPGA 设计之 跨时钟域(六 - 握手)
同步valid&ready握手 与 异步valid&ack握手
《Clock Domain Crossing》 翻译与理解(5)多信号跨时钟域传输
推荐】数字芯片跨时钟域设计经典论文
多bit信号跨时钟域怎么办? – CDC的那些事(4)
菜鸟教程:4.2 Verilog 跨时钟域传输:慢到快

1. 亚稳态问题——电平同步

1.1. 时钟偏斜 导致的采样中间值问题

时钟偏斜skew:时钟沿信号到达各触发器CK端的时间不同

这会导致多bit信号的每个触发器值变化不是同时的,有的变得快有的变得慢,如果每个bit都没变完,就被异步时钟采样了,就会出现中间值。

单bit信号电平也好,脉冲也好跨时钟域,采样到了就算有点延迟也没关系,最终产生一个脉冲就行。
但是多bit信号要求整个变化过程都是恒定的,中间出现了第三个值就可能对功能产生影响。

看图

在这里插入图片描述
红线处adata由000变为111,因为时钟偏斜,该信号每个bit真正开始拉高的时刻不一样。如果异步时钟bclk在不同的时刻采样会对应不同时刻的值,3条绿线分别对应采样到001、101、111。

1.2. “3个沿”+允许skew——电平同步

是的,多bit信号也可以进行电平同步。

如果满足“3个沿”条件,说明最终一定可以采样到正确的数据。但由于time skew的存在,可能第一次采样到中间值、第二次采到正确值。

所以如果允许出现中间值,可以直接打两拍。即要求 1.5 T b c l k < T a s i g 1.5T_{bclk} < T_{asig} 1.5Tbclk<Tasig

2.1. “>8个沿”+不允许skew——valid信号D+MUX选通

如果数据信号带有valid,且占据目的时钟8个沿甚至更久,可以对valid作CDC,然后用valid去采稳定后的源数据信号。

方法与单bit边沿检测是相同的,为多bit信号配一个1bit有效标志valid,使用valid作边沿检测

如下图所示

在这里插入图片描述

avalid拉低表示传输结束,adata没变是用于省电,常见手法

上代码

reg bvalid_cdc_to, bvalid_d2, bvalid_d3;
wire bvalid_d2_rise = bvalid_d2 && (!bvalid_d3);
always@(posedge bclk) begin
	bvalid_cdc_to <= avalid;
	bvalid_d2 	  <= bvalid_cdc_to ;
	bvalid_d3 	  <= bvalid_d2;
	bvalid 	  	  <= bvalid_d2_rise ;
end
always@(posedge bclk) begin
	if(bvalid_d2_rise)
		bdata <= adata;
end

2. 漏采样——展宽

如果不满足“3个沿”出现漏采样,或者“3个沿”不允许time skew,就只能通过展宽解决。

仍然借用DMUX的思路,将valid作展宽处理,采样稳定的data即可

2.1. valid延迟展宽

对valid打拍取或,在目的时钟用沿采样data即可。前提是保证展宽后数据保持不变

reg [3:0] avalid_dly;		// aclk
reg bvalid_dly_cdc_to;		// bclk
reg bvalid_dly_d1;			// bclk
reg bvalid_dly_d2;			// bclk

always@(posedge aclk) begin
	avalid_dly <= {avalid_dly[2:0], avalid};
end

wire bvalid_dly_d1_rise = bvalid_dly_d1 && (!bvalid_dly_d2);

always@(posedge bclk) begin
	bvalid_dly_cdc_to <= (|avalid_dly);
	bvalid_dly_d1 	  <= bvalid_dly_cdc_to; 
	bvalid_dly_d2	  <= bvalid_dly_d1;
	bvalid 		 	  <= bvalid_dly_d1_rise;		// bclk
end

always@(posedge bclk) begin
	if(bvalid_dly_d1_rise)
		bdata <= adata;
end

2.2. valid 异或展宽

对valid也可做异或展宽,与单bit区别就是增加了在bclk有效时采样adata,直接上代码

reg avalid_dly = 1'd0;		// aclk
reg avalid_xor;				// bclk

always@(posedge aclk) begin
	avalid_xor <= avalid_dly ^ avalid;
end

reg bvalid_xor_cdc_to;		// bclk
reg bvalid_d2;				// bclk
reg bvalid_d3;				// bclk
reg bvalid;				// bclk

wire bvalid_xor = (bvalid_d2 != bvalid_d3);

always@(posedge bclk) begin
	bvalid_xor_cdc_to <= avalid_xor;
	bvalid_d2 		  <= bvalid_xor_cdc_to;
	bvalid_d3 		  <= bvalid_d2;
	bvalid 		  	  <= bvalid_d2;
end

always@(posedge bclk) begin
	if(bvalid_xor)
		bdata <= adata;
end

3. 高频变化/缓存——异步FIFO

如果满足1.5倍频DMUX方案中bvalid采样的是下一个adata,怎么办?

如果异或展宽中两个adata离得太近导致bclk无法拆成两个bpulse,怎么办?

如上这种源时钟数据变化太快的问题,都可以用异步FIFO解决。但是异步FIFO实际上并未解决数据信号跨时钟域问题,而是把问题转化成多bit读写指针的跨时钟域问题了。

对于读写指针而言,属于递增计数器,需要电平同步 + Grey码的方式进行处理,同时读写逻辑也并不关注读写指针的变化过程,因此快采慢的多采样问题和慢采快的漏数问题都不会产生影响。

因此,full和empty标志并不能实时反应当前时刻FIFO的真实状态,但这种错误并不会造成满写和空读的问题。

详情见异步FIFO设计

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Starry丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值