ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FPGA调试:SignalTap卡在waiting for clock的根因与排查

FPGA调试:SignalTap卡在waiting for clock的根因与排查 1. SignalTap 调试卡在 waiting for clock 的本质拆解1.1 这个报错到底在说什么SignalTap 的waiting for clock是 FPGA 调试里出现频率极高的一类状态提示。它的字面意思是SignalTap 的采集逻辑已经加载进 FPGA但采样时钟一直没有跳变所以采样缓冲区永远是空的波形窗口里什么都看不到。很多人第一次遇到会以为是 SignalTap 坏了、JTAG 断了、或者 Quartus 版本有问题其实绝大多数情况下问题出在时钟本身没有真正跑起来或者SignalTap 采样时钟选错了源。SignalTap 的工作原理可以类比成一台“挂在时钟上的高速摄像机”。它需要有一个稳定的时钟沿来触发采样每来一个有效沿就抓一组信号值存进片上 RAM。如果这个时钟压根没动摄像机就一直处于“等开机信号”的状态界面上自然显示waiting for clock。所以排查的核心思路只有一句话先确认采样时钟在物理上是否真的在翻转再确认 SignalTap 是否接对了这个时钟。1.2 为什么这个问题在 Quartus 里特别常见Quartus 的 SignalTap 与综合、布局布线、下载流程是深度耦合的。它不像纯仿真那样可以随意给时钟激励而是必须依赖真实硬件上已经存在的时钟网络。常见触发场景有这么几类采样时钟来自 PLL 输出但 PLL 因为参考时钟、复位、锁定条件不满足而没有输出采样时钟来自外部晶振引脚但引脚约束写错时钟根本没进 FPGA采样时钟是内部逻辑分频出来的但分频逻辑被综合优化掉了采样时钟频率太低SignalTap 的采样深度和触发条件设置不合理看起来像“没反应”工程里存在多个时钟域SignalTap 选了一个根本没被使用的时钟。这几种情况在现象上都表现为waiting for clock但根因完全不同。下面我按实际调试中最常踩的顺序把三种典型“姿势”逐一拆开讲。1.3 排查前必须建立的三个基本认知在动手改工程之前先把这三个认知刻进脑子里能省掉大量无效折腾。第一SignalTap 的采样时钟必须是真实存在的、在硬件上持续翻转的时钟。它不能是仿真里的initial激励也不能是综合器“假设存在”但实际被裁掉的信号。第二PLL 没有锁定下游时钟大概率是死的。很多工程把 PLL 的locked信号当作复位释放条件如果locked一直为低整个逻辑都处于复位状态时钟即使有输出逻辑也不工作SignalTap 抓到的也只是一堆复位值。第三引脚配置错误是“隐形杀手”。Quartus 的引脚约束文件如果没写对时钟信号可能被分配到普通 IO 上或者被分配到错误的 bank导致时钟根本进不来。这个问题在初学者工程里尤其常见。2. 三种常见姿势逐一击破2.1 姿势一PLL 未锁定导致采样时钟停摆这是最经典的一种情况。工程里用了一个 PLL 把外部晶振倍频到系统时钟SignalTap 的采样时钟直接选了这个 PLL 的输出。下载后 SignalTap 一直waiting for clock但 JTAG 连接正常器件也能识别。根因分析PLL 的输出时钟是否翻转取决于三个条件——参考时钟是否有效、PLL 是否使能、PLL 是否锁定。很多设计里PLL 的areset信号接了一个外部复位或者内部复位逻辑如果这个复位一直有效PLL 就不会工作。还有一种情况是参考时钟引脚约束错误PLL 的输入时钟压根没进来。排查步骤在 SignalTap 里临时把采样时钟改成外部晶振的原始时钟而不是 PLL 输出。如果改成原始时钟后能抓到波形说明问题出在 PLL 这一级。用 SignalTap 抓 PLL 的locked信号。如果locked一直为低说明 PLL 没有锁定。检查 PLL 的参考时钟引脚约束。在 Quartus 的 Pin Planner 里确认输入时钟引脚是否分配到了专用的时钟输入引脚如CLKIN或GCLK引脚。检查 PLL 的复位逻辑。如果areset是高有效确认它在上电后已经被释放。实操心得我遇到过好几次 PLL 不锁定的情况最后发现是参考时钟频率设置和实际晶振不匹配。比如板子上是 50MHz 晶振但 PLL 配置里写的是 25MHzPLL 自然锁不了。这种问题在 Quartus 的 PLL IP 配置界面里很容易看漏建议每次改 PLL 参数后都重新核对一遍输入频率。注意PLL 的locked信号不要直接用作 SignalTap 的采样时钟它只是一个状态指示不是时钟。采样时钟必须选真正的时钟信号。2.2 姿势二采样时钟选错源或时钟被综合优化第二种常见情况是 SignalTap 的采样时钟选了一个“看起来存在但实际不翻转”的信号。比如选了一个内部逻辑产生的使能信号、一个分频后的低频时钟、或者一个被综合器优化掉的中间信号。根因分析Quartus 在综合和布局布线时会对没有被实际使用的信号进行优化。如果一个时钟信号只被 SignalTap 引用而没有驱动任何实际逻辑综合器可能会把它裁掉导致 SignalTap 采样时钟悬空。另外如果采样时钟频率太低比如几 Hz 的分频信号SignalTap 的采样深度很快就会被填满但波形更新极慢看起来也像“卡住”。排查步骤在 SignalTap 的 Setup 页面确认采样时钟选的是哪个信号。优先选择全局时钟网络上的信号比如 PLL 输出、专用时钟引脚输入的信号。如果采样时钟是内部逻辑产生的检查这个逻辑是否被综合优化。可以在 Quartus 的 Compilation Report 里查看 “Analysis Synthesis” 部分的 “Messages”搜索 “removed” 或 “optimized away” 关键词。如果采样时钟频率很低考虑改用更高频的时钟作为采样时钟然后在触发条件里用低频信号作为触发使能。在 SignalTap 里勾选 “Clock Mode” 为 “Continuous”确保采样时钟持续工作。实操心得我一般会在 SignalTap 里同时挂两个时钟——一个高频系统时钟作为采样时钟一个低频信号作为触发条件。这样既能保证采样率又能抓到低频事件。另外如果怀疑某个时钟被优化掉了可以在代码里加一个(* keep *)属性强制综合器保留这个信号。提示Quartus 的(* keep *)和(* preserve *)属性可以防止信号被优化但不要滥用否则会影响时序和资源。2.3 姿势三引脚配置错误导致时钟根本没进来第三种情况最隐蔽也最容易让人抓狂。工程编译下载都正常但 SignalTap 就是waiting for clock。最后发现是引脚约束文件里时钟引脚被分配错了。根因分析FPGA 的时钟输入引脚通常是专用的比如某些 bank 的CLK引脚。如果引脚约束写错时钟信号可能被分配到普通 IO 上或者被分配到错误的 bank导致时钟信号无法进入全局时钟网络。还有一种情况是引脚电平标准设置错误比如时钟引脚配置成了 LVCMOS 1.8V但实际板子是 3.3V信号幅度不够时钟无法被正确识别。排查步骤打开 Quartus 的 Pin Planner确认时钟输入引脚是否分配到了专用的时钟输入引脚。可以查看器件手册里的引脚定义确认哪些引脚支持时钟输入。检查引脚的电平标准是否与板子实际电平匹配。在 Pin Planner 里查看 “I/O Standard” 列。检查引脚约束文件.qsf里是否有冲突的引脚分配。比如同一个引脚被分配了两次或者时钟引脚被分配成了普通 IO。用示波器或逻辑分析仪测量时钟引脚确认物理上有时钟信号。实操心得我踩过最大的一个坑是工程里用了两个时钟输入引脚但引脚约束文件里只写了一个另一个被 Quartus 自动分配到了普通 IO 上。结果那个时钟一直进不来SignalTap 自然抓不到。后来养成习惯每次新建工程后第一件事就是打开 Pin Planner 核对所有时钟引脚。注意不同系列的 FPGA 时钟引脚位置不同一定要查对应器件的手册不要凭经验猜。3. 引脚配置避坑指南与实操流程3.1 引脚约束文件的正确写法Quartus 的引脚约束通常写在.qsf文件里也可以通过 Pin Planner 图形界面配置。不管用哪种方式核心信息就三样引脚号、电平标准、信号名。下面是一个典型的时钟引脚约束示例set_location_assignment PIN_R8 -to clk_50m set_instance_assignment -name IO_STANDARD 3.3-V LVTTL -to clk_50m第一行把clk_50m分配到PIN_R8第二行设置电平标准为 3.3V LVTTL。这两行缺一不可。如果只写了引脚号没写电平标准Quartus 会用默认值可能和板子不匹配。对于差分时钟写法略有不同set_location_assignment PIN_A10 -to clk_in_p set_location_assignment PIN_A11 -to clk_in_n set_instance_assignment -name IO_STANDARD LVDS -to clk_in_p set_instance_assignment -name IO_STANDARD LVDS -to clk_in_n差分时钟需要同时约束正负两个引脚电平标准也要对应设置。3.2 引脚分配检查清单每次工程编译前建议按下面这个清单过一遍检查项正确做法常见错误时钟引脚位置分配到专用时钟输入引脚分配到普通 IO电平标准与板子实际电平一致用默认值或写错电压引脚冲突每个引脚只分配一次同一引脚多次分配差分对正负引脚成对分配只分配一个未使用引脚设置为三态或接地悬空导致干扰这个清单看起来简单但实际调试中至少有一半的waiting for clock问题都能在这里找到答案。3.3 从工程创建到 SignalTap 抓波形的完整流程下面按顺序走一遍完整流程每一步都标注了容易出问题的地方。第一步确认硬件时钟源。先看板子原理图确认外部晶振频率、连接到哪个引脚、电平标准是什么。这一步不能省很多问题就是从这里开始的。第二步创建 Quartus 工程并配置器件。选择正确的器件型号这一步如果选错后续引脚分配全对不上。第三步编写顶层代码并例化 PLL。PLL 的输入频率要和晶振一致输出频率根据系统需求设置。例化时注意areset和locked的处理。第四步分配引脚。用 Pin Planner 或直接编辑.qsf文件把时钟、复位、关键 IO 都分配好。分配完后再核对一遍。第五步编译工程。编译完成后查看 Compilation Report确认没有严重警告特别是时钟相关的警告。第六步插入 SignalTap。在 Quartus 里打开 SignalTap设置采样时钟为系统时钟添加要观察的信号设置触发条件。第七步重新编译并下载。SignalTap 插入后需要重新编译工程然后通过 Programmer 下载.sof文件。第八步运行 SignalTap 并观察波形。如果一切正常应该能看到波形刷新。如果还是waiting for clock回到前面三种姿势逐一排查。3.4 PLL 配置中的关键参数计算PLL 的配置直接决定了采样时钟是否存在。以常见的 50MHz 输入、100MHz 输出为例计算过程如下输入频率50MHz目标输出频率100MHz倍频系数 M 输出频率 / 输入频率 100 / 50 2实际工程中PLL 的配置参数还包括 VCO 频率范围、分频系数等Quartus 的 PLL IP 会自动计算但需要确认最终输出频率是否正确。在 Quartus 的 PLL IP 配置界面里重点看三个数输入频率、倍频系数、输出频率。这三个数必须和实际硬件匹配。如果输入频率写错PLL 要么不锁定要么输出频率完全不对。提示PLL 的locked信号建议引出一个 LED 或者测试点方便上电时快速判断 PLL 是否正常工作。4. 常见问题速查与独家避坑技巧4.1 问题速查表现象可能原因快速验证方法解决方法waiting for clockPLL 未锁定抓 locked 信号检查参考时钟和复位waiting for clock采样时钟选错换外部晶振时钟试试改选全局时钟waiting for clock引脚分配错误查 Pin Planner重新分配引脚波形不刷新触发条件太严改触发条件为 always放宽触发条件波形只有复位值逻辑处于复位抓复位信号释放复位SignalTap 无响应JTAG 连接问题重新扫描器件检查下载线4.2 独家避坑技巧技巧一先用最简单的工程验证硬件。如果怀疑板子或引脚有问题先写一个最简单的呼吸灯工程只用一个时钟和一个 LED。如果呼吸灯能正常工作说明时钟和引脚没问题问题在 SignalTap 配置上。如果呼吸灯都不亮那问题就在硬件或引脚约束上。技巧二SignalTap 采样时钟优先选全局时钟。全局时钟网络上的信号质量最好抖动最小。内部逻辑产生的时钟虽然也能用但容易受到布局布线的影响。技巧三触发条件从宽到严。刚开始调试时触发条件设成always或者最简单的电平触发先确保能抓到波形再逐步加严触发条件。很多人一上来就设复杂的触发序列结果一直抓不到白白浪费时间。技巧四保存多个 SignalTap 配置文件。不同的调试阶段可能需要不同的采样时钟和信号组合建议把常用的配置保存成不同的.stp文件需要时直接加载。技巧五注意 SignalTap 的采样深度和 RAM 资源。采样深度设得太大会占用大量片上 RAM可能导致布局布线失败或者时序不满足。一般建议从 1K 或 2K 开始够用就行。4.3 一个真实的调试案例之前有个项目用的是 Cyclone 系列 FPGA外部 50MHz 晶振PLL 倍频到 100MHz 作为系统时钟。SignalTap 采样时钟选了 100MHz但一直waiting for clock。排查过程如下先抓 PLL 的locked信号发现一直为低。检查 PLL 配置输入频率写的是 50MHz没问题。检查引脚约束发现晶振引脚分配到了普通 IO 上不是专用时钟引脚。重新分配到专用时钟引脚重新编译下载PLL 锁定SignalTap 正常抓波形。这个案例说明引脚配置错误是waiting for clock的一个非常隐蔽的原因。如果一开始就检查引脚分配能省掉大量排查时间。4.4 关于 Quartus 版本和器件的补充说明不同版本的 Quartus 在 SignalTap 的界面和操作上略有差异但核心逻辑是一样的。Quartus II 13.x、Quartus Prime 18.1、Quartus Prime Lite 20.1 等版本我都用过waiting for clock的排查思路完全一致。需要注意的是新版本 Quartus 对某些老器件的支持可能有限如果用的是老器件建议用对应的老版本 Quartus。另外器件库的安装也很重要。如果器件库没装全编译时可能会报错或者 SignalTap 无法正确识别器件。建议安装 Quartus 时把常用的器件库都勾上。5. 从根源上减少 waiting for clock 的设计习惯5.1 时钟树规划要提前做很多waiting for clock问题根源在于设计初期没有规划好时钟树。建议在写代码之前先画一张时钟树图标明每个时钟的来源、频率、去向。这样在插入 SignalTap 时就能快速找到合适的采样时钟。时钟树规划的核心原则是全局时钟走全局网络局部时钟走局部网络跨时钟域信号要同步。全局时钟网络上的信号驱动能力强、抖动小适合作为 SignalTap 的采样时钟。5.2 复位逻辑要干净复位逻辑混乱是 PLL 不锁定的常见原因。建议采用同步复位、异步释放的复位策略确保上电后复位信号能可靠释放。如果复位信号一直有效PLL 不工作下游时钟全死SignalTap 自然抓不到。一个干净的复位逻辑示例reg [3:0] rst_cnt 4d0; wire rst_n rst_cnt; always (posedge clk or negedge ext_rst_n) begin if (!ext_rst_n) rst_cnt 4d0; else if (!(rst_cnt)) rst_cnt rst_cnt 1b1; end这段代码用计数器实现上电复位延时确保 PLL 有足够时间锁定后再释放复位。5.3 调试接口要预留在 PCB 设计阶段建议预留一些调试测试点比如关键时钟、复位、PLL 锁定信号。这样在调试时可以直接用示波器测量快速判断信号是否正常。如果没有测试点就只能靠 SignalTap 盲猜效率低很多。5.4 养成编译后检查报告的习惯Quartus 编译完成后Compilation Report 里有很多有用信息。重点看这几项Analysis Synthesis Messages看有没有信号被优化掉Fitter Messages看引脚分配有没有警告Timing Analyzer看时序是否满足Resource Utilization看资源占用是否合理。这些信息能帮助提前发现潜在问题减少调试时的意外。我个人在实际操作中的体会是waiting for clock这个问题看起来吓人但排查思路其实很清晰先确认时钟在物理上是否存在再确认 SignalTap 是否接对了时钟最后检查引脚和 PLL 配置。把这三点按顺序过一遍九成以上的问题都能解决。剩下的那一成多半是工程配置或者器件兼容性的问题换个版本或者重新建工程往往就能解决。最后再分享一个小技巧如果实在找不到原因可以新建一个最简单的工程只包含时钟和 SignalTap逐步把原工程的模块加进来直到问题复现。这种“二分法”排查虽然笨但非常有效。
返回列表