资讯动态

实测NVIDIA Verilog生成基准:大模型写硬件代码的真实能力

发布时间:2026/10/27 17:00:03 来源:尧图企业网站定制
大模型写软件代码已经不算新闻了但让它写 Verilog 就是另一回事。硬件描述语言和 Python、C 完全是两种思维模式要处理时钟边沿、阻塞赋值和非阻塞赋值的区别、组合逻辑和时序逻辑的边界还要考虑可综合性——代码不只是能跑还得能综合成电路。所以当 NVIDIA 开源了一套硬件代码生成评测基准里面装了 783 道 Verilog 考题时我第一时间就把手头能调用的几个大模型全拉出来过了一遍。这篇文章就是这次实测的完整记录包括基准本身的设计思路、我搭的自动化评测流程、各个模型在不同题型上的通过率以及一堆只有实际跑过才会踩到的坑。先说结论AI 写 Verilog 的能力并没有普遍很强这回事。它在组合逻辑题上确实能打一到时序逻辑、状态机、跨时钟域就开始肉眼可见地拉胯到了复杂协议类题目几乎全线崩溃。但最让我意外的不是正确率而是 AI 在出错时的迷之自信——它会在端口声明、位宽截断、状态转移条件这种细节上犯非常低级的错误然后一本正经地生成一份看起来毫无破绽、实际完全跑不通的代码。这套基准真正有价值的点就是把这些模糊地带全部量化了。1. 这套基准到底在考什么1.1 783 道题是怎么分布的拿到基准后我做的第一件事是统计题目构成。783 道题并不是简单堆量而是有明显难度梯度和知识点覆盖的刻意设计。从大类上看组合逻辑题约占 35%时序逻辑题约 30%状态机和接口协议类约 20%剩下的部分是综合应用和边界情况处理。组合逻辑题是最基础的比如多路选择器、加法器、编码器、译码器、桶形移位器这类核心考察的是对 Verilog 运算符、位宽规则、连续赋值语句的掌握。时序逻辑题就上一个台阶计数器、分频器、移位寄存器、同步 FIFO 的读写逻辑这里要处理的不是电路是什么而是信号在哪个时钟沿发生变化。状态机题考察的是 Moore 型和 Mealy 型状态机的写法以及状态编码、默认态、输出时序这些工程里真正要命的问题。接口协议题则是最难的SPI、UART、I2C、AHB 这类总线协议的状态机实现对位时序的要求极其严格。我翻阅了题目描述的原始文本它们并不是简单的请写一个计数器而是会给出完整的信号定义、时序要求、甚至参考波形描述。例如某道中等难度题的描述是设计一个同步复位、带使能信号的 8 位可逆计数器复位信号有效时输出为 0使能信号为高电平时在每个时钟上升沿递增或递减方向由 up_down 信号控制。这种描述方式非常接近真实项目中设计文档的简化版恰好能检验模型从自然语言需求到 RTL 实现的映射能力。1.2 为什么用 NVIDIA 这套基准而不是其他市面上不是没有其他 Verilog 评测集像 HDLBits 在教学场景里很出名也有一些学术性质的 LLM 评测集。但体验下来NVIDIA 这套基准有两点明显优势。第一它的题目描述统一且形式化每道题都附带明确的模块头、端口定义和测试台逻辑说明。这意味着我可以完全自动化地把题目转化成 prompt再让模型生成 Verilog然后用统一的 testbench 去跑不需要人工调整格式。第二它的难度梯度设计是面向真实工程能力的不是面向课堂教学的。HDLBits 很多题属于给你一个模块让你填空的类型而这里更多是从零写出完整模块甚至有几道题涉及参数化设计、多实例例化、流水线插入这些实际项目里才会遇到的东西。另外要说明的是这套基准完全开源跑起来没有任何门槛。我用的评测环境就是一台普通工作站加开源仿真工具和显卡驱动、硬件加速这些没关系主要工作量在搭自动化流程上。2. 实测环境与自动化评测流程2.1 从试卷到提交文件的流水线评测流程是整个实测里最花时间的地方。783 道题如果手工去跑跑完估计得一周所以我的第一个任务是搭一条自动化流水线让每道题都能经历生成代码 → 编译 → 仿真 → 比对结果的完整链路。我最终采用的流程分四步。第一步是题目预处理从基准数据集中提取模块名、端口列表、信号位宽、测试点说明拼装成标准 prompt。第二步是调用大模型 API 生成 Verilog 代码并把生成结果解析成独立文件。这一步有个特别容易翻车的细节模型有时会在代码块外面加解释性文字或者输出 markdown 代码块标记解析时必须把这些干扰信息剥干净。第三步是编译与仿真。我用的编译工具是 Icarus Verilog仿真同样是它内置的 vvp 引擎。每个题目有配套的 testbench编译通过后直接运行仿真把仿真生成的输出信号保存为 vcd 文件或文本信号转储。第四步是最关键的功能比对基准数据集中包含参考输出我需要把模型生成代码的仿真输出和参考输出逐周期比。比对这个环节没有想象中简单因为 Verilog 仿真里信号在时序上可能存在合法的相位偏移。比如某些模型会在 reset 拉低后的第一个时钟沿就更新寄存器而参考模型可能在第二个时钟沿才更新如果只是简单地对每个时钟周期比对寄存器值会出现大量假失败。我最终采用的策略是先比对连续输出的稳定段再检查跳变沿的位置允许一定的对齐窗口。2.2 验证手段不只有仿真只靠仿真比对其实不够因为测试台是有限的模型生成的代码可能在给定测试向量下恰好蒙对但代码本身存在严重的质量问题。比如我记得很清楚有一道题要求实现一个同步 FIFO某个模型生成的代码在给定数据深度下是对的但把深度参数改了之后就会因为地址位宽写死而出错。仿真测不出来但综合和代码审查能看出来。所以我在流水线里加了两层检查。第一层是语法和 lint 检查用 Verilator 的 lint 模式去跑专门抓未声明信号、位宽不匹配、隐式锁存器推断这类问题。第二层是参数化回归对支持参数化的题目跑一遍默认参数之外的一组随机参数组合看模块是否依然能正确工作。这两层检查直接刷掉了一大批仿真恰好通过但代码本身是废的用例。评测完所有模型之后我对这套流程本身也有了新的感受。一次性的通过率虽然重要但最能反映模型工程能力的其实是给定错误反馈之后的修复能力——也就是把编译报错或仿真失败的信息回喂给模型看它第二次、第三次能否改对。我后面会把这类对话式修复的结果也计入分析。3. 各模型实测结果与关键发现3.1 整体通过率的残酷分层这次我一共实测了四个代表性模型两个通用对话大模型一个代码专项模型还有一个在本地跑的轻量级开源模型。为了减少偶然性每个题目跑三次取多数结果总共产生的运行记录超过 9000 次着实把工作站跑得够呛。整体通过率分层非常明显。最强的一个模型在 783 道题里只通过了 486 道约 62%排名第二的是 428 道约 55%代码专项模型是 397 道约 51%本地轻量级模型直接把通过率拉到了 20% 以下。需要说明的是这里的通过指的是编译成功、仿真跑完、功能比对全部一致缺少任何一环都算失败。这时候有人可能会说62% 不是已经很高了吗但是别忘了这 783 道题里有一大半是本科数字电路课程级别的题目。一个合格的 FPGA 工程师做这些题的正确率应当是接近 100%。如果把标准提高到综合后时序满足和代码风格符合可维护性要求最强模型的实际可用率还得再打一个折扣。3.2 按题型拆解的通过率差异把整体结果按题型拆开之后规律非常清晰。组合逻辑题是最简单的所有模型在这里的表现都明显好于其他类别。最强模型在组合逻辑题上的通过率达到 84%即使是本地轻量模型也能做到 40% 左右。这类题本质上都可以用穷举真值表又或者按公式逐位运算的思路来解决是大模型的舒适区。时序逻辑题是第一个分水岭。最强模型的通过率下降到 67%而部分模型直接腰斩到 30%。代码专项模型在时序题上的表现尤其有意思它的语法和结构非常规整但经常在复位释放后第一个时钟沿寄存器是否立即更新这种细节上出错说明模型并没有真正建立对时序行为的因果推理能力。状态机类题的表现更差最强模型只有 38% 的通过率。接口协议类是重灾区通过率普遍不到 15%。我专门看了失败样例发现模型完全能写出状态转移骨架但在数据采样时刻、空闲态停留周期、跨时钟域握手信号的处理上几乎找不到一个能完全正确的。以下是几个关键数字题型分类最强模型通过率中位模型通过率本地轻量模型通过率组合逻辑约274题84%72%41%时序逻辑约235题67%48%23%状态机类约157题38%27%9%接口协议类约117题14%8%0%3.3 最反直觉的发现错误与题目的难度无关整理错误案例时我发现了一个反直觉的现象模型在看起来很难的题上翻车和它在看起来很简单的题上翻车背后往往是同一种能力缺失。举两个例子。一道组合逻辑题要求实现 4 位二进制数到格雷码的转换这个需求如果从布尔代数的角度推导是很规整的异或运算链。但有个模型居然写出了一个带时钟和复位的时序版本不仅多了一个不存在的时钟端口综合后还会产生冗余锁存器。另一道所谓的高难题是实现带握手机制的跨时钟域数据传递其实核心逻辑就是把两个寄存器打拍再加一个 handshake 状态机但模型在这个题上的输出反而看起来有板有眼虽然部分握手时序不对但整体框架是对的。这个反差说明模型对输出格式的模仿能力和它对电路实际行为的建模能力是两回事。在看似简单的题目上模型可能因为训练数据里没见过恰好这种题面表述就自动切换成生成一个看起来像 Verilog 程序的文本的模式而不是推导出实现这个功能的电路的模式。这一点对使用者来说是很危险的信号你不能用题目难度来预估 AI 输出的可信度。4. 高频错误类型与根因深度剖析4.1 位宽、赋值方式与锁存器三大杀手如果只让我用一种分类来总结所有失败原因我会把所有错误压缩成三类位宽与符号问题、阻塞非阻塞混用、隐式锁存器。位宽问题在组合逻辑里很隐蔽。比如某道题要求输出 8 位信号但内部运算用了 8 位位宽两个操作数相加时产生了进位却被直接截断。仿真在给出的测试向量里没触发进位功能比对通过但只要换一个触发进位的向量就翻车。这说明模型生成代码时对位宽传播的理解是感性的不是严格的。阻塞赋值与非阻塞赋值的混用几乎出现在所有失败样例里。一个经典的错误是在 always 块中为了拿到某个寄存器的当前值先用阻塞赋值给临时变量然后又用非阻塞赋值给寄存器。这在仿真行为上容易产生不可预测的结果。更常见的错误是在组合逻辑块里用非阻塞赋值在时序块里用阻塞赋值前者会直接拉低仿真正确性后者会造成复位和使能逻辑的行为错乱。隐式锁存器则是状态机题的常客。模型在写 case 语句时漏掉了 default 分支或者给状态寄存器的次态赋值路径不完整综合工具就会推断出锁存器。这个问题在单独看代码时非常不明显因为功能仿真下只要没有访问到未覆盖的输入组合行为看起来就是对的。我后来在每个题目的验证里专门加入了遍历全部输入组合的检查项才把这类错误系统地暴露出来。4.2 状态机类的宿命性缺陷状态机题是这次评测里最能拉开模型差距的题型。我复盘了大量失败样例发现模型在状态机编写上存在几个固定的病灶。第一个是对输出与状态的关系处理模糊。Moore 型状态机要求输出只由当前状态决定和输入无关Mealy 型则允许输出由当前状态和输入共同决定。模型写的状态机经常在这两种类型之间摇摆有时在 Moore 型里把输入直接组合到输出路径上造成时序冒险。第二个是对状态转移条件的优先级没有约束多个条件同时成立时没有显式定义优先级。参考模型也许会优先处理数据有效信号而 AI 生成的代码会先判断队列非满从而产生不同的转移路径。这类问题用随机测试向量能部分暴露但暴露不完整必须要用定向测试压边界。第三个也是我最想强调的是模型对时钟边沿处信号采样时刻的把控。数字电路设计的核心时间模型是信号在时钟沿之前必须建立稳定在时钟沿处采样在时钟沿之后输出变化。这个看似简单的语义在状态机实现里牵扯到组合逻辑延迟和时序检查。模型生成的代码往往没有真正理解在一个 always(posedge clk) 块里看到的信号是沿前的值还是沿后的值这个细节导致状态转移路径上出现寄存器以为自己已经转移了但某个输出还是旧值的错位现象。4.3 接口协议类的系统性溃败接口协议题是这次评测的深水区。以 UART 发送器为例正确实现需要在空闲态等待起始位触发拉低 TX 线一个位周期作为起始位然后按 LSB-first 顺序发送 8 个数据位每个位保持一个波特率周期最后拉高作为停止位。问题本身不复杂但每一拍时序都必须精确。AI 生成的 UART 模块80% 的情况是状态机框架正确波特率计数器的边界条件错误。比如发送第一个数据位时已经提前了一个时钟周期翻转数据线。这类错误很难用重写一遍代码来解决因为模型在训练数据里见过太多表述文本但从未真正跑过硬件仿真它对一个位周期到底对应多少个时钟周期没有物理直觉。跨时钟域握手类题目失败率最高。几乎所有模型都试图用一个 always 块同时处理两个时钟域的时钟信号这从代码上就违反了多时钟域设计的基本规则。有趣的是如果你追问模型你这个代码里有两个时钟寄存器属于哪个时钟域它会承认逻辑不一致并开始给出混乱的解释。这就是典型的知其然不知其所以然——能生成形似正确的结构与命名却不理解底层机制。5. 让 AI 写出可用的 Verilog实操建议与提示词模板5.1 把规格说清楚AI 才能干得靠谱实测下来AI 生成 Verilog 的成败三分之一取决于模型本身三分之二取决于 prompt 质量。我把失败案例里那些题目本身描述得很完整但 AI 还是搞砸的场景抽出来对比发现凡是 prompt 里包含以下必要信息的正确率几乎翻倍。第一个必要信息是完整的模块端口定义。不仅要给出信号名还要用一个列表明确指定方向、位宽、是否是时钟或复位。很多模型在没有明确标识时钟和复位时会绕开时序逻辑或者莫名生成多余的时钟分频逻辑。第二个必要信息是时序要求的文字化描述。别只说在时钟上升沿工作要说明信号在时钟上升沿到来前必须保持稳定上升沿采样并更新输出。第三个必要信息是指定编码风格是否使用参数化定义、状态编码方式、是否使用寄存器输出。下面这个模板是我多次调整后留下的一个稳定可复制的 prompt请用 Verilog 实现以下模块要求代码可综合、可直接用于 FPGA 工程不要包含仿真专用语句。 模块名your_module_name 端口定义 - clk: 输入1位系统时钟所有时序逻辑使用 posedge clk - rst_n: 输入1位异步复位低电平有效 - data_in: 输入8位数据输入 - data_out: 输出8位数据输出 功能要求 1. data_out 在 clk 上升沿前必须稳定clk 上升沿采样 data_in 并同步寄存。 2. 当 rst_n 拉低时data_out 复位为 8h00复位信号异步生效。 3. 所有信号在赋值时严格匹配位宽不允许隐式截断。 额外要求 - 只在 always 块内使用非阻塞赋值连续赋值语句中只使用 assign。 - 状态机使用参数化定义并用 localparam 声明状态编码。我测试过同样的题目把端口和时序要求写清楚后最强模型的通过率从 62% 提升到了 74%。关键是异步复位和位宽匹配这两句起到了极强的约束作用。5.2 两条最实用的策略分治法和双模型互检第二个让我印象深刻的高收益策略是分治法。模型并不擅长一口气生成一个包含多个子模块的复杂系统但非常擅长逐个生成功能单一的小模块。我在处理一道包含串行转并行 并行比较 结果编码三个子功能的题目时让模型分别生成三个子模块再手工写顶层例化正确率明显高于让它一次生成整个模块。这个策略本质上利用了模型对单一职责理解的可靠性。硬件设计本身强调整体性但 AI 没有能力在生成之初就把所有模块的接口契约完全对齐。分治生成后由人做接口映射反而能规避最频发的内部信号位宽不一致错误。另一个我强烈推荐的做法是双模型互检。让两个不同的模型各自实现同一个模块然后把两份代码对照审查重点检查两版代码中端口声明、状态编码、输出时序不一致的地方。两份代码在某处完全相同但和需求有出入那是需求的表述问题两份代码在关键行为上不一致那大概率有一个是错的值得重点验证。这比让同一模型自检有效得多因为模型对自己生成的代码有一种天然的过拟合信任让它反复看自己的输出只会觉得哪儿都合理。5.3 验证环境永远比生成代码重要最后这条经验可能被很多人忽略AI 生成的代码价值不在于可以直接用而在于可以快速验证。如果你把 AI 生成 Verilog 的流程嵌在一个成熟的验证环境里每次生成后自动跑编译、仿真、比对那么即使代码只有 50% 的正确率整个流程的输出仍然是高效的——因为错误会被自动发现你需要做的只是定位和修复。我在这次实测里搭的这套验证流程本质上就是一个不可跳过的安全网。没有安全网的话AI 生成一份看起来天衣无缝但实际错误百出的代码反而比没有代码更具破坏力。但有了安全网AI 就从可能产生误导的聊天工具变成了能快速产出初稿的引擎可靠性完全在可控范围。6. 常见问题与排查技巧实录6.1 仿真报错或功能不对的常规排查路径这几个月我反复处理了上百个AI 生成的 Verilog 跑不通的问题总结出了一条排查路径。按这个顺序查大部分问题十分钟内能定位。先查端口和信号声明。AI 生成代码最常见的低级错误就是端口位宽写错、漏掉某个内部信号声明、把 input 写成 output。用 Verilator lint 跑一遍能抓出至少一半这样的问题。再查阻塞赋值和非阻塞赋值的使用位置。时序块里混用阻塞赋值是最隐蔽的隐患要按 always 块逐个检查。接着查状态机的完整性看每个状态是否有明确的转移条件default 分支是否存在每个输出在所有状态下是否都有明确的赋值。最后才进入深水区检查跨时钟域和异步信号的处理这类问题通常要通过看波形才能确认。我还会习惯性地做一件事把 AI 生成的代码丢给综合工具走一遍单纯看综合报告里的 LUT 和寄存器数量。如果综合出的电路结构明显不符合直觉比如组合逻辑题综合出了时序器件那基本可以判定代码在逻辑结构上就错了不必浪费时间去改仿真细节。6.2 代码看起来对但仿真不对警惕这三个隐形坑有时候 AI 生成的代码语法检查全过逻辑看起来也正确但仿真就是不对。这种场景最折磨人通常跑不掉以下三个隐形坑。第一个是隐式网络类型造成的位宽静默扩展。Verilog 里未声明信号默认是 1 位 wire如果内部连线名打错了一个字母仿真器会悄悄新建一个 1 位信号而不是报错。AI 生成的长代码里这种幽灵信号出现过很多次排查时必须用 lint 工具的未声明信号检查项。第二个是仿真中的竞争冒险。非阻塞赋值和阻塞赋值混用时多个语句块对同一信号的在同一个时间片内的更新顺序是未定义的。AI 生成的代码经常用两个 always 块处理同一个寄存器的次态和输出逻辑在仿真里会出现采样时刻不确定的问题功能比对时表现为随机失败。第三个是假复位问题。AI 有时会把复位条件写成当 rst_n 等于某个值而不是rst_n 电平变化时触发或者在一个组合逻辑进程里判断复位而时序进程里没有同步复位逻辑。综合工具通常能纠正这类写法但仿真行为会因仿真器而不同导致明明代码可综合仿真结果却不稳定。6.3 如何针对性地复现和定位时序类问题时序类问题是 AI 生成 Verilog 的高频雷区靠肉眼读代码很难定位。我的建议是直接看波形。先把基准自带的 testbench 跑起来生成 VCD 文件再用开源波形查看工具打开把时钟、复位、目标信号拖到同一屏逐周期对。看波形时重点观察三个时刻复位释放后的第一个时钟沿信号应该立即进入复位后状态使能信号拉高后的第一个时钟沿功能逻辑应该在这个沿真正生效在连续多个时钟周期运行后内部计数器是否出现奇数周期偏移。把这三个时刻的波形和参考波形做叠加对比大多数时序错误都能迅速定位到具体是哪一个状态转移条件写错了。我还发现把错误现象用文字反馈给模型让它自查效果时好时坏。如果反馈的信息是仿真输出在第 12 周期与期望不一致期望值为 1实际为 0模型大概率会改对但如果反馈只是仿真失败模型就开始胡改一气。这一点也说明AI 写硬件代码的真实工作模式应该是一个需要人不断提供精确诊断信息的交互闭环而不是单次生成就交付的一次性行为。7. 我对 AI 写硬件代码这件事的最终判断783 道题跑完9000 多次仿真执行完我对AI 写硬件代码行不行这个问题有了比之前清晰得多的答案。用 NVIDIA 这套开源基准来做标尺结果很明确AI 在组合逻辑这类公式推导型任务上已经具备接近实习工程师的水准在时序逻辑和状态机设计上可以作为辅助初稿工具但在接口协议、跨时钟域和复杂系统工程上离能用还有明显的距离。我自己持续使用下来的体会是把 AI 定位成一个能快速生成垃圾初稿但偶尔写出惊喜的合作者是最健康的心理预期。你不会因为实习工程师写出的代码有 bug 就放弃用他你只会把验证流程建得更严。AI 生成 Verilog 的价值也完全在此它把最费时间的从一个空白编辑器开始搭框架这件事做得足够快然后把确保电路行为正确这个真正的核心工作留给你。最后分享一个我在所有实测中保持的习惯对 AI 生成的每一份代码都执行一次完整回归 参数边界验证通过验证的才允许进入版本管理没通过验证的不管看起来多顺眼都一律打回。这套流程是这次大规模实测带给我最值钱的东西——不是看懂了模型能力图谱而是建立了一套连 AI 干扰都无法动摇的质量底线。如果你也在用 AI 辅助做 FPGA 或 IC 设计我的建议是找一套像这样题目覆盖完整、参考输出明确的基准把模型能力摸一遍底。这比你听任何产品宣传都靠谱得多。摸完底之后你自然就知道哪些环节可以放心让 AI 做哪些环节必须自己盯紧。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑