概述
异步信号同步化,是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_RST与XPM_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_*所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复