牛客刷题总结——跨时钟域处理

本文介绍了在SoC设计中如何正确处理异步时钟,包括单bit和多bit跨时钟域的数据传输方法,重点讲解了避免亚稳态和确保数据稳定性的方法,如脉冲同步与多bitDMUX同步器的应用。
摘要由CSDN通过智能技术生成

在做SoC设计中,免不了包含异步时钟,那就需要进行正确的跨时钟域处理来保证数据在不同时钟域传输不出错。

一、亚稳态

当bclk的时钟正好采到aclk下data变化的边沿,就会产生亚稳态。

二、单bit跨时钟域处理

1. 快时钟域到慢时钟域

因为慢时钟域采快时钟域的信号可能采不到,所以需要将快时钟域的信号进行脉冲展宽之后再用慢时钟域的时钟采样。

脉冲同步:将时钟域clk_a下的脉冲转化为时钟域clk_b下的脉冲。要求时钟域clk_a下的脉冲必须为一个单时钟脉冲。

原理:将时钟域clk_a下的单脉冲信号pulse_a转化为电平信号pulse_inv,然后在时钟域clk_b下对该电平信号进行异或边沿检测便得到时钟域clk_b下的脉冲信号pulse_b,采用三级寄存器进行边沿检测,可以防止亚稳态传播。

`timescale 1ns/1ns

module pulse_detect(
	input 				clk_fast	, 
	input 				clk_slow	,   
	input 				rst_n		,
	input				data_in		,

	output  		 	dataout
);


reg data_inv;
reg data_reg1;
reg data_reg2;
reg data_reg3;

//脉冲信号转为电平信号
always@(posedge clk_fast or negedge rst_n)
	if(!rst_n)
		data_inv <= 1'b0;
	else if(data_in)
		data_inv <= ~data_inv;

//打拍降低亚稳态
always@(posedge clk_slow or negedge rst_n)
	if(!rst_n)begin
		data_reg1 <= 1'b0;
		data_reg2 <= 1'b0;
		data_reg3 <= 1'b0;
	end else begin
		data_reg1 <= data_inv;
		data_reg2 <= data_reg1;
		data_reg3 <= data_reg2;
	end

//边沿检测
assign dataout = data_reg3^data_reg2;

endmodule

我们在使用这个模块时,无论对于快时钟域到慢时钟域还是慢时钟域到快时钟域,我们都要尽可能让data_inv的高电平持续时间大于等于2个clk_b周期,这样会得到正常的单脉冲输出。

三、多bit跨时钟域处理

1. 多bit DMUX同步器

该方法适合带数据有效标志信号的多bit数据做跨时钟域传输,原理框图如下:

数据有效信号为高电平时,说明此时数据也处于稳定状态,在这种情况下慢时钟域寄存器对信号进行采样,可以保证没有setup/hold违例。当同步过后的data_en作为mux的sel端,当其为1时,将aclk下的data输出给bclk下

对应题目:

在data_en为高期间,data_in将保持不变,data_en为高至少保持3个B时钟周期。表明,当data_en为高时,可将数据进行同步。

本题中data_in端数据变化频率很低,相邻两个数据间的变化,至少间隔10个B时钟周期。

`timescale 1ns/1ns

module mux(
	input 				clk_a	, 
	input 				clk_b	,   
	input 				arstn	,
	input				brstn   ,
	input		[3:0]	data_in	,
	input               data_en ,

	output reg  [3:0] 	dataout
);

reg data_en_a;
reg data_en_b_reg1;
reg data_en_b_reg2;
reg [3:0] data_reg;

//输入使能寄存
always@(posedge clk_a or negedge arstn)
	if(!arstn)
		data_en_a <= 0;
	else
		data_en_a <= data_en;

//使能信号打两拍
always@(posedge clk_b or negedge brstn)
	if(!brstn)begin
		data_en_b_reg1 <= 'b0;
		data_en_b_reg2 <= 'b0;
	end else begin 
		data_en_b_reg1 <= data_en_a;
		data_en_b_reg2 <= data_en_b_reg1;
	end 

//输入数据寄存
always@(posedge clk_a or negedge arstn)
	if(!arstn)
		data_reg <= 4'd0;
	else
		data_reg <= data_in;

//输出
always@(posedge clk_b or negedge brstn)
	if(!arstn)
		dataout <= 0;
	else if(data_en_b_reg2)
		dataout <= data_reg;


endmodule

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值