
1. 这个标题到底在说什么“EDA界的Codex赛道挤满钓鱼佬”这个标题第一次看到的时候我愣了两秒。EDA我熟Codex我也知道是什么但把这两个词放一起再加上“钓鱼佬”三个字就有意思了。说白了这是在讲一个正在发生的行业现象用大模型驱动的Agent来做芯片设计自动化尤其是RTL代码生成和验证这条赛道突然涌进来一大批人。这些人里有真正在做产品的也有大量抱着“先占个坑再说”心态的观望者——所谓“钓鱼佬”钓的是风口不是鱼。我自己在数字IC设计这个行当里摸爬滚打了十来年从最早手写Verilog到后来用脚本做代码生成再到现在看各种Agent工具冒出来这个变化是实实在在能感受到的。以前一个模块的RTL从规格到能跑通仿真怎么也得几天。现在有些工具确实能把初版代码生成的时间压缩到小时级别。但问题也来了生成出来的东西能不能用综合能不能过时序能不能收敛这些才是真正卡脖子的地方。这篇文章我想聊的不是某个具体工具怎么装怎么用而是把这个赛道的底层逻辑拆开来看。EDA领域的Agent到底在解决什么问题目前的技术路线有哪些为什么Cadence这样的老牌厂商也在往这个方向走以及一个真正能落地的RTL Agent需要具备哪些能力。如果你是这个领域的工程师或者正在考虑往这个方向做产品又或者只是好奇为什么突然这么多人往这里挤那这篇内容应该能给你一些实在的参考。我尽量不堆术语用我做项目时踩过的坑和实际验证过的思路来讲。有些地方会涉及到具体的工具和流程但重点始终放在“为什么这么做”和“这么做会遇到什么”上面。毕竟这个赛道现在最不缺的就是概念缺的是能把概念变成能跑通的代码和能收敛的时序的人。2. 为什么EDA成了Agent的新战场2.1 从Codex到RTL Agent的演进逻辑Codex这类代码生成模型刚出来的时候大家第一反应是拿来写Python、写JavaScript后来发现写Verilog和VHDL也不是不行。但芯片设计和软件开发有一个本质区别软件代码错了改一行重新部署就行芯片代码错了流片一次几百万美元就没了。这个差异决定了EDA领域的Agent不能只是“生成代码”它必须嵌入到一套严格的验证和检查流程里。我最早接触用大模型辅助写RTL是拿它来生成一些重复性很高的模块比如APB寄存器文件、简单的状态机、FIFO控制逻辑。这些模块结构固定接口明确生成出来的代码质量还不错。但一旦涉及到跨时钟域处理、低功耗设计、或者需要精确时序控制的逻辑生成结果就经常出问题。最常见的是复位逻辑不完整、时钟门控条件写错、以及综合工具推断出锁存器。这些问题在仿真阶段可能看不出来但到了综合和时序分析阶段就会暴露。所以RTL Agent和通用代码Agent的核心区别在于它必须理解硬件描述的语义约束而不仅仅是语法。Verilog的语法很简单但“可综合”和“可收敛”这两个要求把大部分生成结果都挡在了门外。这也是为什么现在做EDA Agent的团队很多都在强调“验证闭环”——生成只是第一步后面的仿真、综合、形式验证才是真正的门槛。2.2 钓鱼佬涌入的背后门槛在降低但天花板没变为什么突然这么多人往这个方向挤我觉得有几个原因。一是大模型的能力确实到了能处理结构化代码的水平尤其是经过微调的模型在特定领域的代码生成上表现不错。二是EDA工具本身在往云端和AI辅助方向走Cadence、Synopsys这些厂商都在推自己的AI功能生态在打开。三是开源EDA工具链越来越成熟像Yosys、Verilator、OpenROAD这些工具给了小团队和个人开发者一个低成本的验证环境。但“钓鱼佬”多不代表鱼好钓。我见过不少项目Demo阶段生成一个加法器或者计数器看起来挺像那么回事但一放到真实项目里就露馅了。真实项目的RTL有几个特点模块间接口复杂、时序约束多、需要和已有的IP集成、还要考虑DFT和低功耗。这些都不是靠一个prompt就能解决的。更关键的是芯片设计对正确性的要求是接近100%的。软件可以有bug打个补丁就行芯片的bug如果没在流片前发现代价是毁灭性的。这就决定了EDA Agent不能是“生成-完成”的模式而必须是“生成-验证-修正-再验证”的循环。这个循环的每一环都需要工具链的支持而工具链的集成恰恰是最耗时的部分。2.3 Cadence们的动作说明了什么Cadence这几年在AI上的投入很大从Allegro X AI到Verisium平台方向很明确把AI嵌入到现有的设计流程里而不是另起炉灶。这个策略我觉得是对的。因为芯片设计流程已经非常成熟了工程师不会为了用一个AI工具就把整个流程推翻重来。AI要做的是在现有流程的某个环节里把效率提上去。比如在验证环节Cadence的Verisium平台用AI来做覆盖率分析和回归测试优化这个就很有实际价值。验证工程师最头疼的就是跑了几天的回归测试覆盖率就是上不去不知道缺了哪些场景。AI可以帮忙分析日志找出覆盖盲区甚至自动生成定向测试用例。这种应用比“AI直接写RTL”要务实得多。但这也意味着做EDA Agent的团队必须对现有工具链有极深的理解。你得知道综合工具在什么情况下会推断出锁存器得知道形式验证工具对哪些代码结构支持不好得知道时序分析时哪些路径是伪路径。这些知识不是从教科书上能学到的必须在一线项目里积累。这也是为什么这个赛道看起来热闹但真正能做出可用产品的团队并不多。3. RTL Agent的核心技术点拆解3.1 代码生成只是冰山一角很多人以为RTL Agent的核心是代码生成其实不是。代码生成只是最上面那一层下面还有一大堆支撑性的工作。我拿一个实际的项目场景来说明假设你要设计一个AXI总线上的DMA控制器用Agent来辅助生成RTL。第一步是理解规格。Agent需要从自然语言描述或者结构化的规格文件中提取出关键信息数据位宽、地址位宽、突发长度、通道数量、是否支持乱序完成等等。这一步看起来简单但实际做起来很容易漏掉隐含约束。比如“支持4KB边界对齐”这个要求如果Agent没理解到位生成出来的地址计算逻辑就会有问题。第二步是架构设计。DMA控制器内部怎么划分模块FIFO深度怎么定读写通道怎么仲裁这些决策会直接影响面积和性能。Agent需要根据给定的面积和频率目标给出一个合理的架构方案。这一步目前大部分Agent还做不好因为架构设计需要权衡的因素太多而且很多经验性的东西很难用规则描述。第三步才是代码生成。到了这一步Agent需要把架构方案翻译成可综合的Verilog或者VHDL。这里面的坑包括复位策略的选择同步复位还是异步复位、时钟域交叉的处理、状态机的编码方式、以及综合指令的插入。每一个选择都会影响最终的PPA功率、性能、面积。第四步是验证。生成完代码Agent需要自动生成测试平台跑仿真检查功能正确性。如果发现问题还要能定位到具体的代码行并修正。这个闭环的自动化程度直接决定了Agent的实用性。3.2 验证闭环Agent能不能自己发现问题验证闭环是RTL Agent最核心也最难做的部分。我试过用一些工具生成RTL然后手动写测试平台去验证发现的问题五花八门。有的是功能错误比如状态机跳转条件写反了有的是时序问题比如在时钟上升沿采样但数据还没稳定还有的是综合问题比如用了不可综合的语句。一个成熟的RTL Agent应该能自动完成这些检查。功能验证可以用形式验证工具来做比如SymbiYosys它可以证明某些属性在所有情况下都成立。时序检查可以用静态时序分析工具比如OpenSTA它可以报告建立时间和保持时间的违例。可综合性检查可以用综合工具比如Yosys它可以报告推断出的锁存器和不可综合的语句。但这些工具的输出结果Agent能不能理解比如形式验证工具报告了一个反例Agent能不能根据反例定位到代码中的问题这需要Agent具备跨工具的推理能力。目前大部分Agent还做不到这一点它们只能在单一工具的输出上做简单的模式匹配。我自己的做法是把验证流程拆成多个阶段每个阶段用不同的工具然后把结果汇总起来做分析。比如先用Verilator做快速功能仿真再用Yosys做综合检查最后用OpenSTA做时序分析。每个阶段的输出都结构化存储方便后续分析。这个流程虽然不如全自动Agent那么“智能”但胜在可控出了问题能快速定位。3.3 工具链集成最脏最累但最重要工具链集成是RTL Agent落地过程中最脏最累的部分但也是最重要的。因为芯片设计不是写代码而是跑流程。一个RTL文件从写完到变成GDSII中间要经过仿真、综合、布局布线、时序分析、DRC/LVS检查等几十个步骤。Agent如果不能和这些步骤无缝衔接那它生成的东西就只是“文本”不是“设计”。我见过一些团队花了很多精力在模型训练上但工具链集成做得很粗糙。结果就是Demo很漂亮但实际用起来处处卡壳。比如生成的代码在仿真器里能跑但到了综合工具里就报错或者综合能过但时序分析发现关键路径延迟太大。这些问题不是模型能力不够而是工具链没打通。工具链集成的难点在于每个工具都有自己的输入格式、输出格式、命令行参数和错误码。而且很多工具是商业软件接口不开放只能通过脚本或者Tcl命令来调用。要把这些工具串起来需要写大量的胶水代码。这些代码不涉及高深的算法但非常考验耐心和细致程度。我的建议是先把一个最小的工具链跑通。比如从Verilog生成开始到Verilator仿真再到Yosys综合最后到OpenSTA时序分析。这个链条跑通了再逐步加入更多的工具和检查项。不要一开始就追求大而全那样很容易陷入细节泥潭。4. 实操搭一个最小可用的RTL Agent验证环境4.1 环境准备与工具选型如果你想自己动手验证一下RTL Agent的可行性我建议从开源工具链开始。下面是我自己常用的一套环境全部可以在Linux或者WSL下跑起来。工具用途安装方式备注Verilator快速功能仿真apt install verilator速度快适合迭代Yosys综合与可综合性检查apt install yosys支持Verilog-2005OpenSTA静态时序分析源码编译需要配置Liberty文件SymbiYosys形式验证pip install sby基于YosysGTKWave波形查看apt install gtkwave配合Verilator使用Python 3.10脚本与Agent逻辑系统自带或conda建议用虚拟环境这套环境的好处是全部免费开源而且社区活跃遇到问题容易找到答案。缺点是文档比较分散有些工具需要自己编译。但我觉得这个投入是值得的因为只有把工具链跑通了才能真正理解RTL Agent的难点在哪里。安装完工具后建议先跑一个最简单的例子一个8位计数器。用Verilator仿真用Yosys综合看看输出是什么。这个过程中你会遇到各种小问题比如Verilator的C测试平台怎么写Yosys的综合脚本怎么配置OpenSTA的时序约束怎么加。这些问题解决一遍之后后面就顺了。4.2 从规格到RTL的生成流程假设我们要生成一个简单的UART发送模块。规格如下波特率可配置数据位8位停止位1位无校验支持奇偶校验可选。这个规格不算复杂但包含了几个关键点参数化设计、状态机控制、以及可选的校验逻辑。第一步把规格写成结构化的描述。我习惯用YAML格式因为可读性好也方便程序解析。module: uart_tx parameters: baud_rate: 115200 clock_freq: 50000000 data_bits: 8 parity: none # none, even, odd stop_bits: 1 interfaces: - name: clk type: input - name: rst_n type: input - name: tx_data type: input width: 8 - name: tx_valid type: input - name: tx_ready type: output - name: tx_out type: output第二步用Agent或者模板生成RTL框架。这一步可以先用简单的模板引擎比如Jinja2把参数填进去。生成的代码大概长这样module uart_tx #( parameter CLK_FREQ 50000000, parameter BAUD_RATE 115200, parameter DATA_BITS 8, parameter PARITY none, parameter STOP_BITS 1 )( input wire clk, input wire rst_n, input wire [DATA_BITS-1:0] tx_data, input wire tx_valid, output reg tx_ready, output reg tx_out ); localparam BAUD_DIV CLK_FREQ / BAUD_RATE; // 状态机定义 localparam IDLE 2b00; localparam START 2b01; localparam DATA 2b10; localparam STOP 2b11; // ... 后续逻辑 endmodule第三步把生成的代码送到Verilator做仿真。这里需要写一个C的测试平台给tx_data和tx_valid施加激励然后观察tx_out的输出波形。如果发现波形不对就回到生成阶段调整。第四步把代码送到Yosys做综合。Yosys会报告综合后的门级网表以及是否有锁存器被推断出来。如果有锁存器说明代码里有不完整的条件分支需要修正。第五步如果有Liberty文件可以用OpenSTA做时序分析。这一步对于简单的UART模块可能不是必须的但对于更复杂的设计时序分析是必不可少的。4.3 验证闭环的自动化脚本上面这些步骤如果手动做效率很低。我写了一个Python脚本来自动化整个流程。核心逻辑是生成代码 - 仿真 - 检查结果 - 如果失败则记录并尝试修正 - 如果成功则进入综合 - 检查综合报告 - 如果失败则记录并尝试修正 - 如果成功则进入时序分析。这个脚本的关键在于错误处理。比如Verilator仿真失败可能是编译错误也可能是仿真结果不符合预期。编译错误比较容易处理直接看错误信息就行。仿真结果不符合预期就比较麻烦需要分析波形找出哪一拍的数据不对。我的做法是在测试平台里加入断言assertion把预期的行为写成断言。如果断言失败Verilator会输出失败的时间和信号值。然后脚本根据这些信息尝试定位到RTL代码中的问题。这一步目前还需要人工介入但至少能把问题范围缩小。import subprocess import yaml def run_verilator(rtl_file, tb_file): cmd fverilator --cc --exe --build -j 4 {rtl_file} {tb_file} result subprocess.run(cmd, shellTrue, capture_outputTrue, textTrue) if result.returncode ! 0: return False, result.stderr return True, result.stdout def run_yosys(rtl_file, top_module): script f read_verilog {rtl_file} synth -top {top_module} stat with open(synth.ys, w) as f: f.write(script) result subprocess.run(yosys synth.ys, shellTrue, capture_outputTrue, textTrue) if Warning: Latch inferred in result.stdout: return False, Latch inferred return True, result.stdout这个脚本还很粗糙但基本框架有了。后面可以逐步加入更多的检查项比如形式验证、功耗估算、面积报告等。5. 常见问题与排查技巧实录5.1 生成代码综合不过怎么办这是最常见的问题。Agent生成的代码在仿真器里跑得好好的一到Yosys或者Design Compiler就报错。我总结了几类典型问题和对应的排查方法。第一类不可综合的语句。比如用了initial块来初始化寄存器或者用了#delay来做延时。这些在仿真里没问题但综合工具不支持。排查方法是看综合工具的错误信息通常会指出具体的行号。修正方法是把初始化逻辑改成复位逻辑把延时改成计数器。第二类锁存器推断。这通常是因为always块里的条件分支不完整。比如一个if没有对应的else综合工具就会推断出锁存器来保持原值。排查方法是看综合报告里的Latch inferred警告然后找到对应的always块补全条件分支。第三类多驱动冲突。同一个信号在多个always块里被赋值或者在同一模块里被连续赋值和过程赋值同时驱动。这种问题在仿真里可能表现为不定态在综合里会直接报错。排查方法是搜索信号名看它在哪些地方被赋值。第四类位宽不匹配。比如把一个32位的信号赋值给16位的信号综合工具会截断或者扩展但可能不是你想要的行为。排查方法是打开综合工具的位宽检查选项让它报告所有的位宽不匹配。下面这个表格是我整理的一些常见综合错误和解决方法错误类型典型报错信息排查方法修正方式不可综合语句Unsupported statement查看报错行号替换为可综合结构锁存器推断Latch inferred检查always块条件分支补全else分支多驱动冲突Multiple drivers搜索信号赋值位置合并驱动源位宽不匹配Width mismatch检查赋值两侧位宽显式位宽转换组合环路Combinational loop检查组合逻辑反馈插入寄存器5.2 仿真通过但时序不收敛这个问题比综合不过更隐蔽。代码能综合功能仿真也正确但时序分析发现建立时间或者保持时间违例。原因通常有几个关键路径太长、时钟约束不合理、或者代码风格导致综合工具优化不力。关键路径太长是最常见的。比如一个32位的加法器如果直接写成assign sum a b综合工具会生成一个行波进位加法器延迟很大。改成流水线结构或者用超前进位加法器就能改善。Agent如果不懂这些微架构层面的优化生成出来的代码时序就很难收敛。时钟约束不合理也会导致时序问题。比如时钟周期设得太短或者输入输出延迟设得不对。这个需要根据实际的接口协议来调整。我的经验是先用一个宽松的约束跑一遍看看最差路径的延迟是多少然后再逐步收紧约束直到找到合理的平衡点。代码风格方面建议避免使用太长的组合逻辑链尽量用寄存器打拍。另外避免在时钟路径上插入组合逻辑比如用assign clk_gated clk enable这种写法会导致时钟树综合出问题。正确的做法是用时钟门控单元或者用使能信号控制数据路径。5.3 Agent生成的代码可读性差怎么处理这个问题经常被忽略但实际影响很大。Agent生成的代码往往能跑但命名不规范、注释缺失、结构混乱。如果后续需要人工修改或者维护成本很高。我的做法是在生成阶段就加入代码规范检查。比如用Verible这个工具来做lint检查命名风格、缩进、行长度等。Verible可以配置规则也可以自动修复一些简单的问题。把Verible集成到生成流程里每次生成完代码就跑一遍lint不通过就重新生成或者自动修复。另外在prompt里明确要求代码风格也很重要。比如要求模块名用snake_case信号名用lowercase寄存器输出加_r后缀组合逻辑加_comb后缀。这些约定虽然简单但能大幅提升代码的可读性。还有一个技巧是让Agent生成代码的同时生成注释。注释内容包括模块功能、端口说明、关键时序路径、以及设计约束。这些注释不仅方便人工阅读也能作为后续验证的参考。5.4 工具链版本兼容性问题开源EDA工具链的一个大问题是版本兼容性。Yosys的不同版本对Verilog的支持程度不一样Verilator的更新也很频繁。我遇到过好几次同一个代码在一个版本上能跑换一个版本就报错。我的建议是固定工具链的版本。用Docker或者conda来管理环境把每个工具的版本号写死在配置文件里。这样虽然不能享受最新的功能但至少能保证可复现性。如果确实需要升级某个工具先在小范围测试确认没问题再全面切换。另外保留每个版本的错误日志也很重要。有时候一个问题在旧版本上出现在新版本上消失了但你不确定是修复了还是被掩盖了。保留日志可以帮助你追溯问题的根源。6. 这个赛道接下来会怎么走6.1 从生成到优化Agent的能力边界在扩展目前大部分RTL Agent还停留在“生成可综合代码”的阶段但接下来肯定会往“生成优化代码”的方向走。什么叫优化代码就是在满足功能和时序的前提下面积更小、功耗更低。这需要Agent理解PPA的权衡关系并且能够根据目标自动调整微架构。比如同样是实现一个FIFO可以用寄存器堆也可以用SRAM。寄存器堆面积大但速度快SRAM面积小但访问延迟高。Agent需要根据FIFO的深度和性能要求自动选择最合适的实现方式。这种决策目前还需要人工介入但未来有可能被Agent自动化。另一个方向是跨模块优化。现在的Agent通常只关注单个模块的生成但真实设计里模块之间的接口和时序是相互影响的。比如一个模块的输出直接连到另一个模块的输入如果第一个模块的输出延迟太大第二个模块的建立时间就可能违例。Agent如果能在生成阶段就考虑到这些跨模块约束生成出来的代码质量会高很多。6.2 钓鱼佬会留下什么“钓鱼佬”这个词虽然带点调侃但我觉得这个现象本身是健康的。任何一个新技术方向起来的时候都会有一大批人涌进来其中大部分会离开但留下的那些人会把这个方向往前推一大步。EDA Agent这个方向最后能留下来的一定是那些真正理解芯片设计流程、并且愿意花时间打磨工具链的人。光有模型能力不够光有工具链也不够必须两者结合。而且芯片设计的周期长、反馈慢做这个方向需要很大的耐心。那些想赚快钱的“钓鱼佬”大概率是钓不到鱼的。但他们的存在也有价值。他们带来了关注度带来了资金也带来了各种尝试。有些尝试会失败但失败的教训同样有价值。我自己就从一些失败的项目里学到了很多比如哪些验证步骤不能省哪些工具集成方式更稳定。6.3 给想入局的人几点实在建议如果你正在考虑往EDA Agent这个方向走不管是做产品还是做研究我有几个建议。第一先把一个完整的流程跑通。不要一上来就搞大而全的平台先从一个小的模块开始把生成、仿真、综合、时序分析这条链路走通。走通之后你自然就知道难点在哪里了。第二重视验证。生成代码只是开始验证才是大头。把验证流程自动化把常见的错误模式整理成检查项这些工作虽然枯燥但价值很大。第三保持对工具的敬畏。EDA工具是几十年积累的产物里面有很多设计上的巧思。不要试图用AI去替代工具而是让AI去更好地使用工具。工具链集成做得好Agent的价值才能发挥出来。第四耐心。芯片设计的反馈周期很长一个项目从开始到流片动辄几个月甚至一年。做这个方向的工具也需要同样的耐心。不要指望几个月就能做出颠覆性的产品先把一个环节做扎实再逐步扩展。我自己在这个方向上还在摸索踩过的坑不少但每次解决一个问题对这个领域的理解就深一层。这个赛道现在很热闹但真正能沉下心来做事情的人永远是最稀缺的。