
做FPGA的都清楚时钟是整个设计的脉搏。这次我手头这块易灵思Trion T35F324板载晶振只有一路50MHz而项目里需要100MHz的主逻辑时钟和25MHz的串口采样时钟频率不够板子也没法换怎么办常规解法就是上PLL。易灵思的PLL和Xilinx/Altera的风格很不一样没有那么多弹窗选项所有配置集中在Efinity的Interface Planner里第一次用容易找不到入口更别提交到复位极性、反馈模式、专用时钟引脚这些细节。这篇文章把我从零开始配置T35F324内部PLL硬核的完整流程写下来包含参数填写、代码例化、时序约束以及我在实际调板过程中踩过的几个坑适合正在用易灵思做项目、或者准备从其他FPGA平台切过来的工程师参考照着操作基本能复现。1. 为什么自己配PLL之前先要搞懂这几件事1.1 易灵思T35F324的PLL资源长什么样T35F324属于易灵思Trion系列标称35K逻辑单元封装是FBGA-324也就是常说的F324封装。片上集成了专门的模拟PLL模块这类模块不占LUT资源所以官方叫它PLL硬核。它在Efinity里的完整名称是GPLL全称General Purpose PLL即通用锁相环。Trion T35系列根据数据手册内部有两个GPLL可以满足大部分多时钟场景。这个PLL的输入范围、VCO范围、输出分频范围都有严格限制配置前最好去官网下载对应器件的 datasheet翻到PLL章节看一眼。我记得T35系列的GPLL参考输入范围大致在几MHz到三百多MHz的区间VCO最高频率也不是无上限具体数字以你手里批次对应手册为准。最少要确认三件事输入晶振频率是否落在输入范围内、期望输出频率是否在VCO可覆盖范围、分频参数是否支持。如果这三条都不满足上层配置做得再漂亮也没用最终布局布线会报错。1.2 这次实战要达到的目标我这次的目标非常具体50MHz板载晶振输入需要产生两路输出时钟。一路100MHz给主状态机和图像处理模块跑另一路25MHz给UART的过采样逻辑用25MHz作为16倍波特率时钟。选择这个频率组合的原因是分频系数都比较整方便验证PLL配置是否存在误差。如果你手头的需求是生成普通整数分频倍数和我的步骤基本一致如果是小数分频或者动态相移操作界面中会多出对应参数原理仍然相通。这里要提一个实际经验不要一上来就把两路输出都接上一堆复杂逻辑先让PLL产生两个频率的时钟然后各自驱动一个LED闪烁或者计数器确认频率正常后再接业务模块。这个最小验证流程看着笨但能帮你把PLL问题、逻辑问题、约束问题分开排查省下不少调板时间。1.3 软件和硬件准备软件方面用易灵思官方的Efinity IDE我用的是2023年之后的版本界面布局相对稳定。安装之后除了主IDE还会安装综合、布局布线、编程器等组件不需要额外装ModelSimEfinity里可以调用第三方仿真器也可以用它自带的仿真流程。硬件方面我这边用的是一块自制的T35F324核心板板载50MHz有源晶振预留了PLL专用时钟引脚的排针方便示波器测量。没有核心板的话官方评估板也一样。2. Efinity里的PLL配置全流程2.1 建立工程并选对器件型号打开Efinity之后点击Create New Project填写工程名和路径进入器件选择界面。这里要注意Family选择TrionDevice选择T35Package选择F324Speed Grade这个参数往往容易被忽略。如果封装识别不对后面综合、管脚分配全都会乱。芯片丝印上通常写着T35F324C3或者T35F324I3C代表商业级温度范围I代表工业级选错不影响PLL配置本身但会直接影响时序分析的温度模型所以最好和实际芯片一致。工程建立后建议先把顶层RTL文件建出来。我习惯的方式是新建一个top.v顶层文件先把时钟输入端口、复位端口、LED端口定义好不用急着写逻辑等PLL模型生成后再例化进去。这样之后每一步验证都有个落脚点。2.2 用Interface Planner添加PLL易灵思没有把PLL配置放在独立的IP Catalog页面里而是集成在Interface Planner中。打开方式是在Efinity左侧工具窗口找到Interface Planner双击打开。如果你用的是新版本也可以在菜单栏的Tools下拉菜单中直接点Interface Planner。进入Interface Planner后左侧会有一个资源面板列出当前器件可用的PLL、GPIO、LVDS等资源。在工具栏找到“”号按钮点击后选择PLL界面会弹出PLL配置窗口。这个窗口的高频操作项不算多主要就是配置输入时钟、输出时钟、复位和锁定输出。它和Xilinx的Clocking Wizard是非常不一样的体验Interface Planner是让你在管脚分配和接口元素这个层面配置PLL再自动生成RTL模型而不是在纯IP配置界面里做完再让你自己去接线。我自己的操作顺序是先配置输入时钟再配置输出时钟最后处理复位和锁定信号。配置输入时钟时需要选择输入时钟源界面会列出当前已经分配到工程里的时钟引脚或时钟网络如果你还没有做任何管脚分配需要先在Interface Planner中添加一个GPIO或Clock输入元素把50MHz晶振接到对应的专用时钟引脚上。这里就必须强调一下PLL参考时钟必须连接到专门的时钟引脚普通GPIO引脚在物理上到PLL的布线路径不支持硬接会导致DRC报错。2.3 关键参数怎么填在PLL配置窗口里比较核心的参数是输入时钟频率、输出频率以及反馈模式。我的输入时钟填50MHz输出时钟添加两路第一路填100MHz第二路填25MHz。反馈模式我一般保持默认的NORMAL这种模式内部反馈路径自动补偿时钟树延迟适合绝大多数逻辑设计。还有一个外部反馈模式需要额外引脚反馈一般用在需要精确时钟对齐的特定场景普通同步逻辑用不到选错会平白占用引脚。界面里会有自动计算的参数显示比如倍频系数、分频系数、VCO频率。你填完100MHz和25MHz之后软件会自动找一组分频组合尽量让VCO频率落在合理区间。你可以观察一下系统计算出的VCO频率是多少如果提示超范围那就需要调整输出频率组合或者改用其他分频方案。比如你想要100MHz和125MHz若VCO算出来接近上限可以试试把两个输出频率对调或者插入一个中间参考分频让计算器重新收敛。复位和锁定选项我建议都勾选上。PLL复位信号的高有效还是低有效要看配置界面下方的参数列表不同版本可能不同。我用的版本默认高有效复位也就是rst为1时PLL处于复位状态锁相环不工作locked输出为低。锁定信号从低到高跳变意味着PLL已经锁定输出频率稳定。这个信号后期一般会接到逻辑复位的释放逻辑上做异步复位同步释放。2.4 生成IP模型并例化到顶层参数填完后点击窗口里的DRC检查按钮这时候Efinity会检查PLL输入引脚类型、输出频率范围、是否有资源冲突等问题。如果DRC报红色错误先别慌逐条看错误信息多数情况是输入时钟引脚没有放在专用时钟引脚上或者输出频率超范围。全部检查通过后保存配置再点击Generate Model软件会自动生成一个Verilog模型文件里面包含PLL的例化模板和全部参数。这个生成的模型文件一般会出现在工程目录下的ip文件夹或者gen文件夹中文件名类似pll_main_pll.v。你可以直接打开这个文件里面有一个完整的顶层模块端口就是clock_input、rst、locked、clk_out_0、clk_out_1这些。我一贯的做法是不手动修改这个生成模型而是把它当成一个黑盒例化到我的top.v里。例化代码如下pll_main u_pll_main ( .clock_input (clk_50m), .rst (pll_rst), .locked (pll_locked), .clk_out_0 (clk_100m), .clk_out_1 (clk_25m) );我当时在例化时还犯过一个低级错误以为rst端口可以直接接板级低有效复位信号结果PLL一直处于复位状态。实际上如果你板级复位是低有效需要在代码里做一次反相或者把参数里的RST_INV改成1。这个细节后面避坑部分会重点展开。3. 时序约束与仿真调试3.1 输入时钟和生成时钟的约束写法PLL模型生成只是一半另一半是SDC时序约束。Efinity在做时序分析时需要知道外部输入时钟的周期否则布局布线无法计算路径延迟。我习惯在工程中单独建一个top.sdc第一行先约束输入的50MHz时钟。create_clock -name clk_50m -period 20.000 -waveform {0 10.000} [get_ports clk_50m]这里period 20.000对应50MHzwaveform为0到10ns的上升沿。如果你的晶振是差分输出那约束方式会略有不同需要在输入端口上定义差分时钟对。对于PLL的输出时钟Efinity的Interface Planner在生成模型时通常会同时生成对应的时钟约束但不同版本处理方式可能不一样。为了确保时序分析完整覆盖PLL输出到逻辑的路径我也会在SDC中显式声明generated clock让工具知道这两路输出时钟的相位和分频关系。create_generated_clock -name clk_100m -source [get_ports clk_50m] -multiply_by 2 [get_pins u_pll_main/clk_out_0] create_generated_clock -name clk_25m -source [get_ports clk_50m] -divide_by 2 [get_pins u_pll_main/clk_out_1]有一点要注意get_pins的路径写法在不同的综合工具版本里可能有差异如果编译时报找不到引脚可以通过综合后的网表查看实际例化名。实在找不到准确引脚名时可以退一步只保留create_clockPLL输出依靠Efinity自动约束。从我的实践来看显式声明generated clock对最终时序收敛更有利特别是在多时钟域设计中尽量花几分钟把约束写完整。3.2 PLL仿真模型怎么跑拿到生成模型后我建议先做一轮功能仿真再上板测试不要跳步。在Efinity里跑仿真前需要把易灵思的仿真库路径配置好。如果你用ModelSim或者QuestaSim需要在库管理器里添加Efinity安装目录下的仿真库。如果你懒得配库也可以直接用Efinity自带的仿真界面步骤差不多。写testbench时要特别注意PLL复位行为。我的测试环境是这样设计的先给50MHz时钟然后把PLL复位信号拉高持续大约1微秒后拉低等待locked信号跳高。由于PLL锁定需要时间testbench里至少要跑几十微秒我见过有人只跑几百纳秒发现locked一直没拉高就以为PLL坏了其实只是时间不够。initial begin clk_50m 0; forever #10 clk_50m ~clk_50m; end initial begin pll_rst 1b1; #1000; pll_rst 1b0; end initial begin wait (pll_locked 1b1); #10000; $display(PLL locked and clocks running); $finish; end把生成的PLL模型、顶层逻辑、testbench一起加入仿真跑完后重点看clk_100m和clk_25m的频率是否为预期值。这里要留意功能仿真里的频率不一定能看出准确波形周期因为你看到的时钟沿跳变是否稳定取决于仿真器对PLL模型内部延迟参数的解析。如果仿真器和模型版本不匹配有可能出现时序异常属正常现象换一个仿真精度设置通常能解决。3.3 综合、布局布线和下载流程仿真通过后回到Efinity主界面运行Synthesis。综合完成后查看日志确认PLL是否被正确例化没有未连接的端口。接着运行Place Route等待布局布线完成。这一步最容易出现时序违例如果存在违例优先检查约束是否写对然后再看是不是PLL输出频率太高导致后端布线压力过大。布局布线通过后生成bitstream。T35F324的下载方式比较简单用易灵思的下载器连接JTAG在Efinity里打开Programmer选择生成的bit文件点击Program。下载完成后立刻用示波器或逻辑分析仪测PLL的锁定信号和输出时钟。通常上电后几十毫秒内locked会拉高输出时钟稳定建立。如果这时用示波器测量能看到干净的方波。4. 避坑指南我踩过的7个坑4.1 锁定信号一直不拉高这是我在第一次使用易灵思PLL时遇到的最典型问题。代码逻辑、引脚分配都看了好几遍输出就是没有时钟locked信号永远是0。后来查了生成模型的参数才发现PLL复位信号默认是高有效而我顶层复位设计是低有效板级复位按键按下去时是高电平平时是低电平正好让PLL一直处在复位状态。解决方式是加一个反相器或者把PLL生成的IP配置里的RST_INV参数改为1让复位信号变成低有效。这个细节在数据手册里写得并不显眼但实际项目里出问题概率极高。4.2 输出频率对不上还有一次配置界面明明写的是100MHz输出示波器测量却是99.9MHz偏差0.1MHz。这看起来像是晶振精度问题但折腾了一圈发现是配置界面里输入时钟频率填错了。我误把晶振丝印上的频率当成实际频率没看板子原理图上的实际标称真实晶振是66.666MHz而我在配置里填了50MHz导致PLL输出成了预期的1.333倍。因此拿到一块新板子第一步永远是用示波器实测晶振频率不要只看丝印。4.3 用了普通IO做PLL输入DRC直接报错这个问题最容易坑新手。FPGA内部PLL参考时钟输入不是随便一个GPIO都行的它必须经过专用的时钟引脚因为只有这些引脚在物理上连接到了PLL的时钟输入网络。我在一个早期项目中图省事把50MHz时钟接到了普通IO结果DRC直接报错说PLL输入时钟无效。解决方法是在原理图设计阶段就确认晶振连接到专用时钟引脚。如果板子已经做好那就只能飞线或者更换时钟源。4.4 仿真里PLL模型不工作PLL仿真模型不工作的原因通常是仿真库没配好。Efinity生成的PLL模型会调用易灵思的工艺库单元如果你在ModelSim里只添加了PLL模型文件没有添加对应仿真库仿真器会报找不到模块或者未知标识符。编译完仿真库之后还有另一个坑就是仿真精度设置不够。PLL内部有很多延迟参数如果你把timescale的精度设置为1nsPLL模型内部的皮秒级延迟会被舍入导致时序混乱表现为locked信号抖动或者输出时钟不连续。我把仿真精度调到1ps之后问题基本消失。4.5 修改PLL参数后忘记重新综合这个坑很隐蔽。Efinity的Interface Planner里改了PLL输出频率之后直接运行Place Route打开布线报告发现实际资源还是老样子模块占用的LUT数量也完全一致。原因是你只修改了Interface Planner里的配置没有重新生成PLL模型旧模型文件根本没有被替换。改了配置以后必须回到Interface Planner重新点击Generate Model然后回到主界面重新综合再布局布线流程不能跳过。4.6 PLL电源处理不好导致输出时钟抖动大板级问题往往比逻辑问题更让人头疼。PLL对电源噪声非常敏感我遇到过输出时钟抖动达到几百皮秒的情况一开始还以为是PLL配置问题后来发现是板卡上PLL电源引脚没有做好去耦。FPGA内部的PLL供电引脚VCC_PLL需要额外的滤波处理我在核心板上加了磁珠和10uF加0.1uF电容组合后抖动明显改善。如果你自己画板一定要留足去耦电容的位置并且尽量靠近引脚。4.7 输出时钟没有加约束导致时序收敛失败这里的情况是功能一切正常但综合布局布线之后时序报告一片红大量路径违例。排查到最后发现PLL输出时钟在SDC里没有定义。工具不知道100MHz和25MHz从哪里来所以不会对相关路径做约束但后端还是会把它们当成数据信号去布线结果时序一路飘红。解决办法就是前面提到的把generated clock约束补上让工具知道PLL输出是时钟并按指定频率分析。5. 常见问题速查表5.1 PLL配置问题速查现象可能原因解决方案locked不拉高复位极性接反检查RST_INV参数或代码取反输出频率是预期的倍数输入时钟频率填写错误用示波器实测晶振频率DRC报PLL输入无效输入没有接专用时钟引脚原理图确认时钟引脚分配仿真报找不到模块仿真库未添加添加Efinity仿真库并配置精度修改频率后bitstream不变没重新生成PLL模型重新Generate Model并综合输出抖动偏大VCC_PLL去耦不足加磁珠和电容检查PCB布局大量时序违例未定义PLL输出生成时钟补齐SDC约束重新布线5.2 一点实用经验总结配置PLL之前先把芯片的数据手册相关章节读一遍重点看PLL输入范围、VCO范围和复位极性。这个准备工作花不了十分钟但能避免大多数低级问题。Efinity的自动参数计算器在大多数情况下会给你一个能用的分频方案但最好自己心算一遍输入频率乘倍频系数再除分频系数是否等于输出频率。这个简单等式能帮你快速判断界面是否有误导信息。我每次新做一款易灵思FPGA板子时都会先建一个最小PLL工程把晶振输入频率和两路输出频率各验证一遍记录下VCO实际配置值然后才在这个基础上加业务逻辑。这个流程虽然看起来慢但后面所有设计都会受益于一个经过验证的时钟基础。做惯了Xilinx再上手易灵思的人最容易卡在PLL配置入口和复位极性这两个地方。其实理解了Interface Planner的整体思路之后你会发现这种先管脚后IP的方式反而更直观因为它把所有外部接口相关的元素集中在一个视图里RTL例化只是最后一步。最后再分享一个我个人的小习惯每次生成PLL模型我都会把生成文件复制一份到工程目录下的docs文件夹里防止后续软件升级或工程迁移时模型被误删。这个习惯帮我省过不少重配参数的时间。