
IDELAYCTRL 是 Xilinx FPGA(特别是支持高速 I/O 的系列,如 Virtex-5/6/7、Kintex-7、Artix-7、Spartan-6/7 等)中用于管理和校准输入延迟模块(IDELAYE2/IDELAYE3)的必须存在的参考时钟控制模块。
IDELAYCTRL 的主要功能是为 IDELAY 模块提供精确的延迟校准。 IDELAY(输入延迟单元)是一个可以以 ~78ps(32 步进)或 ~11ps(512 步进) 的精度对输入信号进行延迟调整的硬件原语。 但是这种延迟的精度依赖于一个参考时钟(REFCLK),该时钟的频率决定了每一步延迟的实际时间。 IDELAYCTRL 模块的作用就是持续监控和校准 IDELAY 的延迟步进,使其不随 PVT(工艺、电压、温度)变化而漂移。 简单说:没有 IDELAYCTRL,IDELAY 的延迟量将不可预测。
IDELAYCTRL 需要一个稳定且频率匹配的参考时钟 REFCLK REFCLK 频率要求: 对于 IDELAYE2(7系列、Virtex-6等): REFCLK 必须为 200 MHz(如果延迟步进为 78ps) 或 300 MHz(如果延迟步进为 52ps,仅部分型号支持)。 通常 200 MHz 对应 78ps 步进,300 MHz 对应 52ps 步进。 但 7 系列中,实际步进为 78ps(200MHz) 或 ~52ps(300MHz),具体需查手册。 对于 IDELAYE3(UltraScale/UltraScale+): 支持更多频率,步进可为 ~10ps 到 ~50ps,需根据选择的步进配置对应频率。 校准机制: IDELAYCTRL 内部包含一个环形振荡器和校准电路,它通过比较 REFCLK 周期与延迟链的传播时间,动态调整 IDELAY 单元的步进,使其保持恒定。
IDELAYCTRL 用于以下场合: 高速源同步接口(如 DDR、LVDS 接收) 比特对齐(通过调整不同 bit 的延迟实现通道对齐) 时序收敛(调整建立/保持时间余量) 通常与 IDELAYE2/IDELAYE3 和 ISERDESE2/ISERDESE3 结合使用。
一个 IDELAYCTRL 可服务多个 IDELAY: 在同一个区域(通常是一个 Bank 或几个相邻 Bank)内的所有 IDELAY 可以共享一个 IDELAYCTRL 实例。 跨区域需多个 IDELAYCTRL: 不同时钟区域(Clock Region)或不同 IDELAY 类型可能需要独立的 IDELAYCTRL。 必须提供稳定 REFCLK: REFCLK 必须来自全局时钟资源(如 MMCM/PLL 输出),并且频率精确。 上电后需等待 RDY 信号: IDELAYCTRL 启动后需要一段时间校准,完成后输出 RDY 信号为高,之后才能使用 IDELAY。
IDELAYCTRL #(
.SIM_DEVICE("7SERIES") // 对于 7 系列,Virtex-6 为 "VIRTEX6"
)
idelayctrl_inst (
.RDY(rdy_out), // 输出:校准就绪信号,高有效
.REFCLK(refclk), // 输入:参考时钟(200 MHz)
.RST(rst) // 输入:复位,高有效,初始化校准
);
idelayctrl_inst : IDELAYCTRL
generic map (
SIM_DEVICE =>"7SERIES"
)
port map (
RDY => rdy_out,
REFCLK => refclk,
RST => rst
);
在典型设计中: 使用一个 MMCM/PLL 产生精确的 200 MHz 参考时钟。 将该时钟连接到 IDELAYCTRL 的 REFCLK。 将 IDELAYCTRL 的 RDY 信号作为系统中 IDELAY 模块使能的条件(或作为系统复位释放条件)。 同一区域的所有 IDELAYE2 共享此 IDELAYCTRL。
必须使用 IDELAYCTRL: 只要使用了 IDELAYE2/IDELAYE3,就必须例化并正确连接 IDELAYCTRL,否则延迟值会随环境变化,导致接口不稳定。 REFCLK 频率必须精确: 如果 REFCLK 频率偏差大,校准后的延迟步进误差也会增大。 复位和就绪: 上电或复位后,需等待 RDY 变高才能使用 IDELAY。
// 1. 先产生 200 MHz 参考时钟(例如从 100 MHz 系统时钟倍频)
clk_wiz_inst (
.clk_in1(sys_clk),
.clk_out1(refclk_200m) // 200 MHz
);
// 2. 实例化 IDELAYCTRL
IDELAYCTRL idelayctrl_inst (
.RDY(rdy),
.REFCLK(refclk_200m),
.RST(~pll_locked) // PLL 锁定时释放复位
);
// 3. 使用 IDELAYE2(需要延迟的输入信号)
IDELAYE2 #(
.DELAY_SRC("IDATAIN"),
.IDELAY_TYPE("VAR_LOAD"), // 或 "FIXED", "VARIABLE"
.IDELAY_VALUE(0),
.REFCLK_FREQUENCY(200.0)
)
idelaye2_inst (
.IDATAIN(data_in),
.DATAOUT(data_delayed),
.C(refclk_200m), // 时钟,用于加载新延迟值
.CE(ce),
.INC(inc),
.LD(load),
.LDPIPEEN(1'b0),
.CNTVALUEIN(cntvaluein), // 动态加载的延迟值
.CNTVALUEOUT(cntvalueout),
.REGRST(1'b0)
);
// 4. 在系统中,确保在 rdy 为高后才使能 IDELAY 操作
// 时钟生成
clk_wiz_inst u_clk_wiz (
.clk_in1(sys_clk),
.clk_out1(refclk_200m),
.locked(pll_locked)
);
// IDELAYCTRL 实例化
wire idelayctrl_rdy;
IDELAYCTRL u_idelayctrl (
.RDY(idelayctrl_rdy),
.REFCLK(refclk_200m),
.RST(~pll_locked)
);
// 等待 IDELAYCTRL 就绪
reg idelay_ready;
always @(posedge refclk_200m) begin
idelay_ready <= idelayctrl_rdy;
end
// IDELAYE2 实例化
wire [4:0] cntvalueout;
IDELAYE2 #(
.DELAY_SRC("IDATAIN"),
.IDELAY_TYPE("VAR_LOAD"),
.IDELAY_VALUE(0),
.REFCLK_FREQUENCY(200.0)
) u_idelaye2 (
.IDATAIN(data_in),
.DATAOUT(data_delayed),
.C(refclk_200m),
.CE(idelay_ready ? ce_signal :1'b0), // 门控 CE
.INC(inc_signal),
.LD(idelay_ready ? load_signal : 1'b0), // 门控 LD
.LDPIPEEN(1'b0),
.CNTVALUEIN(cntvaluein),
.CNTVALUEOUT(cntvalueout),
.REGRST(~idelay_ready) // 未就绪时复位
);
// 示例:在就绪后加载初始延迟值
reg load_init;
always @(posedge refclk_200m) begin
if (~idelay_ready) begin
load_init <= 1'b0;
cntvaluein <=5'b0;
end else if (idelay_ready && ~load_init) begin
// 第一次就绪时加载默认延迟
load_init <= 1'b1;
cntvaluein <=5'b01000; // 8个步进,约624ps
load_signal <= 1'b1;
end else begin
load_signal <=1'b0;
// ... 正常操作
end
end
必须等待 RDY:在 RDY 为高之前,不应操作 IDELAYE2 门控控制信号:CE、LD 等信号应在 RDY 有效后才使能 位管理:可以使用 ~RDY 作为 REGRST 或系统复位条件
上电时序:整个系统应等待 PLL_LOCKED + IDELAYCTRL_RDY 后才开始工作。
- -THE END- -