
上周在 ICLAD 2025 现场听完 HiVeGen 的 Best Paper 宣讲回来路上我一直在想一个问题为什么我们用大模型写 Verilog总感觉像在让一个很聪明但没受过正规训练的新人写代码他能在五分钟内给你交出一份能跑通的模块但你把整个芯片的架构需求丢给它时它却倾向于把所有东西都塞进一个超大代码块里。这个现象不是个例几乎每个把 AI 接入 RTL 流程的团队都撞到过这面墙。我刚用 ChatGPT 写代码时最常遇到的尴尬局面是生成一个 UART 模块它能像模像样地给你 200 行代码单独仿真完全没问题但当你让它生成一个带有多个子模块、需要分层管理的通信子系统时它依然给你一个扁平的单文件所有状态机、FIFO、控制逻辑全部平铺在一起那场面就像把一整套乐高城堡用一块塑料浇出来。HiVeGen 这篇论文好就好在它没在卷“生成更大规模的代码”而是把矛头直指这个最让人头疼的问题结构性与生成质量。标题里的“Hierarchical Verilog Generation”本质上就是给“乱糟糟一团”的 AI 生成代码立规矩。1. 被低估的元能力从“能跑”到“能被维护”之间有条代沟先聊聊背景。过去一年AI 辅助芯片设计这个方向突然变得很热闹GitHub 上有大量开源项目在尝试用大模型自动生成 RTL 代码。很多 Demo 做得很漂亮给一句自然语言描述就能生成一个能通过测试的加法器、FIFO 或者简单状态机。但这些 Demo 大多停留在“小模块验证”这个舒适区。你让模型写一个 FIFO它写得挺好让它写一个 AXI 接口的跨时钟域模块代码能写出来可顶层模块和子模块的关系往往一塌糊涂。更要命的是这些生成结果很像“一次性代码”能跑通 testbench但你要把它放进真正的 SoC 集成环境里光可读性、可维护性就够你喝一壶的。我这里说的“可维护性”在 Verilog 语境里其实有两层意思结构可读性拿到一份 RTL 代码你能不能在五分钟内画出它的模块层级图每个子模块的边界是否清晰接口信号的命名和分组是否符合直觉物理可实施性这份代码在逻辑综合时能否被工具高效处理有没有把太多逻辑堆积在一个 always 块里导致 critical path 长到无法收敛AI 写代码真正欠缺的恰恰是这种“结构化思维”——知道哪里该切一刀、哪里该立一个层次、哪些逻辑必须分开。与其说 HiVeGen 是在解决“代码生成”不如说它是在解决“代码生成的元规则”。如果拿写文章类比过去的 AI 生成 Verilog 像是让模型当“想到哪写到哪”的散文家而 HiVeGen 做的事情是逼着模型先写一份大纲、再把每一章分派给不同的小组去写。最终拿到的是一本有目录、有章节、有内部引用的书而不是一整块意识流。2. 大模型为什么如此执迷于“单块结构”要理解 HiVeGen 的解决方案得先搞明白大模型为什么天生偏爱把复杂设计压成单块。这不是模型的“道德问题”而是它的技术本性决定的。我在实际调试里总结了三个主要原因第一训练数据的天然偏差。大模型学习 Verilog 代码时见到的绝大多数样本来自开源仓库比如 OpenCores、PULP 平台上的各种 IP、教学性质的代码集合。这些代码里本来就以中小型模块为主——一个 FIFO、一个 UART、一个 SPI 接口——它们本身就只有一层结构天然不需要层次化。模型学到的“平均印象”就是一段 Verilog 代码就等于一个文件、一个 module、一堆 always 块。你让它生成复杂系统它就本能地把所有东西平铺。第二自回归生成机制的局限。大模型是逐 token 预测的它在生成第 100 个 token 时本质上是在“赌”接下来最可能的 1000 个 token。对于小型模块这种单序列预测完全够用但对于复杂系统它缺乏“回看”和“重构”的能力——它没有办法在生成完第 800 行时回头去重新组织前面 200 行的结构。于是它倾向于选择“生成时最省力”的策略不住地往里加代码而不是花代价做层次抽象。第三上下文窗口带来的短视。当 prompt 里描述了太复杂的需求模型的各种能力会退化它会倾向于“先把当前需求写完再说”。这就是为什么你给 ChatGPT 一段几百行的规格说明时它给出的代码往往局部正确、全局混乱——它的注意力被局部需求占满了。我在一次实际项目中深有体会让模型生成一个包含 AXI-Lite 接口的 DMA 控制器它输出的代码里既有顶层模块的端口声明又有子模块比如寄存器组、数据通路的全部实现全部堆在一个 module 里光端口就有 40 多个。你说它错吧每个功能点都实现了你说它对吧这种代码放到真实项目里review 的同事怕不是想拿它垫显示器。3. HiVeGen 三大核心机制把“层次感”灌进 AI 生成的基因里HiVeGen 这篇论文的贡献就是针对这个“单块化”痼疾提出了一个完整的 RTL 生成管线。我精读下来它的核心机制可以拆成三个层次每个层次都对应一种“大模型不擅长但有办法补上”的能力短板。3.1 规格解析器把自然语言拆成一棵可执行的树HiVeGen 的第一步不是直接让大模型写代码而是先对自然语言规格做结构化解构。论文里的做法是将一个设计需求拆解成层次化的规格树顶层目标拆成若干个子任务每个子任务对应一个子模块子模块之间通过接口逻辑联系。这一步的价值很容易被低估。咱们工程师平时接需求时其实也在做同样的事——拿到一份 spec先判断要分几个模块、模块间信号怎么走、哪些逻辑可以合并哪些必须分开。大模型缺的恰恰是这套“需求分析”的习惯。HiVeGen 用规格树的方式强迫模型先做架构分解再代码生成从流程上杜绝了“拿到需求直接写代码”的路径。从论文的设计意图来看规格树还承担了另一个职能它是模块间通信协议的抽象层。每个子模块需要什么输入、产生什么输出、维护什么状态在树节点里先定义清楚后续生成代码时就相当于拿着接口文档填空。这比让模型自己临场决定接口信号要可靠得多。3.2 分层生成器一次只让模型写一层有了规格树之后HiVeGen 采用“由顶向下逐层生成”的策略。每层只生成当前层级的模块骨架和接口例化至于子模块内部的具体实现在更深一级的生成循环里处理。这个设计看起来简单实际上非常聪明。大模型的上下文窗口有限每层只生成少量代码模型的注意力就能高度集中在当前模块的逻辑上。它的“短期记忆”不用承载整个芯片的所有细节生成质量自然就上去了。这就像是你让一个新人工程师写代码你不会直接甩给他整个 SoC 的规格书而是让他先画模块框图、再填端口、最后写逻辑——每次只处理一个复杂度可控的单元。我在复现这个思路时做过一个对照实验让模型直接生成一个 4 通道 DMA 控制器与用“先定义子模块端口再分别生成各子模块最后例化”的方式相比后者的代码中端口不匹配、线网悬空等低级错误明显更少综合后的 LUT 用量也更接近手写水平。3.3 自动检查器给生成结果立一面“照妖镜”HiVeGen 的第三个核心组件是自动检查器。它会从功能一致性和结构规范性两个维度对生成的 RTL 做静态分析发现问题后把错误信息反馈给生成器驱动下一轮修正。这个“反馈-修正”环路非常关键。纯自回归生成的代码不可能一次就完美真正把生成质量拉起来的是错误信息的高效利用。HiVeGen 的做法是每轮生成后自动跑一遍 lint 检查和简单的功能仿真把错误日志作为下一轮 prompt 的一部分让模型知道自己哪里写得有问题。这个思路其实每个用过 ChatGPT 写代码的人都体验过只是 HiVeGen 把它做成了系统化、自动化的闭环。对我个人而言这个设计最大的启发是与其追求一次生成完美代码不如建立一条“生成检查修正”的高效流水线。人写代码尚且要反复 reviewAI 更没有理由一次成型。4. 论文之外从设计术语到工程落地的三层映射HiVeGen 能在 ICLAD 2025 拿到 Best Paper一个重要原因是它没有停留在“又做了一套 benchmark 证明大模型能生成代码”的层面而是真正触碰到了芯片设计流程里“结构性”这个老问题。但论文毕竟是论文从学术到工程中间还有一些需要我们自己思考和消化的问题。4.1 不是所有设计都需要层次化这里得泼一盆冷水。层次化不是银弹对于很多中小型模块强行分层反而会带来额外的接口开销和维护负担。比如一个简单的 SPI slave、一个 LED 呼吸灯控制器如果你也要先建一棵规格树、再逐层生成效率反而更低。我在实际使用时会把设计任务分成两类一是“原子模块”指单个功能单元交互简单可以直接让模型一把梭二是“组合系统”指由多个功能单元协作完成一个复杂任务必须做层次化拆分。HiVeGen 式的方法论弹药应该留给后者。这就像写字写便签不需要先列大纲但写长文不列大纲肯定要翻车。4.2 从“生成代码”到“生成设计文档”的思维转变HiVeGen 给了我另一个重要启发让 AI 生成代码之前可以先让 AI 生成设计文档。这里的“文档”指的不只是自然语言描述更包括端口列表、模块间信号交互矩阵、状态机的状态转移图、关键时序约束等结构化信息。我在工作里已经形成了一套固定打法接到一个复杂模块需求时先让大模型输出一份包含“模块划分、子模块端口定义、关键数据流、状态机设计”的 mini spec我审核通过后再让它分模块写代码。实测下来这种方式生成的结果比“一句话需求让模型连蒙带猜写代码”的可靠度高太多了。原因也简单你先把框架定死了模型的发挥空间就被锁定在正确的方向上翻不了车。HiVeGen 论文里的规格树本质上就是这份 mini spec 的形式化版本。它比自然语言描述更容易做自动验证同时也更贴近真实芯片设计流程中的 spec 习惯。4.3 工具链配套RTL lint 和形式验证是 AI 生成代码的标配论文里反复提到 auto-check 环节的重要性这提醒了我一个几乎被忽略的工程事实AI 写代码人必须要配好护栏。这里的护栏有几个层次。最低一层是语法检查相当于编译器的语法报错中间层次是 RTL lint 规则检查包括信号未使用、多位宽不匹配、锁存器推断等常见问题最高层次是功能验证——你得用直接测试或受约束随机测试确认生成模块的行为真的符合预期。让我说句掏心窝子的话AI 生成的 Verilog 代码在逻辑正确性上已经比大多数初学者要强但在“编码规范性”和“边界情况处理”上仍然不稳定。工具链配套的意义就是给这条不稳定的输出加一道稳定器。没有护栏时AI 一顿输出猛如虎你修复错误累成狗有了护栏AI 只是你的设计助手你才是那个负责人。5. 评估标准之外我用这套思路优化了哪些环节HiVeGen 在论文里提出了一个评价指标主要衡量生成结果的结构层次合理性和模块复用程度。说实话结构合理性和可复用性这两个维度在过去一年多 AI 生成 RTL 的研究里确实严重缺位大家都在比“能不能过测试”很少有人关心“代码结构像不像人写的”。我也尝试着把这种思维引入自己的开发验证流程。现在我用 AI 生成 RTL 后会额外做三个评估结构穿透力检查生成的代码里子模块边界是否与规格树的划分一致有没有出现模块互相例化、隐式依赖的情况接口鲁棒性测试子模块的输入端口如果在仿真里出现悬空或者瞬态抖动会不会引起生成代码的崩溃或者死锁可读性评分这段代码给到一个没有参与生成的同事手上他要花多久能看懂并开始修改这三个评估并非 HiVeGen 论文里的完整内容但它们的思路都是从“结构化生成”这个核心价值延伸出来的。我真实体会是当你开始用这套标准去审视 AI 生成结果时你会猛然发现纯还好代码能跑通那套标准已经太低了。在追求效率的同时工程伦理要求我们交付的必须是能让人维护、能落地的代码而不是一堆能跑的“一次性玩具”。这也是我特别想给同行分享的一点AI 辅助设计的真正门槛不在于让模型生成一段可仿真的代码而在于生成代码之后的一整套工程化评审和重构流程。HiVeGen 的论文价值即是把注意力重新拉回到了正确的位置——结构与工程而非炫技与速度。5.1 一个适合上手实践的最小流程如果你看了这篇精读也想在自己的设计里试一组“结构优先”的 AI 生成流程我建议从一个真实但不复杂的功能模块开始比如带 FIFO 的 UART 发送控制器。第一步先让模型写下模块划分和子模块接口第二步修改并确认这份接口定义没问题第三步要求 AI 分别生成 FIFO 模块、串行发送模块、控制状态机模块最后再让 AI 生成顶层例化文件并把它们连接起来。我第一次走完这个流程花了大概半小时但拿到的代码结构清晰程度远超想象。模块的各司其职可读性接近手写水平仿真首轮就通过了。这个过程中我全程没有亲手写一行 RTL只做了 reviewer 的角色——感觉非常奇妙。6. 尺寸之外的方向对话式设计、形式验证和系统重构HiVeGen 展示了一个阶段性的成果但芯片设计里的 AI 辅助远不止“生成代码再 lint”这一条路。我预判未来两三年内这个方向会有几个更值得关注的变化。第一个变化是“对话式设计”会成为主流交互形态。芯片设计本质上是大量模糊需求的逐步明确过程而大语言模型天然适合这种渐进式对答。未来的 RTL 生成可能不会一上来就铺开所有模块代码而是先跟设计师聊清楚需求边界边聊边完善内部 spec最终一次性输出一份结构清晰的代码包。第二个变化是形式验证会和生成流程深度绑定。现在的 auto-check 偏重 lint 和仿真但这些手段对组合爆炸型 bug 的检测能力有限。如果能把 SVA 断言自动生成、形式验证引擎和 AI 生成流程对接起来每生成一个模块就自动验证其关键属性AI 生成的代码质量会有一个质的飞跃。第三个变化是系统级重构将成为 AI 的必备能力。我们现在谈的都是从零生成但真实芯片设计中有大量的存量代码、旧 IP 需要做兼容和升级。AI 如果能够阅读现有代码、理解其架构、然后针对新需求做增量修改和局部重构那才是真正的生产力解放。HiVeGen 的规格树表示如果复用度足够高完全可以用到这种场景里。无论如何从 ICLAD 2025 现场的热度来看“AI 生成结构化 RTL”这个话题正在从“看个热闹”走向“实际部署”。HiVeGen 拿 Best Paper 实至名归它把 AI 生成 Verilog 的讨论从“能不能”带到了“怎么更好”的层面。最后分享一个我一直在用的小经验现在让 AI 写 RTL 之前我都会强制它先输出一个“模块划分清单 接口表 关键信号说明”然后我花五分钟审阅。这个习惯是从读 HiVeGen 论文之前就养成的但亲眼看到论文把这个流程自动化、工程化之后我更加确信给 AI 立规矩写出来的代码质量会远超你“顺其自然”的想象。结构这件事人和 AI 都一样——有章法才有产量。