第三章 鉴频鉴相器PFD设计

鉴频鉴相器,简称PFD,是PLL中我最喜欢的一个模块。为什么?因为它虽然结构简单,却藏着不少设计上的门道。说白了,PFD就是PLL的“眼睛”——它负责比较参考时钟和反馈时钟的相位差、频率差,然后告诉后面的电荷泵该怎么调整。

我个人习惯把PFD看作一个“三态判决器”。它输出三个状态:UP、DOWN,或者什么都不做。UP表示反馈时钟慢了,需要加速;DOWN表示反馈时钟快了,需要减速;都不输出,说明锁定了。

3.1 PFD的工作原理

先说说最基本的PFD结构。它由两个D触发器和一些组合逻辑组成。每个D触发器的时钟端分别接参考时钟和反馈时钟,数据端都接高电平。触发器的输出经过一个与门后,复位两个触发器。

工作过程是这样的:

  • 参考时钟上升沿到来,UP信号拉高
  • 反馈时钟上升沿到来,DOWN信号拉高
  • 当UP和DOWN同时为高,与门输出复位信号,两个触发器同时清零

你想想看,如果参考时钟领先于反馈时钟,那么UP信号就会比DOWN信号宽。这个宽度,正好等于两个时钟的相位差。电荷泵根据这个宽度来充电,VCO的控制电压就会上升,频率跟着提高。

反过来也一样。反馈时钟领先,DOWN信号更宽,电荷泵放电,VCO频率降低。

我在项目中遇到过一个问题:当参考时钟和反馈时钟频率不同时,PFD也能正常工作。这就是“鉴频”能力的来源。频率高的时钟,它的上升沿来得更频繁,对应的输出信号就会持续占主导,直到频率拉平为止。

核心要点:PFD同时具备鉴相和鉴频能力。锁定状态下,UP和DOWN都是窄脉冲,宽度等于复位延迟。这个窄脉冲宽度,就是后面要说的死区问题的根源。

3.2 死区问题及消除方法

死区,这是PFD设计里最让人头疼的问题。什么叫死区?就是当相位差非常小的时候,PFD“看不见”这个误差,不输出任何调整信号。

为什么会这样?

原因在于复位路径的延迟。当UP和DOWN同时为高时,与门输出复位信号,这个复位信号需要经过一些门电路才能清零触发器。如果相位差小于这个复位延迟,那么UP和DOWN还没来得及产生有效宽度,就被复位了。

我曾经在一个2.4GHz的PLL项目中吃过这个亏。仿真时一切正常,流片回来发现锁定后的相位噪声比预期差了10dB。查了整整两周,最后定位到是死区问题。PFD在锁定状态下根本不响应微小相位误差,导致VCO的控制电压纹波过大。

警告:死区会导致PLL锁定后的相位噪声恶化。更严重的是,它可能造成PLL永远无法精确锁定,始终在目标频率附近来回摆动。

消除死区的方法,业内主流做法是:在复位路径上故意增加延迟。

具体来说,就是在与门输出到触发器复位端之间,插入几个反相器或缓冲器。这样做的目的是:即使相位差为零,UP和DOWN也会产生一个最小宽度的脉冲。这个脉冲宽度由复位延迟决定,通常设计为几百皮秒到几纳秒。

我建议的最小脉冲宽度设计原则:

PLL工作频率 建议最小脉冲宽度 复位延迟单元数
< 100 MHz 2-3 ns 4-6级反相器
100 MHz - 1 GHz 500 ps - 1 ns 2-4级反相器
> 1 GHz 100-300 ps 1-2级反相器

注意,这个最小脉冲宽度不能太大。太宽了,电荷泵每次都会充放电,造成控制电压纹波增大,同样会恶化相位噪声。这是个trade-off,需要根据具体应用来权衡。

设计技巧:我个人习惯在复位路径上使用可编程延迟链。这样可以在芯片测试时调整最小脉冲宽度,找到最优值。虽然面积会大一点,但调试起来方便很多。

3.3 PFD的电路实现

好了,理论说完了,来看看实际电路怎么搭。下面是一个经典的PFD电路结构:

// PFD核心电路(Verilog描述)
module pfd (
    input  clk_ref,    // 参考时钟
    input  clk_fb,     // 反馈时钟
    input  rst_n,      // 异步复位
    output up,         // UP信号
    output down        // DOWN信号
);

reg up_reg, down_reg;
wire reset;

// 两个D触发器
always @(posedge clk_ref or negedge rst_n) begin
    if (!rst_n)
        up_reg <= 1'b0;
    else if (reset)
        up_reg <= 1'b0;
    else
        up_reg <= 1'b1;
end

always @(posedge clk_fb or negedge rst_n) begin
    if (!rst_n)
        down_reg <= 1'b0;
    else if (reset)
        down_reg <= 1'b0;
    else
        down_reg <= 1'b1;
end

// 复位逻辑(带延迟消除死区)
assign reset = up_reg & down_reg;

// 延迟链(消除死区)
// 实际电路中用缓冲器实现
// delay_chain #(.STAGES(4)) u_delay (.in(reset), .out(reset_delayed));

assign up   = up_reg;
assign down = down_reg;

endmodule

这个代码看起来简单,但实际流片时要注意几个地方:

  • 复位信号的同步问题:复位信号直接清零触发器,如果复位路径上的延迟不一致,可能导致UP和DOWN的脉冲宽度不对称
  • 毛刺抑制:组合逻辑输出的复位信号可能有毛刺,建议在复位路径上加一个简单的滤波电路
  • 版图布局:两个D触发器要尽量靠近,减少走线延迟差异

下面我画了一张PFD的工作状态图,帮你理清整个逻辑:

PFD工作状态转换图 空闲状态 UP=0, DOWN=0 UP状态 UP=1, DOWN=0 DOWN状态 UP=0, DOWN=1 参考时钟上升沿 反馈时钟上升沿 复位(UP&DOWN) 复位(UP&DOWN) 异常:反馈时钟先到 注:虚线表示异常情况,正常锁定时不会出现

这张图展示了PFD的三个状态和转换关系。正常锁定时,PFD在空闲状态和UP/DOWN状态之间来回切换。如果相位差很小,UP和DOWN几乎同时出现,然后立即复位回到空闲状态。

嗯,这里要注意:图中的虚线路径表示异常情况。比如在UP状态下,如果反馈时钟的上升沿先于参考时钟到达(这通常不会发生,因为UP状态是由参考时钟触发的),就会直接跳转到DOWN状态。实际电路中,这种路径很少用到,但设计时还是要考虑进去,防止毛刺导致误触发。

最后说一个我踩过的坑:PFD的复位信号一定要做异步处理。我曾经图省事,直接用组合逻辑的复位信号去清零触发器,结果在高速PLL中出现了严重的亚稳态问题。后来老老实实加了同步器,问题才解决。

好了,PFD的设计就讲到这里。记住三个关键词:三态输出、死区消除、复位延迟。把这三点吃透了,PFD设计基本不会出大问题。

本章小结:

  • PFD通过比较参考时钟和反馈时钟的上升沿,输出UP/DOWN信号
  • 死区由复位路径延迟引起,通过增加复位延迟可以消除
  • 最小脉冲宽度需要权衡死区消除和纹波噪声
  • 电路实现时注意复位同步和版图对称性

可可精品资料库