AI编程(二) - 基于OpenSkills的FPGA开发自动化
前置阅读 :AI编程(一) - 从datasheet到Verilog原型设计 - 从datasheet到verilog原型设计/)
本文代码示例基于Windows + Vivado 2024.1环境,理论上适用于Linux版Vivado。
1. 背景 FPGA开发是一个高度流程化的过程,涉及RTL代码编写、约束编写、仿真、综合、实现、比特流生成等多个环节。每个环节都需要手动操作大量的EDA工具命令。这种工作模式存在以下痛点:
Vivado TCL脚本编写繁琐 :Vivado的工程管理几乎完全依赖TCL脚本,参数众多,学习曲线陡峭
约束文件编写枯燥且易错 :XDC约束中的时序路径、IO位置、Clock约束等需要精确对应FPGA器件资源
仿真环境搭建重复 :每个新项目都需要手动创建仿真目录、配置波形文件
综合报告解读困难 :Vivado的综合实现报告结构复杂,人工阅读效率低
本文介绍如何基于Cursor和OpenSkills,将FPGA开发的完整流程封装为可复用的Skills,实现从RTL到Bitstream的全流程自动化 。
2. FPGA开发全流程梳理 在开始自动化之前,先梳理FPGA开发的完整流程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 ┌─────────────────────────────────────────────────────────────┐ │ RTL代码编写 │ │ (Verilog/SystemVerilog/VHDL) │ └─────────────────────────┬───────────────────────────────────┘ │ .v/.sv/.vhd ▼ ┌─────────────────────────────────────────────────────────────┐ │ 仿真验证 │ │ (Vivado Simulator / ModelSim) │ │ RTL仿真 → 功能验证 → 覆盖率统计 → 回归测试 │ └─────────────────────────┬───────────────────────────────────┘ │ 综合通过 ▼ ┌─────────────────────────────────────────────────────────────┐ │ 综合 (Synthesis) │ │ VivadoSynthesis │ │ 时序约束(XDC) → 综合网表 → 时序报告 │ └─────────────────────────┬───────────────────────────────────┘ │ 综合通过 ▼ ┌─────────────────────────────────────────────────────────────┐ │ 实现 (Implementation) │ │ VivadoImplementation │ │ 布局布線 → DRC检查 → 功耗分析 → 时序收敛 │ └─────────────────────────┬───────────────────────────────────┘ │ 实现通过 ▼ ┌─────────────────────────────────────────────────────────────┐ │ 比特流生成 (Bitstream) │ │ write_bitstream │ └─────────────────────────┬───────────────────────────────────┘ │ .bit / .bit.gz ▼ 下载到FPGA板卡
这五个环节中,前三个(RTL编写、仿真、综合)是最适合AI辅助的;后两个(实现、比特流)由于高度依赖器件资源和时序收敛,AI介入的程度有限。
3. 创建FPGA开发Skill 3.1 Skill目录结构 首先创建Skill的基础目录结构:
1 2 3 4 5 6 7 8 fpga-vivado-development/ ├── SKILL.md # 核心技能定义 ├── references/ │ ├── VIVADO_TCL_REFERENCE.md # Vivado TCL命令速查 │ ├── XDC_CONSTRAINT_GUIDE.md # XDC约束编写指南 │ └── VERILOG_STYLE.md # Verilog编码规范 └── scripts/ └── run_simulation.tcl # 仿真脚本模板
3.2 SKILL.md核心定义 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 --- name: fpga-vivado-development description: > 将FPGA开发中的Vivado操作流程封装为可复用的Skills,适用于: - Vivado TCL脚本自动生成 - XDC时序/IO约束编写 - Verilog编码规范检查 - 综合/实现/比特流生成流程自动化 - 综合报告自动解读 当用户提到以下内容时触发: - Vivado, FPGA, Xilinx, 综合, 实现, bitstream, TCL脚本 - XDC约束, 时序约束, IO约束 - FPGA仿真, Verilog, SystemVerilog - Project Navigator, HLS --- 本Skill将FPGA开发中的以下任务自动化: 1 . **TCL脚本生成**:综合、实现、比特流的TCL脚本 2 . **XDC约束生成**:Clock约束、IO约束、时序约束 3 . **代码规范检查**:Verilog/SV编码风格检查 4 . **仿真环境搭建**:仿真脚本+波形配置文件 5 . **报告解读**:综合/实现Timing/Synthesis报告分析 --- Vivado综合是FPGA开发的第一步。以下模板覆盖了常用的综合配置: ```tcl set project_name "fpga_top" set part_name "xc7k325tffg900-2" ;# 根据实际器件修改 set src_dir "./rtl" set constr_dir "./constr" set build_dir "./build/synthesis" create_project $project_name $build_dir -part $part_name -force add_files [glob $src_dir/*.v ]add_files [glob $src_dir/*.sv ]add_files [glob $src_dir/*.vhd ]set_property strategy Flow_PerfOptimized_high [get_runs synth_1 ]add_files -fileset constrs_1 [glob $constr_dir/*.xdc ]set_property used_in_synthesis true [get_files [glob $constr_dir/*.xdc ]]launch_runs synth_1 -jobs 4 wait_on_run synth_1 open_run synth_1 -name synth_1 report_utilization -file "./reports/utilization_synth.rpt" report_timing_summary -file "./reports/timing_synth.rpt" puts "Synthesis completed successfully"
1.2 AI生成TCL的关键要点 让AI生成Vivado TCL脚本时,需要提供以下信息:
1 2 3 4 5 6 7 8 请为以下规格生成Vivado综合TCL脚本: - 器件: xc7k325tffg900-2- 源文件目录: ./rtl (包含*.v和* .sv文件)- 约束目录: ./constr (包含timing.xdc和pins.xdc)- 综合策略: timing_driven - 综合并行任务数: 4 请在综合完成后自动生成utilization和timing_ summary报告
1.3 实现脚本模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 set project_name "fpga_top" set build_dir "./build/synthesis" set constr_dir "./constr" set impl_dir "./build/implementation" open_run synth_1 set_property strategy Performance_ExtraTimingOpt [get_runs impl_1] add_files -fileset constrs_1 [glob $constr_dir /pins_physical.xdc] launch_runs impl_1 -jobs 4 wait_on_run impl_1 open_run impl_1 report_utilization -file "./reports/utilization_impl.rpt" report_timing_summary -file "./reports/timing_impl.rpt" report_power -file "./reports/power_impl.rpt" report_drc -file "./reports/drc_impl.rpt" puts "Implementation completed successfully"
1.4 比特流生成脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 set project_name "fpga_top" open_run impl_1 set_property BITSTREAM.GENERAL.COMPRESS TRUE [get_runs impl_1] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [get_runs impl_1] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [get_runs impl_1] launch_runs impl_1 -to_step write_bitstream -jobs 4 wait_on_run impl_1 puts "Bitstream generated: $project_name.bit"
二、XDC约束自动化 XDC(Xilinx Design Constraints)是Vivado中约束文件的标准格式,包含时序约束和物理约束两大部分。
2.1 Clock约束 Clock是所有时序约束的基础,必须优先定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 create_clock -period 10.000 -name sys_clk [get_ports sys_clk_p] set_property PACKAGE_PIN K17 [get_ports sys_clk_p] set_property IOSTANDARD DIFF_HSTL_I_18 [get_ports sys_clk_p] create_clock -period 8.000 -name gt_ref_clk [get_pins i_gtp0/GTREFCLK0] create_clock -period 10.000 -name virt_clk create_generated_clock -name clk_200m -source [get_ports sys_clk_p] \ -divide_by 2 -multiply_by 20 [get_pins i_mmcm/CLKOUT0]
AI辅助生成Clock约束的prompt示例 :
1 2 3 4 5 6 请为以下时钟系统生成XDC Clock约束: - 输入参考时钟: 25MHz, 引脚G9, LVCMOS33, 差分正端- MMCM输出: - CLKOUT0: 100MHz (给DDR3控制器) - CLKOUT1: 200MHz (给高速串行收发器) - CLKOUT2: 50MHz (给逻辑模块)
2.2 IO约束 IO约束定义引脚位置和电气标准:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 set_property PACKAGE_PIN H5 [get_ports {ddr3_dq[0 ]}] set_property IOSTANDARD SSTL135 [get_ports {ddr3_dq[*]}] set_property PACKAGE_PIN J6 [get_ports ddr3_addr[0 ]] set_property PACKAGE_PIN K7 [get_ports ddr3_we_n] set_property PACKAGE_PIN L8 [get_ports ddr3_ras_n] set_property PACKAGE_PIN T14 [get_ports {led[0 ]}] set_property IOSTANDARD LVCMOS33 [get_ports {led[*]}] set_property PACKAGE_PIN D5 [get_pins i_gtp0/TXP] set_property PACKAGE_PIN C5 [get_pins i_gtp0/TXN] set_property PACKAGE_PIN F6 [get_pins i_gtp0/RXP] set_property PACKAGE_PIN E6 [get_pins i_gtp0/RXN] set_property IOSTANDARD LVDS_25 [get_pins i_gtp0/TXP]
AI辅助生成IO约束的prompt示例 :
1 2 3 4 5 6 7 8 9 10 11 12 13 请为以下接口生成XDC IO约束(器件: xc7k325tffg900-2): 1. FMC HPC接口 (High Pin Count) - 24个LVDS差分对, IOSTANDARD = LVDS_25 - FMC_ LA00_N/P 到 FMC_ LA23_N/P - 参考器件手册Table 4-7: FMC Connector Pinout 2. DDR3接口 - 16位数据总线 DQ[0:15] - 13位地址 ADDR[0:12] - 控制信号: CAS_ N, RAS_N, WE_ N, CS_N, CKE, ODT - 时钟: DQS_ P/N - IOSTANDARD = SSTL135
2.3 时序约束 时序约束是最复杂的部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 set_input_delay -clock virt_clk -max 2.5 [get_ports {pcie_rx[*]}] set_input_delay -clock virt_clk -min 0.5 [get_ports {pcie_rx[*]}] set_input_delay -clock virt_clk -max 2.5 [get_ports {pcie_rx[*]}] -clock_fall set_output_delay -clock virt_clk -max 1.5 [get_ports {pcie_tx[*]}] set_output_delay -clock virt_clk -min 0.0 [get_ports {pcie_tx[*]}] set_false_path -from [get_ports async_reset_n] set_false_path -from [get_clocks clk_200m] -to [get_clocks gt_ref_clk] set_max_delay -from [get_clocks sys_clk] -to [get_clocks clk_200m] 8.000
三、仿真环境自动化 3.1 仿真脚本模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 set project_name "fpga_top" set sim_top "tb_fpga_top" set src_dir "./rtl" set tb_dir "./tb" set wave_dir "./sim/waves" create_project -in_memory -part xc7k325tffg900-2 add_files [glob $src_dir /*.v] add_files [glob $tb_dir /*.v] set_property top $sim_top [get_filesets sim_1] set_property time_precision 1 ps [get_filesets sim_1] launch_simulation run 1 ms close_sim
3.2 Verilog测试台模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 `timescale 1ns / 1ps module tb_fpga_top; logic sys_clk; logic sys_rst_n; initial begin sys_clk = 0 ; forever #5 ns sys_clk = ~sys_clk; end initial begin sys_rst_n = 0 ; #100 ns; sys_rst_n = 1 ; end fpga_top u_dut ( .sys_clk (sys_clk), .sys_rst_n (sys_rst_n), .led (led) ); initial begin $display ("[%0t] Testbench started" , $time ); wait (sys_rst_n === 1'b1 ); @(posedge sys_clk); $display ("[%0t] Test 1: Initialization" , $time ); #1 us; $display ("[%0t] Test 2: Data transfer" , $time ); $display ("[%0t] Testbench finished" , $time ); $finish ; end always @(posedge sys_clk) begin if (led !== 2'b00 ) $display ("[%0t] LED status: %b" , $time , led); end covergroup cg_led @(posedge sys_clk); option.per_instance = 1 ; coverpoint led { bins all_off = {2'b00 }; bins all_on = {2'b11 }; bins mixed = {[2'b01 :2'b10 ]}; } endgroup cg_led cg_inst = new (); endmodule
四、综合报告自动解读 Vivado综合会生成大量报告,AI可以帮助自动解读关键信息:
4.1 关键报告项
报告类型
关键关注点
utilization
LUT/FF使用率、BRAM、DSP、IO利用率
timing_summary
WNS/TNS、最差路径、时钟域穿越
power
动态功耗、静态功耗、时钟网络功耗
drc
设计规则检查错误
4.2 AI解读报告的prompt模板 1 2 3 4 5 6 7 请分析以下Vivado综合报告,重点关注: 1. 资源利用率是否超过80%(如果超过,给出优化建议)2. 是否有未约束的时钟或跨时钟域路径3. 最差时序路径位于哪个模块4. 是否有高扇出的信号导致布线困难以下是utilization报告内容(粘贴报告全文)
4.3 时序违例修复策略 1 2 3 4 5 6 7 8 9 10 11 12 13 根据以下时序违例报告,给出修复优先级排序: Timing Report摘要: - WNS: -0.842ns- TNS: -45.321ns- 最差路径: dut/i_axi_ arb/i_priority_ encoder -> dut/o_crossbar/mux_ 0分析以下可能的优化策略,并按优先级排序: 1. 流水线寄存器插入2. 重定时(Retiming)3. 扇出优化(Carry-Structure)4. 物理约束(Block Placement)5. 综合策略调整
五、完整工作流脚本 将以上所有脚本整合为一个一键执行的工作流:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 set project_name "fpga_top" set part_name "xc7k325tffg900-2" set src_dir "./rtl" set constr_dir "./constr" set build_dir "./build" set rtl_dir "./rtl" puts "\n==== Step 1: Synthesis ====" create_project -force $project_name /synth $build_dir /synth -part $part_name add_files [glob $rtl_dir /*.v] add_files [glob $constr_dir /*.xdc] set_property used_in_synthesis true [get_files [glob $constr_dir /*.xdc]] launch_runs synth_1 -jobs 4 wait_on_run synth_1 if {[get_property PROGRESS [get_runs synth_1]] != "100%" } { error "Synthesis failed. Check logs." } puts "\n==== Step 2: Implementation ====" open_run synth_1 launch_runs impl_1 -jobs 4 wait_on_run impl_1 if {[get_property PROGRESS [get_runs impl_1]] != "100%" } { error "Implementation failed. Check logs." } puts "\n==== Step 3: Bitstream ====" open_run impl_1 set_property BITSTREAM.GENERAL.COMPRESS TRUE [get_runs impl_1] launch_runs impl_1 -to_step write_bitstream -jobs 4 wait_on_run impl_1 puts "\n==== Full flow completed ====" puts "Bitstream: $build_dir/impl_1/$project_name.bit" puts "Reports: $build_dir/"
使用方法 :
1 2 cd D:\fpga\projectvivado -mode batch -source run_full_flow.tcl
六、自定义Skill的工程实践 6.1 项目AGENTS.md配置 在FPGA项目的根目录创建AGENTS.md,让AI了解项目硬件规格:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # AGENTS.md - FPGA项目配置 ## 项目信息 - 器件: xc7k325tffg900-2- 综合工具: Vivado 2024.1- 仿真器: Vivado Simulator## 时钟规格 - 系统时钟: 100MHz (引脚K17)- DDR3参考: 200MHz- PCIe参考: 125MHz## 资源预算 - LUT使用率目标: < 70%- FF使用率目标: < 60%- BRAM使用率目标: < 50%## 编码规范 - 使用SystemVerilog进行接口定义- 时钟复位统一使用: input clk, input rst_n - 状态机使用one-hot编码 - 异步FIFO深度: 16级以上
6.2 自定义Skill脚本 将常用的TCL操作封装为Python脚本,供AI调用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 """ fpga_flow.py - FPGA开发流程辅助脚本 """ import subprocess, os, sysfrom pathlib import Pathclass VivadoFlow : def __init__ (self, project_dir ): self .project_dir = Path(project_dir) self .vivado = "vivado" def run_tcl (self, tcl_script ): """执行TCL脚本""" cmd = [self .vivado, "-mode" , "batch" , "-source" , str (tcl_script)] result = subprocess.run(cmd, capture_output=True , text=True ) return result def read_report (self, report_path ): """读取Vivado报告""" if not Path(report_path).exists(): return None with open (report_path, "r" ) as f: return f.read() def check_timing (self, build_dir ): """检查时序收敛""" report = self .read_report(f"{build_dir} /impl_1/timing_summary.rpt" ) if not report: return {"status" : "unknown" } wns = self ._extract_wns(report) return {"status" : "pass" if wns >= 0 else "fail" , "wns" : wns} def _extract_wns (self, report ): """从报告提取WNS""" for line in report.split("\n" ): if "WNS" in line and "ns" in line: parts = line.split() for i, p in enumerate (parts): if "WNS" in p and i+1 < len (parts): return float (parts[i+1 ].rstrip("ns" )) return 0.0
七、常见问题与解决 7.1 综合报告中LUT使用率过高 原因 :缺乏流水线、状态机未优化、高扇出信号。
解决 :
在关键路径插入流水线寄存器
使用max_fanout属性限制信号扇出
状态机使用one-hot编码
1 2 3 4 5 set_property MAX_FANOUT 16 [get_nets -hier -filter {NAME =~ "ctrl_en*" }] set_property fsm_encoding one_hot [get_cells -hier -filter {FSM_ENCODING}]
7.2 跨时钟域路径违例 原因 :两个时钟域之间缺少CDC约束。
解决 :
使用set_false_path标记异步CDC路径
使用异步FIFO隔离时钟域
添加set_max_delay约束
1 2 3 set_false_path -from [get_clocks clk_a] -to [get_clocks clk_b] set_false_path -from [get_clocks clk_b] -to [get_clocks clk_a]
7.3 DRC检查错误 常见错误 :
IO bank电压冲突
引脚被占用
DCI级联不匹配
1 2 report_property -all [get_iobanks]
7.4 Vivado License获取失败 1 2 $env:XILINXD_LICENSE_FILE = "2100@license-server"
八、总结 本文介绍了基于OpenSkills的FPGA开发自动化工作流:
开发环节
AI辅助价值
自动化程度
RTL代码编写
⭐⭐⭐⭐⭐
高(见AI编程(一))
XDC约束生成
⭐⭐⭐⭐
高
TCL脚本生成
⭐⭐⭐⭐
高
仿真环境
⭐⭐⭐
中
综合报告解读
⭐⭐⭐⭐
高
实现/比特流
⭐⭐
低(时序收敛需人工)
核心经验:
约束先行 :在开始RTL编写之前,先用AI生成完整的XDC约束模板,可以避免后期大量的时序修复工作
脚本版本化 :将所有TCL脚本纳入Git管理,便于追踪变更和回退
报告自动化解读 :让AI负责解读Vivado生成的各类报告,人工只需关注AI标注的重点
参数化设计 :RTL代码中充分使用parameter和localparam,让同一套代码适配不同器件
参考资料
Xilinx Vivado Design Suite User Guide
Vivado Design Suite TCL Documentation
XDC约束指南 (UG903)
AI编程(一) - 从datasheet到Verilog原型设计 - 从datasheet到verilog原型设计/)
Anthropic Claude Code Skills