介绍:vivado iodelay可以调整输入FPGA IO信号的延时,集成在芯片IOB内部以ps为单位。适用于外部输入信号时钟和数据由于走线延时不等长导致的不同步,可以通过给时钟或者数据加idelay单元,使得时钟能稳定的采集到数据。
在7系列的FPGA里,该原语名字为idelay2,用法如下所示。
CINVCTRL_SEL: 是否动态翻转时钟信号C的极性
DELAY_SRC:输入信号来源
IDATAIN:输入信号来自于端口(管脚输入的信号),输入数据信号要接在IDATAIN端口
DATAIN:输入信号来自于数据(内部的信号),用于级连延时链。输入信号要接在DATAIN 端口
IDELAY_TYPE有三种模式:
fixed:固定延时模式,通过调整输入IDELAY_VALUE数值可以实现不同挡位的延时效果。但是每次编译完延时就固定了。
VAR_LOADABLE:动态加载抽头值模式,可以在线调整延时大小,通过调整输入CNTVALUEIN的数值,可以实时的修改端口的延时状态。
SIGNAL_PATTERN:用于配置输入信号属性,不同类型信号路径上的抖动不同
CLOCK:时钟信号;
DATA:数据信号;
HIGH_PERFORMANCE_MODE:是否使用高性能模式减小抖动,会增加功耗。
IDELAYCTRL原语
IDELAYCTRL:使用IDELAY或者ODELAY,IDELAYCTRL必须被使用。因为IDELAY或者ODELAY的延迟精度是由IDELAYCTRL的输入时钟决定的,一般为200MHz。REFCLK输入时钟最好经过BUFG上全局时钟树。
用法如下所示:
wire ref_clock_bufg;
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYCTRL delayctrl (
.RDY (delay_locked),
.REFCLK (ref_clock_bufg),
.RST (!rst_n));
BUFG ref_clk_bufg (
.I (clk_200m),
.O (ref_clock_bufg));
/******************FIXED 模式*************************************/
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE2
# (
.CINVCTRL_SEL ("FALSE"), // TRUE, FALSE
.DELAY_SRC ("IDATAIN"), // IDATAIN, DATAIN
.HIGH_PERFORMANCE_MODE ("TRUE"), // TRUE, FALSE
.IDELAY_TYPE ("FIXED"), // FIXED, VARIABLE, or VAR_LOADABLE
.IDELAY_VALUE (CLK0_TAPS), // 0 to 31
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("CLOCK")) // CLOCK, DATA
idelaye2_clk0
(
.DATAOUT (dco_0_temp_delay), // Delayed clock
.DATAIN (1'b0), // Data from FPGA logic
.C (ref_clock_bufg),
.CE (1'b0),
.INC (1'b0),
.IDATAIN (dco_0_temp),
.LD (0),
.LDPIPEEN (1'b0),
.REGRST (1'b0),
.CNTVALUEIN (5'b00000),
.CNTVALUEOUT (),
.CINVCTRL (1'b0)
);
// FIXED 模式下级联延时链
wire dco_0_temp_delay1;
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE2
# (
.CINVCTRL_SEL ("FALSE"), // TRUE, FALSE
.DELAY_SRC ("DATAIN"), // IDATAIN, DATAIN
.HIGH_PERFORMANCE_MODE ("TRUE"), // TRUE, FALSE
.IDELAY_TYPE ("FIXED"), // FIXED, VARIABLE,orVAR_LOADABLE
.IDELAY_VALUE (CLK1_TAPS), // 0 to 31
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("CLOCK")) // CLOCK, DATA
idelaye2_clk2
(
.DATAOUT (dco_0_temp_delay1), // Delayed clock
.DATAIN (dco_0_temp_delay), // Data from FPGA logic
.C (ref_clock_bufg),
.CE (1'b0),
.INC (1'b0),
.IDATAIN (1'b0),
.LD (0),
.LDPIPEEN (1'b0),
.REGRST (1'b0),
.CNTVALUEIN (5'b00000),
.CNTVALUEOUT (),
.CINVCTRL (1'b0)
);
/****************** VAR_LOADABLE 模式*************************************/
genvar pin_count;
generate
for (pin_count = 0; pin_count < 5; pin_count = pin_count + 1) begin: pins
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE2
# (
.CINVCTRL_SEL ("FALSE"), // TRUE, FALSE
.DELAY_SRC ("IDATAIN"), // IDATAIN, DATAIN
.HIGH_PERFORMANCE_MODE ("TRUE"), // TRUE, FALSE
.IDELAY_TYPE ("VAR_LOAD"), // FIXED, VARIABLE, or VAR_LOADABLE
.IDELAY_VALUE (DATA0_TAPS), // 0 to 31
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("DATA")) // CLOCK, DATA
idelaye2_bus_adc0_l
(
.DATAOUT (data_in_p0_delay[pin_count]),
.DATAIN (1'b0), // Data from FPGA logic
.C (ref_clock_bufg),
.CE (1'b0),
.INC (1'b0),
.IDATAIN (data_in_p0[pin_count]), // Driven by IOB
.LD (1'b1),
.REGRST (1'b0),
.LDPIPEEN (1'b0),
.CNTVALUEIN (FIRST_IMAGE_DATA_NUM),
.CNTVALUEOUT (),
.CINVCTRL (1'b0)
);
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE2
# (
.CINVCTRL_SEL ("FALSE"), // TRUE, FALSE
.DELAY_SRC ("IDATAIN"), // IDATAIN, DATAIN
.HIGH_PERFORMANCE_MODE ("TRUE"), // TRUE, FALSE
.IDELAY_TYPE ("VAR_LOAD"), // FIXED, VARIABLE, or VAR_LOADABLE
.IDELAY_VALUE (DATA1_TAPS), // 0 to 31
.REFCLK_FREQUENCY (100.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("DATA")) // CLOCK, DATA
idelaye2_bus_adc1_l
(
.DATAOUT (data_in_p1_delay[pin_count]),
.DATAIN (1'b0), // Data from FPGA logic
.C (ref_clock_bufg),
.CE (1'b0),
.INC (1'b0),
.IDATAIN (data_in_p1[pin_count]), // Driven by IOB
.LD (1'b1),
.REGRST (1'b0),
.LDPIPEEN (1'b0),
.CNTVALUEIN (DATA_ADC2_DELAY),
.CNTVALUEOUT (),
.CINVCTRL (1'b0)
);
end
endgenerate
在ultrascare+系列FPGA中,idelay原语改为idelay3
用法如下所示:
wire delay_locked;
wire ref_clock_bufg;
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYCTRL #(
.SIM_DEVICE("ULTRASCALE") // Set the device version for simulation functionality (ULTRASCALE)
)
delayctrl (
.RDY (delay_locked),
.REFCLK (ref_clock_bufg),
.RST (!rst_n));
BUFG ref_clk_bufg (
.I (clk_200m),
.O (ref_clock_bufg));
wire [8:0] cntvout;
wire [8:0] cntvout_1;
genvar pin_count;
generate
for (pin_count = 0; pin_count < 5; pin_count = pin_count + 1) begin: pins
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE3 #(
.CASCADE("NONE"), // Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE)
.DELAY_FORMAT("TIME"), // Units of the DELAY_VALUE (COUNT, TIME)
.DELAY_SRC("IDATAIN"), // Delay input (DATAIN, IDATAIN)
.DELAY_TYPE("VAR_LOAD"), // Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD)
.DELAY_VALUE(1100), // Input delay value setting
.IS_CLK_INVERTED(1'b0), // Optional inversion for CLK
.IS_RST_INVERTED(1'b0), // Optional inversion for RST
.REFCLK_FREQUENCY(300.0), // IDELAYCTRL clock input frequency in MHz (200.0-800.0)
.SIM_DEVICE("ULTRASCALE_PLUS"), // Set the device version for simulation functionality (ULTRASCALE,
// ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1, ULTRASCALE_PLUS_ES2)
.UPDATE_MODE("ASYNC") // Determines when updates to the delay will take effect (ASYNC, MANUAL,
// SYNC)
)
idelaye2_bus_adc0_l (
.CASC_OUT(), // 1-bit output: Cascade delay output to ODELAY input cascade
.CNTVALUEOUT(cntvout), // 9-bit output: Counter value output
.DATAOUT(data_in_p0_delay[pin_count]), // 1-bit output: Delayed data output
.CASC_IN(1'b0), // 1-bit input: Cascade delay input from slave ODELAY CASCADE_OUT
.CASC_RETURN(1'b0), // 1-bit input: Cascade delay returning from slave ODELAY DATAOUT
.CE(1'b0), // 1-bit input: Active high enable increment/decrement input
.CLK(ref_clock_bufg), // 1-bit input: Clock input
.CNTVALUEIN(DATA_ADC2_DELAY), // 9-bit input: Counter value input
.DATAIN(1'b0), // 1-bit input: Data input from the IOBUF
.EN_VTC(1'b1), // 1-bit input: Keep delay constant over VT
.IDATAIN(data_in_p0[pin_count]), // 1-bit input: Data input from the logic
.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
.LOAD(1'b0), // 1-bit input: Load DELAY_VALUE input
.RST(1'b0) // 1-bit input: Asynchronous Reset to the DELAY_VALUE
);
(* IODELAY_GROUP = "selectio_wiz_1_group" *)
IDELAYE3 #(
.CASCADE("NONE"), // Cascade setting (MASTER, NONE, SLAVE_END, SLAVE_MIDDLE)
.DELAY_FORMAT("TIME"), // Units of the DELAY_VALUE (COUNT, TIME)
.DELAY_SRC("IDATAIN"), // Delay input (DATAIN, IDATAIN)
.DELAY_TYPE("VAR_LOAD"), // Set the type of tap delay line (FIXED, VARIABLE, VAR_LOAD)
.DELAY_VALUE(1100), // Input delay value setting
.IS_CLK_INVERTED(1'b0), // Optional inversion for CLK
.IS_RST_INVERTED(1'b0), // Optional inversion for RST
.REFCLK_FREQUENCY(300.0), // IDELAYCTRL clock input frequency in MHz (200.0-800.0)
.SIM_DEVICE("ULTRASCALE_PLUS"), // Set the device version for simulation functionality (ULTRASCALE,
// ULTRASCALE_PLUS, ULTRASCALE_PLUS_ES1, ULTRASCALE_PLUS_ES2)
.UPDATE_MODE("ASYNC") // Determines when updates to the delay will take effect (ASYNC, MANUAL,
// SYNC)
)
idelaye2_bus_adc1_l (
.CASC_OUT(), // 1-bit output: Cascade delay output to ODELAY input cascade
.CNTVALUEOUT(cntvout_1), // 9-bit output: Counter value output
.DATAOUT(data_in_p1_delay[pin_count]), // 1-bit output: Delayed data output
.CASC_IN(1'b0), // 1-bit input: Cascade delay input from slave ODELAY CASCADE_OUT
.CASC_RETURN(1'b0), // 1-bit input: Cascade delay returning from slave ODELAY DATAOUT
.CE(1'b0), // 1-bit input: Active high enable increment/decrement input
.CLK(ref_clock_bufg), // 1-bit input: Clock input
.CNTVALUEIN(DATA_ADC2_DELAY), // 9-bit input: Counter value input
.DATAIN(1'b0), // 1-bit input: Data input from the IOBUF
.EN_VTC(1'b1), // 1-bit input: Keep delay constant over VT
.IDATAIN(data_in_p1[pin_count]), // 1-bit input: Data input from the logic
.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
.LOAD(1'b0), // 1-bit input: Load DELAY_VALUE input
.RST(1'b0) // 1-bit input: Asynchronous Reset to the DELAY_VALUE
);
end
endgenerate