FPGA中一个“被优化”的信号,让我白熬了两天——直到用了 AI工具
上周一位做 FPGA 开发的朋友找到我们语气非常着急。他说工程已经生成了 bitPS 侧通过 BRAM 接口往 PL 写数据总线 Debug 抓到的波形完全正确。但数据进入控制解析模块后再传到目标 RTL 模块时ad9361_cfg_done这个信号始终拉不起来。我加了(* dont_touch true *)也没用。打开实现后的原理图发现 CDC 原语的输入引脚直接接地。可 RTL 里明明连接得好好的。项目催得很紧我已经熬了两天实在没办法了。他的工程规模不小每次重新综合、实现、生成 bit都要等待半个小时左右。两天里他反复修改代码、重新跑实现、烧录验证前后试了好多轮。真正消耗他的不只是一个 Bug。而是每一次错误判断背后都要付出半小时甚至更久的等待成本。一、最初的判断地址译码被常量折叠了用户首先怀疑ps_ctrl_addr[13]可能被综合工具优化成了常数导致控制解析模块的地址使能始终无效最终造成ad9361_cfg_done 1无法被正常写入。这个判断并不离谱。在 FPGA 工程中如果某一位地址信号没有真正参与有效逻辑或者上游连接存在问题综合工具确实可能进行常量传播和逻辑折叠。一旦地址译码逻辑被折叠相关控制信号就可能在实现后的网表中“消失”。于是他开始沿着这个方向排查检查顶层端口连接对比各级模块中的地址位宽手动追踪实现后网表给关键信号添加dont_touch反复重新综合、实现和烧录。但问题始终没有解决。大型工程中的实现后网表包含成千上万个 cell 和 net。只靠 Vivado 原理图手动追踪很容易在层层重命名和优化后的逻辑中迷失方向。更关键的是他的排查方向从一开始就错了。问题根本不在地址译码。二、RepoKey 介入先确认“信号到底还在不在”我们先让他使用 AI RepoKey 的工程上下文摘要能力对项目进行快速扫描。RepoKey 很快提取出与当前问题最相关的几个文件top.v system.bd control_decode_top.v cat_input_lvds_pll.v随后RepoKey attach 到他已经打开的 Vivado 实现任务impl_1并直接查询ps_ctrl_addr[13]在实现后网表中的真实状态。结果很快出来了ps_ctrl_addr[13]并没有被综合优化。它仍然真实存在并且驱动了读数据 MUX 中的多个 LUT进入了控制解析模块在实现后网表中保留了完整的功能连接。之所以用户在原理图中难以辨认是因为 Vivado 对部分 pin 和 net 进行了重命名。名字变了但连接没有断。这一步直接排除了用户两天以来最怀疑的问题地址译码逻辑没有被常量折叠ps_ctrl_addr[13]也没有消失。既然前半段链路正常问题就只能继续向后查。三、沿着 CDC 原语真正的问题浮出水面接下来AI 引导用户把注意力从地址译码转移到ad9361_cfg_done_cdc_inst这个xpm_cdc_array_single原语上。RepoKey 查询该原语的实现后网表连接得到了一组非常关键的信息src_clk net (empty) src_in[0] net (empty) syncstages_ff_reg[0][0]/D - ZERO这意味着CDC 的源时钟没有连接到有效 netCDC 的源数据也没有形成有效输入第一级同步寄存器的 D 端被直接固定为ZERO。此时问题已经非常清楚了。我们立刻回到top.v检查该 CDC 原语的例化代码xpm_cdc_array_single #( .DEST_SYNC_FF (2), .INIT_SYNC_FF (0), .SIM_ASSERT_CHK (0), .SRC_INPUT_REG (1), .WIDTH (1) ) ad9361_cfg_done_cdc_inst ( .dest_out (ad9361_cfg_done_cdc), .dest_clk (sdr_clk), .src_clk (ctrl_clk), // 问题在这里 .src_in (ad9361_cfg_done) );问题就出在这一行.src_clk (ctrl_clk)继续追踪后发现ctrl_clk在顶层文件中早已被注释掉。但由于 Verilog 默认允许隐式 wirectrl_clk并没有立即触发明显的编译错误而是变成了一个未驱动的隐式信号。综合时这个未驱动信号被视为常数0。于是整个问题链条变成了ctrl_clk 未驱动 ↓ CDC 源时钟固定为 0 ↓ CDC 内部寄存器无法采样 ↓ ad9361_cfg_done_cdc 固定输出 0 ↓ 用户在实现后原理图中看到 CDC 输入接地所以用户看到的“CDC 输入接地”并不是因为ad9361_cfg_done被综合工具优化掉了。真正原因是CDC 原语根本没有拿到有效的源时钟。这也解释了为什么添加(* dont_touch true *)完全无效。dont_touch可以阻止部分逻辑被优化或重构但它无法挽救一个根本没有驱动源的时钟信号。四、修复只改一行问题解决修复方式非常简单。把错误的.src_clk (ctrl_clk)改为工程中真实存在的控制时钟.src_clk (ps_ctrl_clk)同时我们还发现控制解析模块存在一个地址位宽不一致的问题。原来的连接是.ctrl_addr (ps_ctrl_addr[12:0])但模块端口实际定义为[13:0]因此一并修改为.ctrl_addr (ps_ctrl_addr[13:0])完整修复后重新执行综合 → 实现 → 生成 bit → 烧录验证一次通过。实现后再次检查 CDC 原语src_clk已连接到有效时钟src_in不再为空同步寄存器输入不再固定为ZEROad9361_cfg_done可以正常拉高。从 RepoKey attach 工程到定位真正根因整个过程不到 15 分钟。实际用于工程扫描和关键信号定位的 Token 只有几千远低于用户最初担心的“让 AI 读取大型工程会消耗天文数字 Token”。五、为什么一个不复杂的问题会让人白熬两天复盘整个过程真正拖慢排查的不是问题本身而是以下四点。1. 一开始就选错了排查方向用户看到地址使能异常下意识怀疑地址位被优化。这个假设虽然合理但没有先通过实现后网表确认就直接进入了反复修改和跑 bit 的循环。对于一个跑一次 bit 需要半小时的工程错误方向的每一次尝试都非常昂贵。2. 大型工程中Vivado 原理图很难手动导航实现后的cell 名称pin 名称net 名称层级结构都可能经过重命名、折叠或重构。当工程规模足够大时手动追踪一个信号很容易变成“大海捞针”。3. 真正的问题藏在思维盲区里谁会第一时间想到一个 CDC 原语的源时钟竟然接到了一个已经被注释掉的信号而且这个信号因为隐式 wire 的存在没有立刻以明显错误的形式暴露出来。仿真阶段它还可能被初始化值、测试激励或模型行为暂时掩盖。直到实现后查看网表才发现 CDC 内部已经被固定为常数输出。4. 用户担心 AI 太耗 Token反而付出了更高成本用户一直担心让 AI 读取这么大的 Vivado 工程会不会消耗非常多 Token所以他想先靠自己解决。结果节省下来的可能只是几块钱的 Token 成本却付出了两天时间多次无效实现数小时等待高强度熬夜项目延期风险。RepoKey 并不是把整个工程、所有源码、所有报告全部塞给 AI。它会先提取工程结构、关键上下文和网表证据再把真正需要分析的信息交给 AI。这也是为什么大型工程依然可以用较低的 Token 成本完成定位。写在最后问题解决后这位用户感慨了一句早知道一开始就用工具两天时间够我做多少事了。对于 FPGA 开发者来说真正稀缺的从来不只是算力也不是 Token。而是时间。一个需要半小时才能跑完 bit 的工程每一次错误方向的尝试都在持续消耗开发周期。RepoKey 的设计初衷就是让 AI 不再靠“盲读整个工程”来猜问题而是通过工程上下文、Vivado 状态和实现后网表证据快速看清项目的真实状态。RepoKey 现在免费开放目前已在 Vivado 2017.42023.2 的多个版本中完成验证。你可以使用 RepoKey一键扫描 Vivado 工程结构快速定位关键文件Attach 到已经打开的综合或实现任务查询任意信号、cell、pin 和 net 的真实网表连接通过自然语言向 AI 提问用更少的 Token快速定位大型 FPGA 工程问题。别再让你的两天消耗在错误方向上。上RepoKey 官网看详情本文由 RepoKey 团队原创转载请注明出处。