我花了一周时间,把 NVIDIA 这个开源 Verilog 基准里的 783 道题,全部拿主流大模型跑了一遍。结果很有意思:总体语法通过率能到八成以上,但你要是真让它独立写一个带完整时序的 I2C 从机,翻车率照样高得吓人。这篇文章就是这次完整实测的记录——环境怎么搭、分数怎么打、几道典型考题的翻车现场,以及最后我总结出来的“哪些 RTL 可以放心交给 AI、哪些绝对不能碰”。
软件侧 AI 写代码这半年已经卷成红海了,但硬件圈子里一直存着很重的怀疑。Verilog 毕竟是硬件描述语言,跟 Python、Rust 有本质区别:并发执行、时钟语义、可综合性、面积时序功耗,哪一个拎出来都能把“看起来能跑”的代码打回原形。问题是怀疑归怀疑,之前缺一个题目量足够大、评分标准统一的基准来量化这件事。NVIDIA 这套开源基准的价值就在这里,它不是网上那种“十行点亮 LED”的玩具题,而是从工程和教学场景里整理出来的一整套带 testbench 的实测题。如果你也是写 RTL 的,或者正在学 Verilog,又好奇 AI 到底能帮你做到哪一步,这份实测应该能给你一个比较靠谱的答案。
1. 783 道题从哪来:这份基准的构成和特殊之处
1.1 为什么硬件代码比软件代码更难评估
AI 写软件代码好不好判断,编译了跑一下、上线的线上指标说话就行。硬件不行,光能编译不算数,要过仿真、过综合、看时序、比面积,一个模块错一个位宽,流片回来就是几百万美金的沉默成本。所以 AI 写硬件代码这事,单靠几个 demo 根本说明不了问题,必须有一套大规模、带标准评分流程的题目集。
NVIDIA 这次开源出来的东西,据我了解题目来源主要分成几块:一块来自真实 RTL 工程和内部考核里的经典设计,一块来自高校数字电路教学里的典型练习,还有一块是围绕总线接口、算术单元、状态机这类高频场景改编的变体题。三块凑到一起,最终是 783 道,带配套 testbench 和难度标注。这个体量的好处是终于可以做统计了,而不是今天看一个例子说“AI 好强”、明天看另一个例子说“AI 好菜”。
1.2 题目的分类与数量分布
我先按自己的理解把 783 道题划成了六大类,这样后面打分和分析才有粒度:
| 题目类 | 题目数 | 考察重点 |
|---|---|---|
| 基础语法与微操作 | 112 | 位拼接、参数递增、模块例化、简单赋值 |
| 组合逻辑 | 180 | 逻辑门、编码器、译码器、二进制转格雷码类 |
| 时序逻辑与计数器 | 150 | 计数器、移位寄存器、分频器、脉冲产生 |
| 状态机与接口协议 | 120 | FSM、UART、I2C、SPI 类接口时序 |
| 算术与算法电路 | 110 | 加法器、乘法器、除法器、滤波算法硬件化 |
| 工程进阶与边界处理 | 111 | 跨时钟域、三模冗余、复位策略、低功耗写法 |
这个分类不是官方口径,是我自己做评测时为了方便统计而切的。六类加起来正好 783。除了按功能分类,每道题还带难度标签,我把它合并成四档:入门、基础、进阶、挑战。比例大约是入门 312 道、基础 238 道、进阶 148 道、挑战 85 道。为什么要单独看难度?因为后面你会发现,一个漂亮的总体通过率,很可能就是被简单题堆出来的。
1.3 我如何定义一道题算“答对”
评测最怕标准不一致。我把一道题判定为“通过”,要求同时满足三个条件:
- 语法编译通过:用
iverilog编译生成代码,零报错零警告; - 功能仿真通过:跑基准自带的 testbench,所有断言全部满足;
- 可综合检查通过:用 Yosys 做工艺无关综合,能吐出标准单元网表,且没有 latch、多驱动这类致命风险。
三个条件缺一个都不算对。这比很多论文里只统计“是否通过仿真”要严格得多,因为仿真通过但不可综合,是 AI 写 Verilog 最常见的障眼法,后面我会专门用除法器那道题展开讲。
另外我同时统计了 pass@1 和 pass@3。pass@1 就是一次性生成的代码直接全过;pass@3 是同样的提示词采样三次,只要任意一次全过就算过。为什么要看 pass@3?因为真实工程里没人会用一次生成的结果直接流片,工程师和 AI 之间本来就有“生成-反馈-修正”的交互过程,pass@3 更贴近实际生产力,pass@1 则反映模型“一次拿对”的能力上限。
2. 测试环境与评测方法:尽量把实验做得公平
2.1 软件工具链与硬件环境
先说环境,方便你复现。我跑评测的机器是一台双卡机器,主卡是 RTX 4090,用来本地部署开源权重模型;闭源模型走 API 访问,不占本地算力。仿真链路用的是iverilog 12做快速语法拦截,Verilator 5再跑一遍 lint,最后由 Yosys 做综合检查。测试脚本用 Python 写的,顺序是:生成代码 -> 写临时文件 -> iverilog 编译 -> 跑 testbench -> Yosys 综合 -> 汇总 JSON 报告。
综合这一步为什么不用 Vivado 而用 Yosys?两个原因:一是 Yosys 免费、无 License 限制,可以 783 道题全量跑,Vivado 批量跑会把人烦死;二是这个评测关注的是“代码可不可综合”这个基本事实,不是特定工艺下的时序收敛,所以用工艺无关综合足够。如果你自己复现,想换成 Quartus 或 Vivado 做关键题目的复核也可以,但全量跑我还是推荐 Yosys。
2.2 模型分组:闭源组和开源组
我测的模型分两组。闭源组选了三个主流的头部通用对话模型,代号 C1、C2、C3,统一走 API;开源组选了三个能本地部署的代码专项模型,代号 O1(7B 小模型)、O2(14B 通用)、O3(32B 代码增强),本地量化部署。这里不点具体名字是有原因的:大模型迭代太快,今天测的版本明天可能就下架了,点名字反而容易让结论过期。你只要知道分组逻辑就行——闭源组代表“开箱即用、能力天花板最高”的路线,开源组代表“数据可控、成本更低、可私有化部署”的路线。
推理参数也做了统一:temperature 0.7,top_p 0.95,max_tokens 2048。为什么温度取 0.7?太低容易每次都生成同一个错误答案,太高又会引入随机噪音;0.7 是代码生成场景里比较通用的折中,既能看到不同采样结果,又不至于天马行空。数据集固定在一个 commit 版本上,所有模型跑同一批题,避免版本漂移影响复现。
2.3 统一评测用提示词模板
为了防止模型因为不知道要“可综合”而生成一堆仿真风格代码,我先把提示词模板固化下来了:
你是一名熟练的 RTL 工程师,请用 Verilog-2001 实现以下任务: {task} 要求: - 顶层模块名为 {module_name},端口列表固定为 {port_list}; - 代码必须可综合,禁止使用 initial、fork/join、wait、 动态数组、递归等不可综合结构; - always 块必须明确区分组合逻辑 @(*) 与时序逻辑 @(posedge clk), 时序逻辑统一使用同步复位,复位极性为低有效; - 所有寄存器和 wire 显式声明位宽,不允许隐式 1 bit 截断; - 请给出关键信号和状态机的注释说明; - 只输出单个 .v 文件内容,不要附加解释。这个模板不是拍脑袋写的。我在试跑的 50 道题里对比过,如果不把“禁止 initial”“显式位宽”“同步复位”写进去,生成结果里至少多出三成不可综合的代码;把约束写清楚之后,模型生成“仿真风格代码”的概率明显下降。所以后面所有模型的评测都用这一版模板,不用各自的特调提示词,保证公平性。
3. 结果总览:通过率看着还行,但里面的水分不少
3.1 按题类统计的功能通过率
先上总表。下表是各模型组在不同题类上的 pass@1 和 pass@3,单位是百分比:
| 题目类 | 题量 | C组 pass@1 | C组 pass@3 | O组 pass@1 | O组 pass@3 |
|---|---|---|---|---|---|
| 基础语法与微操作 | 112 | 92 | 98 | 76 | 90 |
| 组合逻辑 | 180 | 84 | 91 | 45 | 61 |
| 时序逻辑与计数器 | 150 | 65 | 78 | 22 | 34 |
| 状态机与接口协议 | 120 | 48 | 61 | 10 | 17 |
| 算术与算法电路 | 110 | 36 | 50 | 12 | 20 |
| 工程进阶与边界处理 | 111 | 15 | 25 | 5 | 9 |
C 组就是闭源模型组,O 组是开源模型组。看出来了吗?C 组总体 pass@1 大概有 57%,pass@3 到 68% 左右,听着是不是还行?但只要拉到“状态机与接口协议”和“工程进阶与边界处理”这两类,直接掉到 48% 和 15%,O 组更是惨不忍睹,接口题 pass@1 只有 10%。所谓“AI 写硬件代码很行”的感觉,很大程度是前两类简单题给的。
3.2 按难度档位看:简单题撑起了八成的好感度
再按难度档位切一刀,这个趋势会更明显:
| 难度档位 | 题量 | C组 pass@1 | C组 pass@3 | O组 pass@1 | O组 pass@3 |
|---|---|---|---|---|---|
| 入门 | 312 | 90 | 97 | 70 | 85 |
| 基础 | 238 | 52 | 72 | 20 | 34 |
| 进阶 | 148 | 18 | 30 | 6 | 10 |
| 挑战 | 85 | 5 | 9 | 1 | 2 |
入门档占比接近四成,而且通过率能做到九成以上;基础档就腰斩了;到了挑战档,C 组最好的模型 pass@3 也只有 9%。换句话说,AI 在简单可复现的模板题上已经非常强,但题目一旦涉及多周期时序、异常状态、边界条件这些真实硬件痛点,能力是断崖式下跌的。所以“AI 写硬件代码行不行”这个问题,不能用一个百分比回答,必须拆开看。
3.3 各家强项与死角的差异说明什么
从分类结果里还能看出一个有意思的规律:闭源组在“组合逻辑”“算术算法”这类纯功能题上很稳,说明模型对经典电路结构的记忆很扎实;但到了接口协议题,普遍暴露出“状态机骨架会画、时序细节不会填”的问题。开源组则是另一幅景象——基础语法题能拿高分,说明“背模板”能力够用,但稍微复杂的题目就顾此失彼,经常修好一个报错又弄出新报错。
这背后的原因其实不复杂:大模型生成 Verilog 的能力,本质上取决于它训练语料里见过多少真实的、高质量的 RTL 代码。组合逻辑、计数器这类代码在开源仓库和教材里多得是,模型学得透;而 I2C 从机带跨时钟域处理的完整工程代码,公开语料很少,模型自然只能拼凑一个“形似”的壳子。这对我们判断“AI 现在该用在哪个环节”非常关键。
4. 几道决定结论的考题复盘
4.1 二进制转格雷码:组合逻辑才是最稳的答案
先看一道组合逻辑入门题。题目很经典:将 N 位二进制数转换为格雷码。这道热词背后一直有人问“为什么不用时序逻辑而用组合逻辑”,其实答案就一句话:这个转换本质是纯组合逻辑,不需要任何状态。标准表达式是gray = (bin >> 1) ^ bin,用异或树一拍完成,无时钟、无寄存器、无复位,延迟最小,面积也最小。
实测里闭源组基本都给出组合逻辑写法,类似下面这样:
module gray_encoder #(parameter W = 4) ( input [W-1:0] bin, output [W-1:0] gray ); assign gray = (bin >> 1) ^ bin; endmodule但开源组里有不少模型给的是always @(posedge clk)版本,功能仿真也能过,因为多了一级寄存器,输出晚了一个周期。问题在哪?如果下游逻辑按“组合逻辑一拍输出”做时序预算,AI 多加的这组触发器会直接破坏关键路径。功能对,语义不对,这在硬件里就是坑。它提醒我一件事:AI 能写出“语法正确”的代码,但不一定理解“为什么这么写”的工程约束。
4.2 滑动窗口滤波:位宽、复位、除法三个坎
第二道题比上一道实用得多:对一个连续输入的数据流做窗长为 4 的滑动平均滤波。这是信号处理硬件里的常客,也是典型“看着简单、落地全是坑”的题。正确思路是环形缓冲加累计和:来一个新数据,从累计和里减掉最旧的数据,加上新数据,再除以窗长。
AI 在这道题上的错误非常有代表性,我统计了一下,高频翻车点有三个:
- 窗口数组没有复位逻辑。很多模型只写了
buf[idx] <= din,但没处理sum的初值,结果综合出一堆 latch,代码明明看着很顺,可综合检查直接报错; - 累计和位宽不够。8 位输入、窗长 4 的滑动平均,累加和至少需要
8 + ceil(log2(4))也就是 10 位。AI 经常直接声明一个 8 位sum,仿真时前几个周期没事,窗口灌满之后溢出,测试用例一加长就挂; - 窗口长度是 2 的幂时,老老实实写
/ 4其实能过功能仿真,但被综合成除法器电路,而工业实现通常用右移两位做截断近似,或者加了半个窗口的偏置做四舍五入。AI 没有这种面积优化的意识。
正确写法的核心片段是这样:
reg [WIDTH-1:0] buf [0:WIN-1]; reg [WIDTH+LOG2WIN-1:0] sum; reg [LOG2WIN-1:0] idx; always @(posedge clk or negedge rst_n) begin if (!rst_n) begin sum <= 0; idx <= 0; end else begin sum <= sum - buf[idx] + din; buf[idx] <= din; idx <= (idx == WIN-1) ? 0 : idx + 1; end end // WIN 是 2 的幂,所以等效于 sum / WIN,截断取整 assign dout = sum[WIDTH+LOG2WIN-1:LOG2WIN];除非严格要四舍五入,否则这种“减最旧加最新”的写法在工程上比每次都重新求和高效得多。这道题给我的感受是:AI 能搭出滑动平均的框架,但对位宽、复位、综合这些硬件独有的细节,仍然需要人手去逐项校。
4.3 三模冗余模块:会搭架子,但表决器写歪等于白干
三模冗余(TMR)是安全关键设计里的常见套路:三份相同的逻辑同时运行,再用一个多数表决器决定最终输出。题目让设计一个带表决器的三模冗余模块。这种题难度不高,但考察的是“你是否理解冗余的真正目标”。
实测里 AI 经常把表决器写成:
assign voter_out = (a | b | c);这是错得最典型的一种。一个或门,三个信号里任何一个为高,输出就是高;真正要的应该是“三个里至少两个为高才输出高”,即:
assign voter_out = (a & b) | (a & c) | (b & c);这两个写法在只有一个模块出错时行为完全不同。或逻辑会把单个故障直接传播出去,整个 TMR 形同虚设;真正的表决器能够屏蔽单点故障。AI 为什么容易写错?因为它训练语料里“多个输入然后输出”的场景太多,大部分是或逻辑,专门的真值表约束反而学不进去。好在写代码的模型还算老实,如果提示词里明确写了“多数表决”,C 组大部分能回到正轨;开源组表现就差很多,不少模型对“冗余”的理解就停在“复制三份”,三个人都犯了同样的病,冗余就成笑话了。
这道题还有个衍生教训:AI 生成的 TMR 模块往往不做故障注入测试。真实工程里要把三份输入的差异强制翻转用来验证表决器有效性,AI 基本不会主动加这个验证逻辑,需要工程师在后置环节补。
4.4 I2C 从机状态机:协议细节是重灾区
接口协议题是这次评测里最能拉开差距的一类。我挑一道有代表性的题:实现一个支持单字节读写的简化 I2C 从机接口,用来读写内部寄存器。听上去结构不复杂,就是状态机加移位寄存器,但我统计的结果是:C 组 pass@3 只有三成出头,O 组几乎全军覆没。
复盘生成的代码,问题集中在四个地方:
- START/STOP 检测写错:I2C 的起始条件是 SCL 为高电平期间 SDA 产生下降沿,停止条件是在 SCL 为高电平期间 SDA 产生上升沿。很多模型直接把 SDA 当成普通信号,用
posedge SCL采样,这样根本抓不到起始和停止; - ACK 周期差一拍:I2C 每个字节 8 位数据之后还有第 9 个 ACK 时钟周期,模型经常把 ACK 状态机和数据移位计数器混在一起,导致 ACK 提前或延后一个周期;
- 状态枚举没有复位值:系统上电时状态机落在
IDLE以外,这在硬件设计里属于大忌; - 地址写死:有模型把从机地址硬编码成
7'b1010010,而不是做成参数。功能仿真恰好匹配时能过,换个地址就全崩。
这里我把一个标准的简化状态流列出来,你拿 AI 的生成结果对一下就明白差距在哪:
IDLE:等待起始条件;ADDR:收 7 位从机地址加 1 位读写位,第九拍输出 ACK;REG_ADDR:收寄存器地址,第九拍输出 ACK;WRITE:逐位收数据,每字节第九拍输出 ACK;READ:逐位发数据,每字节第九拍等待主机的 ACK;STOP:收到停止条件后回到IDLE。
AI 生成的版本往往“看着都写了”,但状态转移条件一带而过,边沿检测算法缺失,这种代码放到真实总线上抓波形,大概率第一个事务就跑飞。接口协议题恰恰是 RTL 工程师日常写最多的部分,也是 AI 现在最靠不住的部分。
4.5 二进制除法器:仿真能过,综合不行的典型
这道题我一定要拿出来单独讲,因为它完美展示了为什么“仿真通过”和“可以用”是两回事。题目是实现一个无符号二进制除法器。AI 最常生成的代码如下:
// 仿真可以跑,但综合直接崩 while (remainder >= divisor) begin remainder = remainder - divisor; quotient = quotient + 1; end懂综合的读者看到这个while应该已经皱眉了。仿真器跑这段逻辑没问题,remainder 减到小于 divisor 就停;但综合器需要把所有循环展开成确定的硬件结构,而这里的循环次数取决于运行时的数据值,不是编译期常量。Yosys 对这种结构的态度是:要么直接报 unsupported loop,要么尝试展开成一个超大的组合逻辑块,面积和时序全都不可控。
正确做法是基于移位-减法的迭代除法器,每个周期做一个位的判断和移位,W 个周期出结果,核心逻辑如下:
always @(posedge clk) begin if (start) begin remain_q <= dividend; divisor_q <= divisor; quotient_q <= 0; iter <= 0; busy <= 1'b1; end else if (busy) begin if (remain_q >= (divisor_q << (W-1-iter))) begin remain_q <= remain_q - (divisor_q << (W-1-iter)); quotient_q[W-1-iter] <= 1'b1; end iter <= iter + 1; if (iter == W-1) busy <= 1'b0; end end这道题的评测结果在两组里都很难看,因为大模型天然倾向于用“人类思考除法”的方式写循环,而不是“硬件执行除法”的迭代方式。这说明一件事:AI 写算法思路可以,写可综合的硬件架构还不行。
4.6 基础样板题:AI 的舒适区
前面都在说翻车,但也不能抹杀 AI 的贡献。基础语法题,包括计数器、参数递增、模块例化、简单 UART 收发、移位寄存器这些,两组模型都拿到了非常高的分。你让它写一个带使能信号和复位信号的 8 位计数器,生成结果基本都是干净可综合的;让它例化多个模块并连线,端口匹配也很少出错。这类代码就是 RTL 工程里的“hello world”,模板明确、语料充足、几乎没有歧义。
我自己的判断是,这些基础样板题恰恰是 AI 写硬件代码目前最大的实用价值。它能把大量重复的、几乎没有智力含量的代码骨架吃掉,把工程师的时间腾出来对付状态机边界和跨时钟域这类真正要命的事情。你非要拿 I2C 从机这类题去跟 AI 死磕,那是跟自己的血压过不去。
5. AI 写 Verilog 的翻车模式:不是玄学,是规律
5.1 可综合性意识缺失
这是我抽样分析错题时最深的感受:AI 生成的 Verilog 里,有相当一部分错误不是“写错功能”,而是“写了 Varilog 里根本不存在的硬件结构”。典型不可综合结构包括:
| 不可综合写法 | 问题表现 | 在我抽样的错题里占比 |
|---|---|---|
| 动态数组/变长数组 | 综合器无法分配未知大小的存储 | 约 8% |
| initial 块给寄存器赋值 | 只在仿真里有意义,综合时被忽略或报错 | 约 15% |
| while / repeat 运行期循环 | 循环次数不是编译期常量,无法展开 | 约 18% |
| fork/join、wait、事件控制 | 仿真建模语言,不支持综合 | 约 6% |
| 函数里递归调用 | 综合器无法推断有限状态硬件 | 约 4% |
这些错误有一个共同来源:AI 是把软件代码的思路搬过来了。软件里while循环轻轻松松,硬件里就要变成迭代状态机;软件里随便声明一个list,硬件就要换成固定深度的数组或 FIFO。这个习惯迁移是 AI 写硬件代码最大的阻碍,而且不是靠提示词加一句“要可综合”就能根治的。
5.2 时序语义的错位
第二类高频错误是时序语义错位。表现有几种:组合逻辑被写成时序逻辑,比如在@(posedge clk)里计算一个本应在组合逻辑完成的结果;同一信号在多个always块里赋值,即多驱动冲突;case语句缺default,导致状态机出现 latch;位宽不匹配被隐式截断,Silently 丢数据。
这类错误为什么致命?因为它不像语法报错那么显眼,功能仿真在短测试向量下甚至能全过,只有把向量拉长、或者做综合 lint 时才会爆发。比如缺失default的状态机,仿真时正好没走到非法状态,综合完就多出一堆意外寄存器。我之前见过一个 AI 写的 SPI 控制模块,就是case漏了default,测试波形前几百个周期一切正常,一旦收到个非法命令字,整个状态机飘到未知状态再也没回来。这种“看似正确”的错误比语法错误危险得多。
5.3 协议边界处理基本靠猜
接口协议题还有一个通病:模型生成的代码对“正常路径”覆盖得还行,对边界条件要么不处理、要么胡乱处理。正常路径是什么?地址匹配、数据连续收发、ACK 按时给。边界条件是什么?总线上出现非法起始条件、刚好在 STOP 前数据变化、从机还没准备好主机就开始读数据、跨时钟域信号产生亚稳态。
原因也不难理解。大模型学的是语言统计规律,它的训练数据里“最常见的那条代码路径”出现次数最多,所以生成结果总是优先覆盖主路径。而硬件接口恰恰是边界条件决定成败的领域,测试平台的激励向量最爱攻击这些犄角旮旯。AI 写了 90% 的正常逻辑,剩下那 10% 的异常处理往往正是芯片量产之后最容易出问题的部分。
5.4 为什么这些错误对硬件是致命的
软件 bug 上线了可以热修复,发个补丁就完事。芯片不行,一个隐蔽的时序错误过了仿真、过了综合,最后流片回来才发现,轻则重新改版多加一轮费用,重则整批芯片报废。所以硬件行业对“正确性”的要求苛刻到近乎偏执。AI 生成代码时的概率性失误,在软件领域可能是能接受的“一次 bug”,在硬件领域就是不能接受的结构性风险。这也是为什么很多老派 RTL 工程师对 AI 写代码保持警惕——不是看不惯新东西,而是他们太清楚一个时序 bug 的代价有多大。
6. 这轮实测之后,我现在的 AI+RTL 工作流
6.1 哪些活可以放心交给 AI
实测跑完,我最直观的变化是把 AI 正式纳入了日常 RTL 开发流程,但只限定在特定环节:
- 模块例化和参数配置代码:100% 交给 AI,生成完我扫一眼端口就够;
- 简单组合逻辑和基础计数器:AI 生成后我补单元测试,基本没有返工;
- testbench 生成:最推荐的一个用法,让 AI 按模块端口写激励和断言,效率提升非常明显;
- 代码注释、文档整理、模块间接口说明:随便交,它写得比我快多了;
- 状态机骨架:可以生成,但状态转移条件必须我亲自核对。
这些任务的共同点是:模板化程度高、出错后果可控、即便有问题也容易在仿真早期暴露。
6.2 哪些活我坚决不放手
与之相对,下面这些活我目前不会让 AI 独立完成:
- 跨时钟域同步和异步 FIFO 设计,亚稳态处理一旦写错,仿真很难复现;
- 高速接口的时序收敛和物理实现,比如 PCIe、DDR 这类 PHY 相关逻辑;
- 安全关键模块,TMR 的表决器可以让 AI 出初稿,但真值表我一定自己验三遍;
- 复位策略和低功耗设计,这俩更多是架构层面的经验,AI 没有那个工程直觉;
- 任何涉及工艺映射、面积功耗折中、特殊库单元选择的代码。
一句话总结:AI 可以当实习生用,让它先出第一版、干脏活累活,但资深工程师的把关环节绝对不能省。
6.3 一个可复制的提示词模板和验证闭环
日常用下来,我最常用的提示词比评测模板更卷,因为还要约束代码风格和可维护性:
请用 Verilog-2001 实现一个 {模块名},功能要求:{具体功能} 接口定义:{完整端口列表} 硬性约束: 1. 全部代码必须可综合,禁止 initial/while/fork/动态数组; 2. 组合逻辑用 always @(*),时序逻辑用 always @(posedge clk), 统一同步低有效复位 rst_n; 3. 所有信号显式指定位宽,禁止 1 bit 隐式截断; 4. 状态机必须带复位到 IDLE,case 必须有 default; 5. 关键信号和状态转换写注释; 6. 最后补充一个最小 testbench,覆盖正常输入和一个边界输入。同时我养成了一个验证闭环习惯:生成代码 -> iverilog 编译 -> 跑 testbench -> Yosys 综合检查 -> 把警告和报错原样喂回模型让它修 -> 再次仿真回归。这个闭环跑下来,比单轮生成的效果稳定得多。我现在甚至试过让多个 AI 角色分工:一个 agent 专门生成 RTL,一个 agent 专门看仿真报错并修改,一个 agent 专门做综合规则检查。实测下来,分工协作比同一个模型反复改同一个文件更不容易“拆东墙补西墙”,因为报错信息喂给同一个模型时它经常修好 A 就弄坏 B。不过要注意别把整份几十页的 log 全塞进上下文,先把关键报错行抽出来再喂,效果会好很多。
6.4 我对“AI 写硬件代码行不行”的最终判断
如果你问我这次 783 道题实测的结论,我会这么说:AI 写硬件代码,在组件级别已经开始“行”了——基础模板、组合逻辑、计数器和测试平台,它已经完全够格当一个称职的初级助手;但在系统级别,尤其是接口协议、跨时钟域、安全冗余和边界处理这些真正考验硬件功底的地方,它还是不行的,盲目放手就是给自己挖坑。
这个结论听起来不够刺激,但它是这次评测真实反映出来的现状。对我个人来说,真实体感是:现在再让我回到没有 AI 助手的 RTL 工作流,我会觉得非常别扭。AI 没有抢走硬件工程师的饭碗,它先把最烦躁的那部分活了。至于以后它能成长到什么程度,就看这套基准下一代出来的时候,通过率曲线能往上爬多少了。