ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Vivado门级网表导出实战:模式选择、SDF反标与后仿真验证

Vivado门级网表导出实战:模式选择、SDF反标与后仿真验证 1. 先把概念说清门级网表在 Vivado 流程里到底是个什么东西刚上手 Vivado 的朋友经常会被网表这个词绕进去觉得它是个高级玩法跟自己没关系。其实真不是。你在 Vivado 里点一下 Run Synthesis工具在后台做的事情之一就是把你的 RTL 代码翻译成一张由 LUT、触发器、DSP、BRAM、IO 缓冲这些底层原语互相连线组成的电路图这张图落到磁盘上就是门级网表。Vivado 综合、门级网表这三个词是绑在一起的理解不了它你就永远只能停在写代码—点按钮—烧板子的层面出了问题只能靠猜。我从很早的 ISE 时代就开始折腾这东西中间换到 Vivado 又踩了几年坑。说句实话导出网表这件事本身极度简单一条write_verilog就完事了真正难的是知道什么时候该导、导出来的东西长什么样、导完之后怎么验证它是对的。很多人卡在最后一步——网表导出来仿真一跑满屏 X或者编译报一堆找不到的模块最后不了了之。这篇东西我准备按实战顺序讲先搞清楚综合后网表和实现后网表的区别再讲综合策略里哪几个参数会直接改变网表的形态然后是 GUI 和 Tcl 两条导出路径的具体操作接着是网表的验证链路glbl.v、仿真库、SDF 反标最后把我这些年整理的报错速查表和个人踩坑心得一起放出来。适合谁看呢写过一点 Verilog、能跑通基本综合流程现在需要给第三方交付网表、需要做后仿真、需要做形式验证或者需要加速大型系统仿真的同学。纯新手也能看前面概念部分我尽量用大白话。全程用 Vivado 2020.2 之后的版本演示命令在 2022.2 / 2023.2 上我都实测过基本通用。1.1 从 RTL 到门级综合这一步到底干了什么综合Synthesis本质上是三个动作串起来的翻译、优化、映射。翻译阶段把你写的 always 块、assign 语句转成一个跟工艺无关的逻辑网络优化阶段做布尔化简、公共子表达式提取、状态机重编码、资源共享映射阶段才真正跟器件挂钩把逻辑网络塞进 6 输入 LUT把时序逻辑映射成 FDRE/FDCE/FDPE 这类触发器把算术逻辑识别成 CARRY4 和 DSP48E2。所以综合后的网表有两个非常关键的特征。第一个特征是只有 LUT 级结构没有物理延迟信息。你能看到信号经过了几个 LUT 级但每根线走多长、经过几个开关盒综合阶段完全不知道这些要等实现Implementation做完布线才有。第二个特征是名字全变了。你在 RTL 里写的data_cnt_reg[3]综合后可能变成data_cnt_reg[3]_i_4或者干脆并在某个LUT6的输入里只有在特定条件下才保留原名。这两个特征决定了综合后网表的用途边界它可以做功能验证、可以做逻辑等价性检查、可以交付给别人当黑盒但不能用来评估时序。我见过太多人拿着综合后网表跑时序仿真SDF 文件死活生成不出来还以为是工具坏了其实是流程搞错了。1.2 综合后网表 vs 实现后网表一字之差天壤之别这个区别我必须单独拎出来讲因为它是最容易出问题的地方。Vivado 的流程里网表可以在三个时间点生成每个时间点的产物用途完全不同。综合完成synth_design done之后生成的网表包含的是 LUT、FF、DSP、BRAM 这些逻辑原语管脚上会带 IBUF/OBUF时钟上会带 BUFG但没有布局布线信息。它对应的仿真类型是功能后仿真functional post-synthesis simulation也叫零延迟仿真。这个网表可以加密可以给第三方可以做逻辑等价性验证。实现完成route_design done之后物理信息全都有了。这时候导出的网表如果配合write_verilog -mode timesim会带上 specify 块的时序检查结构再配一个从实现结果里write_sdf导出的 SDF 文件才能做时序后仿真timing simulation。这才是报告真实建立保持时间的仿真。还有一个中间态opt_design或place_design之后导出的网表属于部分实现一般只在特定的 ECO 场景里用日常很少碰。时间点网表内容能否拿 SDF典型用途综合后LUT/FF/DSP/BRAM IO 缓冲不能功能后仿、形式验证、网表交付实现后opt/place/route逻辑原语 布局布线信息能时序后仿、功耗分析、门级调试提示write_sdf只能在实现后的 design 上执行。如果你在综合后的 design 上敲这条命令工具会直接报错别怀疑是自己命令写错了。1.3 哪些场景真的需要导出网表不是所有项目都需要这一步我把它归纳成五类场景你可以对号入座。第一类是对外交付。你把设计做成 IP 交给客户又不想暴露 RTL 源码这时候交付加密后的 Verilog 网表或者 EDIF 网表就是标准做法。客户拿到之后能例化、能综合、能仿真但看不到你的实现思路。第二类是大型系统仿真加速。SoC 项目里CPU 核跑 RTL 仿真慢得让人抓狂把它综合成网表再做混合仿真速度能提升一大截因为网表是扁平化的仿真器不用反复解析层次和过程块。第三类是逻辑等价性检查LEC。综合过程可能因为优化改变了逻辑结构形式验证工具需要拿综合前的 RTL和综合后的网表做等价性比对确认功能没被改坏。这也是网表的一个重要用途尤其在有安全要求的场景里。第四类是模块级独立验证。子模块单独综合成网表可以在不带完整顶层的情况下单独仿真缩短迭代周期。第五类是教学和研究。想看清楚 Vivado 把自己的代码变成了什么样的电路-flatten_hierarchy none加网表导出是唯一的路子比看综合报告直观一百倍。2. 动手前必须搞定的工程准备我特别反感那种打开软件就点按钮的教程因为网表导出这事对工程状态的依赖很强。综合设置没配对导出来的网表要么仿真跑不通要么结构乱得看不懂回头重来一遍更费时间。这一章讲导出前必须确认的几件事。2.1 目录结构与版本约定我的习惯是给每个工程配一套固定的目录模板网表相关的东西全部集中管理具体是这样proj/ ├─ rtl/ # 设计源码 ├─ sim/ # testbench 与仿真脚本 │ └─ tb_top.v ├─ constr/ # xdc 约束 │ ├─ timing.xdc │ └─ pin.xdc ├─ scripts/ │ ├─ build_netlist.tcl │ └─ run_sim.tcl ├─ netlist/ # 所有导出的网表产物 │ ├─ funcsim/ │ ├─ timesim/ │ └─ edif/ └─ sim_lib/ # 编译好的仿真库这么搞的理由很实际网表文件动辄几十兆混在工程根目录里几次迭代下来你自己都分不清哪个是哪个版本。按类型分目录、按日期或 commit id 打尾缀比如top_funcsim_20240612.v出了问题回溯起来一目了然。2.2 综合前必须核对的三件事导出网表之前下面这三项我每次都要过一遍缺一项都可能让网表变成废品。第一件顶层模块名确认。综合报告里第一行会打印 Top module name一定要跟你后续write_verilog -cell或者仿真 top 名对得上。新手最容易犯的错是把 testbench 模块设成了顶层综合出来的网表里带着 initial 块和延时语句看着就不对劲。第二件约束文件是否齐全。综合阶段的 xdc 主要管两件事时钟定义和 IO 引脚。综合后网表虽然不带物理延迟但时钟定义会影响 BUFG 的推断和 MMCM 的配置IO 约束会影响 IBUF/OBUF 的插入。约束不全网表结构和实际硬件可能对不上。第三件IP 核是否已经生成。Vivado 的 IP 在综合时会走 OOCOut-of-Context流程单独综合成.dcp文件。如果 IP 还没生成就去综合顶层工具会把 IP 当黑盒处理导出的网表里就是一个空壳模块仿真时必然找不到内部逻辑。2.3 keep_hierarchy 与 flatten_hierarchy 的取舍这一对参数直接决定网表的可读性必须提前想清楚。Vivado 默认的-flatten_hierarchy rebuilt会把整个设计打散重新组织只保留必要的层次边界用于跨层次优化。结果就是网表里几乎看不到你的模块结构全是xxx_LUT6_2这种机器生成的名字。如果你是为了做形式验证或者交付扁平化反而是好事因为它优化得更充分。但如果你是为了看懂网表、或者需要按模块定位问题就必须在 RTL 里对关键模块加属性(* keep_hierarchy yes *) module data_path #( parameter WIDTH 16 )( input wire clk, input wire [WIDTH-1:0] din, output reg [WIDTH-1:0] dout );keep_hierarchy属性会强制工具保留这个模块的边界。实测下来加了属性之后网表里会多出一个层级的壳虽然名字后面还是会带_0后缀但至少能按模块找到对应的逻辑块定位问题方便太多。代价是跨边界的优化会被阻断资源可能多用 1% 到 3%时序紧张的工程要权衡一下。3. 综合策略里的关键参数直接决定网表长什么样Vivado 综合设置界面里选项一大堆大部分保持默认就行但有那么几个会实打实地改变网表形态。这一章我把它们挑出来讲清楚每个参数背后的逻辑以及我自己的取值习惯。3.1 flatten_hierarchy 三种取值的实测对比-flatten_hierarchy有三个取值full、none、rebuilt。我用一个 8 层层次、约 12 万 LUT 的通信基带工程做过对比测试结果如下。取值网表层次LUT 用量综合时间适用场景full完全扁平只剩顶层最少最长交付、形式验证、追求面积none完整保留 RTL 层次最多最短调试、教学、模块定位rebuilt默认保留边界但内部重组接近 full中等大多数常规工程full的优化最激进跨层次常量传播和资源共享能做到底面积和时序通常最好但代价是编译慢、网表可读性为零。none保留了完整层次网表读起来最舒服但优化受限资源可能多用 5% 以上而且在边界处容易出现冗余逻辑。我的建议是交付和形式验证用full或默认的rebuilt需要调试可读性的时候用rebuilt配合 RTL 里的keep_hierarchy属性比整个设计用none划算得多。3.2 keep_equivalent_registers 什么时候该打开这个选项的作用是阻止工具合并功能等价的寄存器。举个具体例子你写了两组寄存器输入完全一样输出也完全一样只是分别驱动不同的下游逻辑。默认情况下 Vivado 会把它们合并成一组省寄存器省功耗。听起来很美好对吧问题出在仿真和调试上。合并之后你在波形里看不到原来那两组信号了后仿真时对着网表找半天也找不到。更麻烦的是如果这两个寄存器在 RTL 里带不同属性比如一个带ASYNC_REG、一个不带合并可能导致跨时钟域处理失效。所以我的经验是含跨时钟域逻辑的设计把-keep_equivalent_registers打开。资源会多用一点但能避免很多诡异的时序问题。纯数据通路、时序宽裕的工程保持关闭就行。3.3 no_iobuf模块级网表仿真的救命开关这个是排在flatten_hierarchy之后的第二大坑。综合的时候Vivado 会给你顶层的每一个 input/output 端口自动插上 IBUF、OBUF 或者 IOBUF。你如果是做整芯片仿真这没问题。但如果你是拿某个子模块单独做网表仿真麻烦就来了子模块端口上多出来的 IBUF/OBUF 需要连接到实际的引脚或者顶层缓冲才能正常工作悬空的话输出就是 X。解决方式就是在综合时加上-no_iobufsynth_design -top data_path -part xc7z020clg400-2 -no_iobuf -flatten_hierarchy rebuilt加了之后顶层端口上不再插入 IO 缓冲网表就是一个纯粹的内部逻辑模块直接例化在 testbench 里就能跑。这个选项在 GUI 里的位置比较隐蔽在 Synthesis Settings 的 More Options 输入框里手写-no_iobuf即可。注意整芯片交付的网表不要加这个选项因为下游需要真实的 IO 缓冲结构。只有模块级仿真才用。3.4 directive 与 retiming 的取舍-directive是 Vivado 给的策略包一个参数顶一堆细碎设置。常用取值里Default是平衡型AreaOptimized_high拼命省面积PerformanceOptimized冲时序RuntimeOptimized缩短综合时间。我的习惯是第一版综合用Default看报告如果时序差得不多比如 WNS 差 0.2ns 以内换PerformanceOptimized再跑一次如果面积超标严重才考虑AreaOptimized_high。注意AreaOptimized_high会打开资源复用代价是组合逻辑路径变长时序压力变大一定要重新看时序报告。-retiming是另一回事它允许工具在组合逻辑之间移动寄存器位置平衡路径延迟。这个功能对数据通路有效但对含有异步复位、或者需要严格保持寄存器一一对应的设计比如跨时钟域同步器要慎用因为搬动位置之后你原来的约束可能就失效了。我对它的使用原则是纯 DSP 数据通路可以开含控制逻辑的模块不开。4. 动手生成网表GUI 与 Tcl 两条路准备工作做完正式导出。我建议你第一次用 GUI 走一遍搞清楚每一步在干什么之后立刻转到 Tcl因为网表导出这件事迟早要进流水线的。4.1 GUI 操作路径流程是这样的左侧 Flow Navigator 打开Synthesis→Open Synthesized Design等 design 加载完右上角会出现 Synthesized Design 标识。然后菜单File→Export→Export Netlist弹出对话框后选择格式Verilog 或 EDIF、输出路径、以及是否加密。这个对话框里有个 Options 标签页能选仿真模式对应-mode参数。我第一次用的时候没注意导出的是默认模式拿去跑仿真发现很多原语没有仿真模型编译报了一堆错。所以这个下拉框一定要按用途选具体见下一小节。导出完成后工具会在 Tcl Console 里回显对应的命令。把这些命令记下来这是转 Tcl 脚本最省事的办法——GUI 本质上就是在帮你拼 Tcl。4.2 Tcl 脚本可复现的导出方式下面这个脚本是我实际在用的放在scripts/build_netlist.tcl用vivado -mode batch -source调用即可# # 综合后网表导出脚本 # 用法: vivado -mode batch -source build_netlist.tcl # set proj_name top_proj set top_module top set part xc7z020clg400-2 set out_dir ./netlist file mkdir $out_dir/funcsim file mkdir $out_dir/edif # 1. 打开综合后的 design open_run synth_1 -name synth_1 # 2. 导出功能仿真网表 write_verilog -force \ -mode funcsim \ $out_dir/funcsim/${top_module}_funcsim.v # 3. 导出默认网表用于形式验证 / 第三方综合 write_verilog -force \ -mode default \ $out_dir/${top_module}_default.v # 4. 导出 stub 网表只有端口声明做黑盒最方便 write_verilog -force \ -mode synth_stub \ $out_dir/${top_module}_stub.v # 5. 导出 EDIF 网表 write_edif -force \ $out_dir/edif/${top_module}.edif # 6. 导出资源报告方便核对 report_utilization -file $out_dir/${top_module}_util.rpt puts Netlist export done 几个细节说明一下。open_run synth_1是把已经综合好的结果加载进内存不需要重新跑综合。-force是覆盖已有文件批处理模式必加不然第二次运行会直接报错中断。资源报告一定要一起导出它是你跟客户或者同事核对网表完整性的第一手凭证。4.3 write_verilog 四种 mode 的区别这是全文最需要记住的一张表。mode生成内容用途需要 unisim 库default纯逻辑网表无仿真结构交付、形式验证、再综合否funcsim含仿真原语与初始化结构功能后仿真是timesim含 specify 时序检查结构时序后仿真需 SDF是synth_stub仅模块端口声明空壳黑盒占位、顶层例化否我踩过的最典型的坑是用default模式导出网表拿去跑 XSIM 仿真编译时报Module FDRE is not defined。原因就是 default 模式假设下游有完整的工艺库仿真器没有。换成funcsim立刻就过了。反过来如果你要给第三方公司做再综合千万别给funcsim因为里面混了仿真专用的结构综合器会报错。给default或者 EDIF。4.4 EDIF 导出与加密交付EDIF 是业界通用的网表交换格式Vivado 的write_edif生成的 EDIF 能被大多数后端工具和仿真器吃下去。如果你交付的对象用的不是 Xilinx 工具链EDIF 通常是首选。加密方面Vivado 支持 IEEE 1735 标准的加密 Verilog。命令形式如下write_verilog -force -mode default \ -encrypt -key ./keys/mykey.txt \ ./netlist/encrypted/top_enc.v密钥文件里放的是 RSA 公钥格式是工具规定的不能自己瞎编。加密后的网表里模块内部被替换成pragma protect包裹的密文下游工具只要有对应私钥就能正常综合和仿真没有私钥就只能看到端口。write_edif也有-security_mode all选项做加密但这属于 Xilinx 的专有加密下游必须也是 Vivado 才能解开通用性反而不如 IEEE 1735。交付前一定要问清楚对方用什么工具链我因为这个来回折腾过一次白白多花了两天。4.5 产物命名与归档最后提一句归档。网表文件是二进制/文本混合的大文件用 Git 直接管会撑爆仓库。我的做法是网表不进版本库但生成网表的脚本和综合日志进版本库同时在网表目录下放一个MANIFEST.txt记录生成时间、Vivado 版本号、综合策略、顶层模块名和 md5 校验值。这样任何时候都能复现出同一份网表审计也方便。5. 网表验证从编译报错到波形正确网表导出来了接下来的问题是它到底对不对我的验证习惯是分三步走——先过编译再看功能最后可选做时序。5.1 glbl.v为什么你的波形第一拍全是 X这是后仿真里出现频率最高的问题没有之一。你把网表编译通过了仿真跑起来了波形一打开所有寄存器输出全是 X等一万个时钟周期也不变。原因在于 Xilinx 的原语模型里有一个全局信号叫 GSRGlobal Set/Reset上电时必须由glbl模块驱动它完成一次初始化。glbl模块不在你的网表里它是一个独立的仿真专用模块位置在$XILINX_VIVADO/data/verilog/src/glbl.v对应的 VHDL 版本是glbl.vhd。你的 testbench 顶层需要例化它module tb_top; reg clk 0; reg rst_n 0; always #5 clk ~clk; initial begin #200 rst_n 1; #10000 $finish; end // 网表顶层 top u_top ( .clk (clk), .rst_n (rst_n) ); // 全局初始化模块不能省 glbl glbl(); endmodule编译的时候glbl.v必须一起加进去仿真顶层elaboration top要写成tb_top glbl两个模块都要指定。这一点几乎所有新手都会漏因为 XSIM 不会报错只是默默给你一堆 X。5.2 用 XSIM 跑功能后仿真完整的命令行流程如下# 1. 编译网表、testbench、glbl xvlog -i $XILINX_VIVADO/data/verilog/src \ ./netlist/funcsim/top_funcsim.v \ ./sim/tb_top.v \ $XILINX_VIVADO/data/verilog/src/glbl.v # 2. 精化指定仿真库和两个顶层 xelab -debug typical \ -L unisims_ver -L secureip -L unimacro_ver \ tb_top glbl -s tb_sim # 3. 运行 xsim tb_sim -R关键在xelab那一行。-L unisims_ver加载基础原语库-L secureip加载加密原语MMCM、PLL、GT 这些都在里面-L unimacro_ver加载宏原语。工程里只要用了 MMCM 或者收发器secureip就是必须的漏了会报找不到模块。如果你用的是第三方仿真器需要先用compile_simlib把库编出来这个命令会把 Xilinx 全部仿真库编译成目标仿真器格式比较耗时但一次编译长期使用。命令大致是compile_simlib -simulator vcs_mx -family all -language all \ -dir ./sim_lib -no_ip_compile编译一次大概十几分钟之后每次仿真直接复用。5.3 时序后仿真与 SDF 反标严格来说综合后网表做时序仿真没有意义因为没有延迟信息。真正的时序仿真要在实现完成之后做步骤是这样# 打开布线完成的 design open_run impl_1 # 导出时序仿真网表 write_verilog -force -mode timesim \ -sdf_anno true \ -sdf_file ./netlist/timesim/top.sdf \ ./netlist/timesim/top_timesim.v # 导出 SDF write_sdf -force ./netlist/timesim/top.sdf-sdf_anno true会把$sdf_annotate系统任务直接写进网表文件里仿真时自动反标延迟省得你手动加。SDF 文件里有 typ典型、min最小、max最大三组延迟值仿真时通过-sdf_typ之类的编译选项选择。做建立时间检查用 max做保持时间检查用 min两个都要跑一遍这是标准做法。时序后仿真跑得极慢一个中等规模设计跑 100us 可能要几个小时。我的建议是只针对关键路径附近的场景跑短时仿真别拿它做全功能回归那是效率灾难。5.4 加速网表仿真的几个实操技巧跑过时序仿真的人都懂那种煎熬。我总结了几个提速手段实测有效。第一把非关键模块换回行为模型。整个系统不需要全部用门级网表只把需要精确验证的模块换成网表其余保持 RTL混合仿真速度能快好几倍。第二减少 dump 的层次和信号量。$dumpvars不加参数会把所有信号全 dump 下来IO 压力巨大。指定只 dump 顶层和关键模块即可。第三合理设置仿真的 timing check 开关。调试阶段可以把$timeformat精度调粗或者临时关闭部分时序检查等逻辑跑通了再打开验证。第四用-debug off编译。XSIM 默认带调试符号关掉之后运行速度有明显提升代价是不能再加波形信号所以只在回归验证阶段用。6. 常见问题与排查速查表这一章是我这些年攒下来的问题库按类型整理遇到问题直接查表。6.1 编译类问题报错信息根本原因解决方式Module FDRE is not defined网表 mode 选成了 default改用-mode funcsim重新导出Cannot find MMCME4_ADV缺少 secureip 库xelab 加-L secureipModule glbl not found没编译 glbl.v把$XILINX_VIVADO/data/verilog/src/glbl.v加入文件列表Duplicate module definition网表和 RTL 同时参与了编译仿真工程里只保留网表版本剔除对应 RTLIOBUF has no simulation model用了-no_iobuf之外的场合确认仿真库编译完整或改用 funcsim第一条和第二条是最常见的。我建议你在编译脚本里把三个-L参数写死别等报错再补。6.2 仿真行为异常类问题现象可能原因排查顺序所有输出持续为 XGSR 未释放 / glbl 没接查 glbl 例化、查复位时序部分寄存器一直为 0寄存器被优化合并打开-keep_equivalent_registers时钟不出波形MMCM 未锁定 / BUFG 未驱动查 LOCKED 信号、查时钟约束输出比 RTL 仿真晚几拍网表插入了额外的流水寄存器对比综合报告检查 retiming 设置BRAM 读出的数据错位读使能/输出寄存器配置差异检查 IP 配置是否与 RTL 一致第三条我特别要强调。MMCM 在仿真里锁定时间跟实际芯片不一样仿真中的锁定时间由模型参数决定通常是几百个时钟周期。如果你的 testbench 只跑了 100 个周期就检查结果肯定看到的是未锁定状态。把仿真时间拉长或者等LOCKED信号拉高后再开始激励。6.3 交付与兼容类问题问题处理方式第三方打开网表报语法错误确认对方工具支持的 Verilog 标准版本必要时加-verilog_std加密网表对方解不开核对密钥文件格式确认对方拿到的是正确私钥EDIF 导入后资源翻倍对方工具把 LUT 拆成了门级属于正常现象网表综合后时序变差层次被展平导致优化空间变化属预期行为网表里找不到某个模块被综合优化掉了检查是否真的被使用最后一条有个排查小技巧在综合日志里搜Removed或者unusedVivado 会明确告诉你哪些逻辑被优化掉了。如果这个模块本来应该被使用那就是它没有被正确例化或者被常量优化剪掉了。7. 几个踩坑之后才明白的道理网表导出这件事我前后断断续续做了七八年有几个认知是踩了坑才建立起来的。第一个是先想清楚用途再选 mode。我早年拿到需求导个网表直接一条write_verilog完事结果对方要的是 EDIF返工。后来我养成了一个习惯导出之前在 README 里写清楚四件事——用途、mode、是否需要加密、接收方工具链。这四件事确认了导出就是纯机械操作。第二个是保留综合日志。日志里记录了每一个参数的实际取值包括你用 GUI 设置的和你写进脚本的。有次客户反馈网表行为跟 RTL 不一致我翻出综合日志发现是-keep_equivalent_registers默认关闭导致两个跨时钟域寄存器被合并了。如果没日志这个问题能查一整天。第三个是网表不是更底层所以更可靠。恰恰相反网表是工具优化后的产物工具可能做了你意想不到的变换。所以任何一次网表交付我都建议配一次形式验证或者至少一次带覆盖率的功能后仿真确认优化没有改变功能语义。第四个也是我最有感触的一条小工程别急着上后仿真。很多同学一听说后仿真更严谨就把每个工程都跑一遍时序仿真结果几十个小时耗进去发现的还是 RTL 仿真阶段就能发现的问题。我的做法是RTL 仿真 静态时序分析能覆盖 95% 的验证需求后仿真只在涉及时钟域交互、异步接口、上电复位这些对延迟敏感的场景才启用而且要针对性地跑短时场景不要全量回归。最后再分享一个我常用的检查小动作。网表导出来之后别急着跑仿真先用文本编辑器打开文件头几行看看有没有module声明、endmodule结尾funcsim模式下应该能看到一堆FDRE、LUT6、CARRY4的例化。同时用grep -c ^ LUT6之类的命令粗略统计一下原语数量跟综合报告里的 LUT 数量对一下。如果差得离谱说明导出过程出了问题。这个动作花不到一分钟但能帮你省下很多弯路。
返回列表