赞
踩
异步信号同步化,是FPGA使用中独有的特点,也是逻辑工程时在进行代码编写时,应该特别需要注意的地方。本文章只介绍单比特缓变信号的跨时钟域转换。
所谓的缓变信号是指满足奈圭斯特采样定律的信号。
缓变的单BIT信号进行跨时钟域转换常采用两级及以上D触发器打拍的方式解决,但为了保证编译器能够遵守编程者的意愿,跨时钟域转换代码编写往往需要一些编程技巧,下面以Xilinx的应用平台为例进行介绍。
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”属性时,综合工具实现后,与我们预期的目标设计相同。
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强大的生态环境,给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 );
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。