我是靠谱客的博主 清新花生,最近开发中收集的这篇文章主要介绍单bit信号跨时钟域处理及时序约束前言一、RTL实现方式二、使用原语实现三、使用Xilinx原语xpm_*,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

异步信号同步化,是FPGA使用中独有的特点,也是逻辑工程时在进行代码编写时,应该特别需要注意的地方。本文章只介绍单比特缓变信号的跨时钟域转换。

前言

所谓的缓变信号是指满足奈圭斯特采样定律的信号。

缓变的单BIT信号进行跨时钟域转换常采用两级及以上D触发器打拍的方式解决,但为了保证编译器能够遵守编程者的意愿,跨时钟域转换代码编写往往需要一些编程技巧,下面以Xilinx的应用平台为例进行介绍。

一、RTL实现方式

module async_in (
	 input	wire		src_in          
	,input	wire		dest_clk
	,output	wire		dest_out
);
//==============================================================================================
//======                                  define signal                                 ========
//==============================================================================================
	(* ASYNC_REG="TRUE" *)		reg	[2:0]	sreg	;
//==============================================================================================
//======                                  initial	                                 	========
//==============================================================================================
	initial begin
		sreg = 3'b000;
	end
//==============================================================================================
//======                                  behave of RTL                                 ========
//==============================================================================================

	always@(posedge dest_clk)begin
		sreg <= {sreg[1:0], src_in};
	end

	assign dest_out = sreg[2];
  
endmodule   

说明:ASYNC_REG 是影响 Vivado 工具流程中许多进程的属性。 该属性的目的是通知工具,某个寄存器能够在 D 输入引脚中接收相对于源时钟的异步数据,或者该寄存器是同步链中的同步寄存器。 Vivado 综合,遇到这种情况时 属性将其视为 DONT_TOUCH 属性并将 ASYNC_REG 属性在网表中向前推送。 此过程可确保具有 ASYNC_REG 属性的对象不会被优化掉,并且流程中稍后的工具会收到该属性以正确处理它。

“ASYNC_REG”属性对实现的影响

在这里插入图片描述
可以看到有“ASYNC_REG”属性时,综合工具实现后,与我们预期的目标设计相同。

二、使用原语实现

module async_cdc(
	 input 	wire	src_in
	,input	wire	dest_clk
	,output	wire	dest_out
);
//==============================================================================================
//======                                  define signal                                 ========
//==============================================================================================
	(* keep = "TRUE" *)wire 	data_sync1;
	(* keep = "TRUE" *)wire 	data_sync2;
//==============================================================================================
//======                                  behave of RTL                                 ========
//==============================================================================================
	(* ASYNC_REG *) 
	(* BOX_TYPE = "PRIMITIVE" *) 
	(* SHREG_EXTRACT = "no" *) 
	(* XILINX_LEGACY_PRIM = "FD" *) 
	FDRE #(
		.INIT		(1'b0		)
	)data_sync_reg1(
		 .C			(dest_clk	)
        ,.CE		(1'b1		)
        ,.D			(src_in		)
        ,.Q			(data_sync1	)
        ,.R			(1'b0		)
	);
	//---------------------------------------------------------//
	(* ASYNC_REG *) 
	(* BOX_TYPE = "PRIMITIVE" *) 
	(* SHREG_EXTRACT = "no" *) 
	(* XILINX_LEGACY_PRIM = "FD" *) 
	FDRE #(
		.INIT		(1'b0		)
	)data_sync_reg2(
		 .C			(dest_clk	)
        ,.CE		(1'b1		)
        ,.D			(data_sync1	)
        ,.Q			(data_sync2	)
        ,.R			(1'b0		)
	);
	//---------------------------------------------------------//
	(* ASYNC_REG *) 
	(* BOX_TYPE = "PRIMITIVE" *) 
	(* SHREG_EXTRACT = "no" *) 
	(* XILINX_LEGACY_PRIM = "FD" *) 
	FDRE #(
		.INIT		(1'b0		)
	)data_sync_reg3(
		 .C			(dest_clk	)
        ,.CE		(1'b1		)
        ,.D			(data_sync2	)
        ,.Q			(dest_out	)
        ,.R			(1'b0		)
	);

endmodule

使用该模块时,可以在XDC文件中约束一下异步时钟路径,约束语法如下:

set_false_path -to [get_cells -hierarchical -filter {NAME =~ *data_sync_reg1}]

三、使用Xilinx原语xpm_*

xilinx强大的生态环境,给FPGA用户提供了许多库函数,其中包括用于异步信号同步化的XPM_CDC库,其中包括:
在这里插入图片描述
注意:
XPM_CDC_SYNC_RSTXPM_CDC_ASYNC_RST不同,两个模块均用于复位的同步化,但XPM_CDC_ASYNC_RST输出的复位信号在断言时,与目标时钟域是异步的,释放是同步的;而XPM_CDC_SYNC_RST的复位断言和释放均与目标时钟域同步。

以下为Verilog下XPM_CDC_*模块例化的模板:

	//-----------------------------------------------------------//
	// xpm_cdc_async_rst: Asynchronous Reset Synchronizer
	//-----------------------------------------------------------//	
	xpm_cdc_async_rst #(
		.DEST_SYNC_FF		(4),
		.INIT_SYNC_FF		(0),
		.RST_ACTIVE_HIGH	(0)
	)
	xpm_cdc_async_rst_inst (
		.src_arst			(power_reset	),
		//-------------------------------------//
		.dest_clk			(clk_300m		),	
		.dest_arst			(sync_reset		)
	);

//----------------------------------------------//
// xpm_cdc_single: Single-bit Synchronizer
//----------------------------------------------//   
   xpm_cdc_single #(
		.DEST_SYNC_FF		(4				), // DECIMAL; range: 2-10
		.INIT_SYNC_FF		(0				), // DECIMAL; 0=disable simulation init values, 1=enable simulation init values
		.SIM_ASSERT_CHK		(0				), // DECIMAL; 0=disable simulation messages, 1=enable simulation messages
		.SRC_INPUT_REG		(1				)  // DECIMAL; 0=do not register input, 1=register input
   ) xpm_cdc_sync_inst0 (
		.src_clk			(src_clk		),
		.src_in				(src_in			),
		//-------------------------------------//
		.dest_clk			(dest_clk		),
		.dest_out			(dest_out		)
   ); 

//----------------------------------------------//
// xpm_cdc_array_single: Single-bit Array Synchronizer
//----------------------------------------------//    
	xpm_cdc_array_single #(
		.DEST_SYNC_FF		(4				),// DECIMAL; range: 2-10
		.INIT_SYNC_FF		(0				),// DECIMAL; 0=disable simulation init values, 1=enable simulation init values
		.SIM_ASSERT_CHK		(0				),// DECIMAL; 0=disable simulation messages, 1=enable simulation messages
		.SRC_INPUT_REG		(1				),// DECIMAL; 0=do not register input, 1=register input
		.WIDTH				(2				) // DECIMAL; range: 1-1024
	)xpm_cdc_array_single_inst (
		.src_clk			(src_clk		),
		.src_in				(src_in			),
		//-------------------------------------//
		.dest_clk			(dest_clk		),   
		.dest_out			(dest_out		)
	);

//----------------------------------------------//
// xpm_cdc_handshake: Bus Synchronizer with Full Handshake
//----------------------------------------------//
	xpm_cdc_handshake #(
		.DEST_EXT_HSK		(0				),// DECIMAL; 0=internal handshake, 1=external handshake
		.DEST_SYNC_FF		(4				),// DECIMAL; range: 2-10
		.INIT_SYNC_FF		(0				),// DECIMAL; 0=disable simulation init values, 1=enable simulation init values
		.SIM_ASSERT_CHK		(0				),// DECIMAL; 0=disable simulation messages, 1=enable simulation messages
		.SRC_SYNC_FF		(4				),// DECIMAL; range: 2-10
		.WIDTH				(1				) // DECIMAL; range: 1-1024
	)xpm_cdc_handshake_inst (
		.src_clk			(src_clk		),//input 					
		.src_send			(src_send		),//input
		.src_in				(src_in			),//input
		.src_rcv			(src_rcv		),//output
		
		.dest_clk			(dest_clk		),//output
		.dest_req			(dest_req		),//output
		.dest_out			(dest_out		),//output
		.dest_ack			(dest_ack		),//input
   );

最后

以上就是清新花生为你收集整理的单bit信号跨时钟域处理及时序约束前言一、RTL实现方式二、使用原语实现三、使用Xilinx原语xpm_*的全部内容,希望文章能够帮你解决单bit信号跨时钟域处理及时序约束前言一、RTL实现方式二、使用原语实现三、使用Xilinx原语xpm_*所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(44)

评论列表共有 0 条评论

立即
投稿
返回
顶部