1. 为什么国产FPGA的PLL值得单独拿出来聊
这两年国产FPGA的讨论热度肉眼可见地涨起来了,尤其是易灵思(Efinix)这条线,Trion和Titanium两个系列在中小规模逻辑、低功耗场景、MIPI和LVDS接口应用里被越来越多的项目选中。我自己从T8、T20一路用到T35F324,再到后来接触Ti60F225,踩过的坑不算少,其中PLL配置这一块是最容易让新手翻车、也最容易被老手忽视的地方。
PLL锁相环在FPGA里承担的角色,说白了就是整个系统的“节拍器”。外部晶振给一个参考时钟,PLL把它倍频、分频、移相,生成内部各个模块需要的时钟域。你后面跑的SPI、I2C、MIPI、LVDS、图像处理流水线、定点数运算,全都建立在这个时钟质量之上。PLL没配好,后面全是白搭——时序收敛不了、接口误码率高、图像出马赛克、系统跑一会儿就死机,这些现象追到根上,十有八九是时钟的问题。
易灵思的PLL和Xilinx、Intel那套东西在思路上有相通的地方,但工具链Efinity的配置界面、参数命名、约束写法都有自己的脾气。很多从Xilinx转过来的朋友,习惯性地套用Vivado那套MMCM/PLL的经验,结果在Efinity里怎么调都不对。这篇内容就是把我自己在T35F324和Ti60F225上配置PLL的实战过程、参数计算、性能优化和排查经验完整梳理一遍,适合刚上手易灵思的工程师,也适合已经在用但PLL性能没调到位的朋友参考。
2. 易灵思PLL的架构与核心参数拆解
2.1 PLL在Trion/Titanium里的基本结构
易灵思的PLL模块在Trion系列里通常每个器件有4个PLL,Titanium系列根据型号不同数量有差异。每个PLL的核心结构包括参考时钟输入、预分频器(Pre-divider)、鉴相器(PFD)、电荷泵、环路滤波器、压控振荡器(VCO)、以及多路输出分频器。这个结构和大多数FPGA的PLL是一致的,但易灵思在参数范围和约束方式上有自己的特点。
参考时钟进来之后,先经过一个预分频器,把外部时钟降到PFD能接受的频率范围。PFD把参考时钟和反馈时钟做相位比较,输出误差信号给电荷泵,电荷泵驱动环路滤波器产生控制电压,控制VCO的频率。VCO的输出经过反馈分频器回到PFD形成闭环,同时经过各个输出分频器送到不同的时钟网络。
这里有个关键点:VCO的频率范围是有限制的。易灵思Trion系列的VCO典型工作范围在600MHz到1200MHz之间,Titanium系列会更高一些。你所有的倍频分频计算,最终都要保证VCO落在这个范围内,否则PLL要么锁不住,要么输出抖动大得没法用。
2.2 核心参数的计算逻辑
配置PLL本质上就是解一个方程。假设外部参考时钟频率为Fref,预分频系数为M,反馈分频系数为N,输出分频系数为O,那么:
- PFD频率:Fpfd = Fref / M
- VCO频率:Fvco = Fpfd × N = Fref × N / M
- 输出频率:Fout = Fvco / O = Fref × N / (M × O)
举个例子,T35F324上外部晶振是50MHz,我要生成一个100MHz的时钟给图像处理流水线用。那么我可以选M=1,N=20,O=10,这样Fvco = 50 × 20 / 1 = 1000MHz,落在VCO范围内,Fout = 1000 / 10 = 100MHz。也可以选M=2,N=40,O=10,Fvco还是1000MHz,效果一样。但不同的M/N组合,PFD频率不同,环路带宽和抖动特性会有差异。
提示:PFD频率不宜过低,一般建议在10MHz以上,否则锁定时间会变长,抖动也会变差。但也不能太高,超过PFD的最大工作频率就直接不工作了。
2.3 Efinity里PLL IP的配置界面
在Efinity里添加PLL是通过Interface Designer或者直接例化PLL原语来完成的。Interface Designer里有一个Clock PLL的配置向导,你输入参考时钟频率和期望的输出频率,工具会自动帮你算一组M/N/O参数。但自动算出来的不一定是最优的,有时候工具为了凑频率会选一个PFD频率很低的组合,导致抖动偏大。
我一般习惯手动指定参数,先把VCO频率定在一个比较高的值(比如1000MHz到1100MHz),然后反推M和N。VCO频率高一点,输出分频的选择余地大,抖动也相对好控制。Efinity的PLL配置界面里可以设置输出时钟的相位偏移,单位是皮秒或者度数,这个在做源同步接口的时候特别有用。
3. 从零开始配置一个可用的PLL
3.1 工程准备与时钟输入约束
假设你手上是一块T35F324的开发板,外部有一颗50MHz的有源晶振接在专用时钟输入引脚上。第一步是在Efinity里创建工程,选好器件型号T35F324,然后在Interface Designer里添加一个Clock PLL。
时钟输入引脚需要做位置约束和IO标准约束。易灵思的专用时钟输入引脚通常在Bank的特定位置上,具体要看器件的Pinout文档。在Efinity的约束文件(.xml格式)里,你需要指定这个引脚的位置和IO标准,比如:
<pin name="clk_in" location="A12" iostd="LVCMOS33"/>IO标准要根据你板子上的实际电平来选,3.3V的晶振就选LVCMOS33,2.5V就选LVCMOS25。选错了要么不工作,要么长期可靠性有问题。
3.2 PLL参数配置实操
在Interface Designer的PLL配置页面里,依次填入:
- 参考时钟频率:50 MHz
- 参考时钟容差:根据晶振规格填,一般填100 ppm或者50 ppm
- 期望输出频率:比如100 MHz
- 输出数量:根据你的设计需要,T35F324的PLL一般有4路输出
工具会自动算出一组参数。我实测下来,对于50MHz到100MHz这个需求,工具通常会给M=1,N=20,O=10,VCO=1000MHz。这个组合是合理的,PFD频率50MHz,在推荐范围内。
如果你需要多个不同频率的输出,比如同时要100MHz、50MHz、25MHz,那就在输出分频器那里分别设置O=10、O=20、O=40。注意所有输出都来自同一个VCO,所以VCO频率必须是所有输出频率的公倍数。1000MHz可以同时分频出100、50、25、200、125等频率,但分不出33MHz这种非整数分频的频率。
注意:易灵思PLL的输出分频器一般是整数分频,不支持小数分频。如果你需要33.33MHz这种频率,要么换一个VCO频率,要么用多个PLL。
3.3 锁定时间与复位逻辑
PLL配置好之后,上电需要一个锁定过程。Efinity的PLL IP会输出一个locked信号,这个信号在PLL锁定之前是低电平,锁定之后拉高。你的设计里必须用这个locked信号来复位后续的逻辑,否则PLL还没稳定,后面的电路就开始跑,行为不可预测。
我一般的做法是把locked信号打两拍同步到PLL输出时钟域,然后用这个同步后的信号作为后续逻辑的复位释放条件。这样做的原因是locked信号是异步的,直接拿来用会有亚稳态风险。
reg [1:0] locked_sync; always @(posedge clk_out or negedge locked) begin if (!locked) locked_sync <= 2'b00; else locked_sync <= {locked_sync[0], 1'b1}; end wire rst_n = locked_sync[1];这段代码的意思是,locked拉低时同步寄存器清零,locked拉高后经过两个时钟周期,rst_n才释放。这样后续逻辑的复位释放是同步的,避免了亚稳态传播。
4. 性能优化:抖动、相位与功耗的平衡
4.1 抖动来源分析与抑制
PLL的输出抖动主要来自几个方面:参考时钟本身的抖动、PFD和电荷泵的噪声、VCO的相位噪声、电源噪声。参考时钟的抖动你控制不了,只能选一个好晶振。VCO的相位噪声和VCO频率有关,一般来说VCO频率越高,相位噪声越差,但分频到目标频率后抖动会被分频比改善。
这里有个反直觉的地方:VCO频率高,绝对抖动可能变大,但经过大分频比之后,输出频率低,相对抖动(周期抖动的百分比)反而可能更好。所以选VCO频率的时候要综合考虑。
电源噪声对PLL的影响特别大。易灵思的PLL电源引脚通常有专门的VCCAUX和VCCPLL,这些引脚上的去耦电容一定要按推荐值放,一般是一个0.1uF加一个10uF,尽量靠近引脚。我遇到过因为PLL电源去耦没做好,导致输出时钟抖动大,下游LVDS接收误码率居高不下的情况。后来在PLL电源引脚旁边补了一个1uF的电容,误码率直接降了一个数量级。
4.2 相位偏移的精确控制
易灵思PLL支持输出时钟的相位偏移,这个功能在源同步接口里非常关键。比如你用FPGA输出一个时钟给外部ADC,同时输出数据,外部ADC用这个时钟来采样数据。如果时钟和数据之间的相位关系不对,采样窗口就可能落在数据跳变沿上,导致采样错误。
Efinity的PLL配置里可以设置每个输出的相位偏移,单位可以是皮秒或者度数。我一般先用0度相位跑一遍,用示波器或者逻辑分析仪看数据和时钟的实际相位关系,然后根据建立保持时间的要求来调整。比如数据在时钟上升沿之后2ns稳定,那我把时钟相位往后调2ns左右,让采样点落在数据稳定区的中间。
提示:相位偏移的精度受限于PLL的VCO周期。VCO频率1000MHz时,一个VCO周期是1ns,相位偏移的步进大概是1ns/8或者更细,具体看器件的相位偏移分辨率。
4.3 动态重配置与低功耗场景
有些应用场景需要在运行过程中切换时钟频率,比如低功耗模式下降频,高性能模式下升频。易灵思的部分PLL支持动态重配置,可以通过APB接口或者专用配置端口在运行时修改M/N/O参数。
动态重配置的流程一般是:先让PLL进入旁路或者停止输出,修改分频参数,等待PLL重新锁定,然后恢复输出。这个过程需要小心处理,因为重配置期间输出时钟是不稳定的,下游逻辑必须处于复位状态。
在低功耗场景下,如果某个时钟域暂时不用,可以把对应的PLL输出关掉,而不是让PLL一直跑着。易灵思的PLL支持输出使能控制,关掉不用的输出可以省一些功耗。但要注意,关掉输出再打开,需要等PLL重新锁定,不是瞬间就能用的。
5. 常见问题排查与实战避坑记录
5.1 PLL不锁定或锁定不稳定
这是最常见的问题。现象是locked信号一直不拉高,或者拉高之后又掉下去。排查思路按优先级来:
| 排查项 | 可能原因 | 解决方法 |
|---|---|---|
| 参考时钟 | 晶振没起振、频率不对、电平不匹配 | 用示波器测晶振输出,确认频率和幅度 |
| 电源 | PLL电源引脚电压不对、去耦不足 | 测VCCPLL电压,补去耦电容 |
| 参数 | VCO频率超出范围、PFD频率过低 | 重新计算M/N/O,确保VCO在范围内 |
| 约束 | 时钟输入引脚约束错误 | 检查.xml约束文件里的引脚位置和IO标准 |
| 复位 | PLL复位信号一直有效 | 检查复位逻辑,确保复位释放 |
我遇到过一次PLL不锁定,查了半天发现是晶振的负载电容焊错了,导致晶振频率偏了差不多1%,PLL的参考时钟容差设的是100ppm,直接超出范围锁不住。换了对的电容就好了。所以晶振这一块千万别想当然,该测就测。
5.2 输出时钟抖动大导致下游误码
这个问题的表现是接口能工作但误码率高,或者图像处理出现随机噪点。用示波器看时钟波形,会发现抖动明显偏大。原因通常是VCO频率选得太低,或者PFD频率太低,或者电源噪声大。
我的经验是,VCO频率尽量选在范围的中高段,比如Trion系列选1000MHz到1100MHz。PFD频率尽量在25MHz到50MHz之间。电源去耦一定要做好,PLL电源引脚旁边至少放一个0.1uF和一个1uF的电容,地平面要完整。
5.3 多时钟域之间的相位关系不对
当你的设计里有多个时钟域,而且它们之间有数据交互时,时钟之间的相位关系就很重要。比如一个时钟域写FIFO,另一个时钟域读FIFO,如果两个时钟同源但相位不对,FIFO的读写指针可能同时变化,导致亚稳态。
解决办法是让所有相关时钟都来自同一个PLL,这样它们之间的相位关系是确定的。然后在跨时钟域的地方用同步器或者异步FIFO。易灵思的Efinity里有时钟域交叉的检查工具,可以帮你找出潜在的亚稳态风险点。
5.4 动态重配置后PLL失锁
动态重配置的时候,如果参数改得太猛,比如VCO频率一下子从1000MHz跳到600MHz,PLL可能失锁。我的做法是分步改,先改输出分频,再改反馈分频,每次改完等锁定再改下一步。另外重配置期间一定要把下游逻辑复位,不然会出现不可预测的行为。
6. 从PLL延伸到系统级时钟规划
6.1 时钟树与全局时钟资源
易灵思FPGA的全局时钟资源是有限的,T35F324大概有十几个全局时钟网络。PLL的输出要接到全局时钟缓冲器上,才能低偏斜地分布到整个芯片。如果你把PLL输出直接接到普通IO或者局部时钟网络上,偏斜会很大,时序很难收敛。
在Efinity里,PLL输出到全局时钟的连接一般是自动的,但你要注意不要超过全局时钟资源的数量。如果设计里时钟太多,可以考虑用时钟使能或者门控时钟来减少同时活跃的时钟数量。
6.2 时钟域交叉与复位同步
多时钟域设计里,复位同步是个容易被忽视的问题。异步复位信号如果直接接到多个时钟域的触发器上,复位释放的时候可能在不同时钟域里发生在不同的时刻,导致状态机跑飞。
正确的做法是每个时钟域都有自己的复位同步器,把异步复位同步到各自的时钟域。易灵思的Efinity里有一些复位同步的参考设计,可以直接拿来用。
6.3 与其他国产FPGA的对比思考
我用过高云和安路的FPGA,PLL的配置思路大同小异,但工具链的成熟度和参数范围有差异。易灵思的Efinity在PLL配置的自动化程度上做得不错,但手动调参的灵活性也很高。高云的PLL配置更接近Xilinx的风格,安路的则有自己的特色。
选哪个平台,除了PLL本身,还要看整体工具链、IP生态和技术支持。易灵思在MIPI和LVDS这些高速接口上的IP比较成熟,如果你做图像处理或者视频接口,易灵思是个不错的选择。
7. 几个我踩过的坑和实测有效的技巧
第一个坑是PLL的参考时钟引脚选错了。易灵思的专用时钟输入引脚和普通IO引脚在电气特性上有区别,专用时钟引脚到PLL的路径更短,抖动更小。我一开始把晶振接到普通IO上,PLL也能锁,但抖动明显比接到专用时钟引脚上大。后来看文档才发现这个问题,换到专用引脚后抖动改善了差不多30%。
第二个坑是PLL输出分频器的顺序。易灵思的PLL输出分频器有的是级联的,有的是独立的。如果你需要两个频率成整数倍关系的输出,比如100MHz和50MHz,最好用同一个VCO的不同输出分频器,而不是用100MHz再分频得到50MHz。前者两个时钟的相位关系是确定的,后者会引入额外的分频器延迟。
第三个技巧是关于PLL的锁定时间。易灵思的PLL锁定时间一般在几十微秒到几百微秒之间,具体取决于环路带宽和参考时钟频率。如果你的系统对启动时间有要求,可以适当增大环路带宽来加快锁定,但代价是抖动会变大。这是一个权衡,没有免费午餐。
第四个技巧是仿真。Efinity支持PLL的行为仿真,你可以在仿真里看到锁定过程、输出时钟的相位关系。虽然仿真不能完全反映实际抖动,但至少能验证参数配置对不对、锁定逻辑有没有问题。我一般在板子回来之前都会跑一遍PLL仿真,省得板子回来发现配置错了还要改。
最后一个经验是关于PLL的电源。易灵思的PLL对电源噪声比较敏感,如果板子上有DC-DC开关电源,尽量让PLL的电源来自LDO,或者在DC-DC输出后面加一级LC滤波。我在一个项目里因为PLL电源和数字电源共用了一个DC-DC,结果PLL输出抖动一直下不来,后来单独给PLL加了一个LDO,问题就解决了。这个改动在PCB设计阶段就要考虑,板子做回来再改就麻烦了。