使能信号的跨时钟域处理

文章讨论了一个项目中遇到的问题,即通过RMII接口接收的2位数据需转换到50MHz系统时钟下进行分析。由于亚稳态的存在,直接打拍法导致数据错误。解决方案是延长使能信号并添加4拍延迟,同时使用异步FIFO来确保数据的正确传输,但需注意异步FIFO的延迟影响。
摘要由CSDN通过智能技术生成

最近做的一个项目中,需要将网口传输的数据同步到系统时钟下进行分析。
这块板子上以太网使用的是 RMII 接口,一次发送 2 位数据。我在网口时钟域下,将数据拓宽成 8 位,分析完网络协议之后再传递给系统时钟。这样,每 4 个时钟周期出现一次使能信号,一次发送 1 字节数据。
我原本想着,网口时钟和系统时钟都是 50 MHz,那么直接打两拍就可以了。刚开始少量的数据并未发现问题,后面大量数据连续发送时,出现了明显的数据错误。抓取使能信号可以看到,有一些地方使能信号连续出现两个时钟周期,并且出现错误的地方都不是孤立的,错误会连续出现。
这是因为打拍只能消除亚稳态,但无法保证数据的正确。上述抓取到的错误情况中,源数据恰巧处于亚稳态,打拍时选取了错误的值,给后续使用。并且可以推测,也有许多使能缺失的错误情况。
对于这个问题,可以延长原使能信号,打拍后捕捉上升沿的方式来产生新的使能信号。代码如下:

always @ ( posedge rmii_clk or negedge sys_rst_n ) begin
	if ( !sys_rst_n ) begin
		udp_rxdv_d1 <= 1'b0;
		udp_rxdv_wide <= 1'b0;
	end else begin
		udp_rxdv_d1 <= udp_rxdv_i;
		udp_rxdv_wide <= udp_rxdv_i || udp_rxdv_d1;
	end
end

always @ ( posedge sys_clk or negedge sys_rst_n ) begin
	if ( !sys_rst_n ) begin
		udp_rxdv_wide_d1 <= 1'b0;
		udp_rxdv_wide_d2 <= 1'b0;
	end else begin
		udp_rxdv_wide_d1 <= udp_rxdv_wide;
		udp_rxdv_wide_d2 <= udp_rxdv_wide_d1;
	end
end

always @ ( posedge sys_clk or negedge sys_rst_n ) begin
	if ( !sys_rst_n ) begin
		udp_rxdv <= 1'b0;
	end else if ( udp_rxdv_wide_d1 && !udp_rxdv_wide_d2 ) begin
		udp_rxdv <= 1'b1;
	end else begin
		udp_rxdv <= 1'b0;
	end
end

这样使能信号处理好了,理想情况下,相对于原使能信号打了 4 拍。这种处理方法也适用于频率不同的时钟,但要确保以下两点:

  1. 使能信号不是连续的。
  2. 演延长后的使能信号,其高、低电平的持续时间,在新的时钟域下都要大于一个时钟周期,以确保使能信号发生时能捕捉到上升沿。

对于数据,同样不能做简单的打拍处理,首先是打拍无法保证数据的正确,其次产生的使能信号位置不一定准确。最后还需要加个异步 FIFO 。需要注意的是,异步 FIFO 会有较长的 latency, 新的使能信号得做适当的延迟才能使用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值