
写Verilog代码这件事很多人的第一道坎其实不是语法而是“代码写完了怎么把它变成一个能跑、能烧到板子里的东西”。Vivado作为当前最主流的FPGA集成开发环境之一工程创建这一步看似简单但实际踩过坑的人都懂从版本选择、安装目录到源文件管理、仿真设置任何一个环节出问题都会让你在后续折腾半天。这篇笔记继续《Verilog编程笔记》系列专门聊基于Vivado的FPGA工程创建把你从第一次点New Project到最终烧录bit文件的完整链路盘一遍。这个内容适合谁适合刚写完几段Verilog、正准备把代码真正跑上开发板的新手也适合一直在用文本编辑器写代码、对Vivado工程结构不太熟悉的老选手甚至包括那些已经创建过不少工程、但从来没搞明白.runs和.cache到底能不能删的人。核心目标只有一个让你从头到尾把“新建工程→写代码→写Testbench→仿真→综合实现→生成比特流→烧录”这条链路完整跑通并且知道每一步到底在干什么、为什么这么干。1. Vivado装机踩坑实录版本选择与安装细节1.1 Vivado版本到底怎么选免费版够不够用先解决最基础的问题装哪个版本。Vivado现在由AMD原Xilinx维护对外发布的名字一般是Vivado ML Edition。针对学习用途和中小规模FPGA开发官方提供的免费标准版Standard Edition以前叫WebPACK完全够用支持Artix-7、Spartan-7、Zynq-7000这一大类常用中低端器件。我见过不少人一上来就纠结要不要折腾收费的Enterprise版或者到处找“全功能激活文件”。说实话纯学习、DIY项目、毕业设计、普通工业产品原型免费版够你用很久。区分标准很简单一是看器件如果你用的是UltraScale这类高端FPGA那免费版确实不支持二是看IP免费版里一些硬核IP比如部分高速收发器方案会受限但大多数通用的FIFO、乘法器、BRAM IP都随便用。要验证自己手里的芯片受不受支持最稳的办法是在新建工程选择器件时看该型号旁边是否显示“Supported”。版本号怎么选最近“vivado 2025.1下载”热度上来了但我建议不一定追最新稳定优先。2020.2到2023.1之间任意一个成熟版本都行因为网上可参考的资料多、大家踩过的坑都有记录。除非你确实要用某新款器件否则没必要第一个跳进新版本。另外提醒一句Vivado的工程格式一般向上兼容、向下不兼容——你用高版本创建的工程低版本打不开反过来高版本打开老工程时会提示升级。所以团队协作时全组统一一个版本能省掉大量麻烦。1.2 安装环节少折腾的三件事安装本身不算复杂但有几个细节直接决定你后面顺不顺。第一安装路径和工程路径必须纯英文。这不是迷信Vivado内部的编译器、仿真器对非ASCII路径支持很差中文路径经常导致综合报一些莫名其妙的文件错误。有些人的账号名恰好是中文Windows用户目录默认就是中文路径如果你装到C盘用户目录下后面会踩各种灵异问题。解决办法很简单装到C盘根目录下的自定义目录比如C:/Xilinx或者干脆装到独立盘符的英文目录。第二磁盘空间和内存要预留够。下载的离线安装包十几个GB解压安装时还要再占几十GB空间完整安装完的占用通常在30GB以上再加上综合实现的中间文件建议至少留出100GB空闲空间。内存方面8GB能跑但很痛苦16GB算舒服如果你还要开仿真、看波形、同时挂着浏览器32GB也不嫌多。第三许可证问题。免费版需要去AMD官网注册账户下载一个节点锁定的license文件然后在Vivado License Manager里加载。别把这事想复杂了官网流程就是注册账号→填信息→获取标准版许可→下载.lic→导入。就算你暂时不导入licenseVivado也能以评估模式打开但部分功能会受限所以还是建议第一时间配好。还有一个经常在安装过程中弹出来的WinPcap安装项热词里有人提到“vivado winpcap安装失败”。这个组件主要用于某些板级调试和以太网相关功能一般的学习和JTAG下载用不到。如果安装失败大部分情况下可以忽略继续不会影响正常的综合、仿真、烧录流程。但如果后续你要用特定的调试功能再回来单独装一次也是可以的。最后顺带回答一个高频问题Vivado能不能改成中文界面如果你的版本比较新打开Tools Settings General会看到Language下拉菜单里面有English和简体中文可选切换后重启IDE就生效。不过说实话Vivado的中文界面只是表面汉化日志、Tcl控制台、报错信息仍然是英文而且部分术语翻译得比较别扭。我的建议是新手可以先用英文界面配中文教程学习慢慢习惯英文术语毕竟网上绝大多数资料、报错搜索都基于英文关键词。2. 新建工程的完整流程从点按钮开始2.1 Create New Project每一步到底在问什么打开Vivado第一个界面通常会有Create New Project的入口。点进去之后是向导流程很多人一路Next其实每一步都值得看两眼。第一步是Project Name和Project Location。Name必须英文可以带下划线别带中文和空格。Location选一个你清晰的目录比如D:/FPGA_Projects。默认勾选的Create project subdirectory建议保留这样Vivado会在这个目录下再建一个以工程名命名的子文件夹所有工程文件都收在里面不会散落一地。第二步是Project Type选RTL Project。如果你的工程上有IP核设计还可以顺便勾Block Design选项但这属于另一个话题现阶段用最朴素的RTL Project就好。有一个选项叫Do not specify sources at this time意思是先不指定源文件后面自己加。我第一次创建工程就选了它结果后面要手动添加源文件和约束文件反而多绕了一圈。建议新手不要勾在向导里顺手把代码文件加进来省事。第三步是Add Sources和Add Constraints。如果你已经有写好的.v文件直接在这里加没有就跳过后面在Sources面板里创建。约束文件XDC同样有现成的就加没有就留空后面补。接下来是选择目标器件你可以按Board选开发板型号或者按Part选芯片型号比如常见小型开发板用的Artix-7芯片型号往往类似xc7a35tcsg324-1或xc7z010clg400-1根据你的板卡手册来。选错了也能在工程创建后修改但建议一开始就选对否则后面前端分析和时序报告可能不准。全部设置完点FinishVivado会生成工程并提示是否打开。打开后你会看到Sources面板里分了好几类Design Sources是你写的RTL代码Constraints是XDC文件Simulation Sources是仿真用的Testbench文件这三个大类务必分清。很多人把Testbench加到Design Sources里最后综合时报出一堆不可综合的错误其实就是这里没分对。2.2 约束文件XDC的起步认识XDCXilinx Design Constraints是Vivado专用的约束文件作用是把Verilog代码里的端口映射到FPGA真实的物理引脚上同时告诉工具时钟频率是多少。它本质上是Tcl命令序列最简单的约束就两行set_property PACKAGE_PIN P15 [get_ports {clk}] set_property IOSTANDARD LVCMOS33 [get_ports {clk}]意思分别是把端口clk分配到P15这个物理引脚电平标准用3.3V的LVCMOS。如果是个LED输出同理。时钟约束稍微不一样一般用create_clock来声明外部时钟频率比如50MHz晶振create_clock -period 20.000 [get_ports clk]这里的20表示周期20ns对应50MHz。如果你是接到PLL等IP的输入时钟约束方法类似但要额外注意。XDC有个特点它按照从上到下的顺序执行后面的命令可以覆盖前面的同类型设置同一个约束重复写有时候还要加-add选项否则会覆盖而不是追加。新手容易踩的坑是把XDC文件放到Design Sources里面或者把引脚约束写在Verilog代码里比如用LOC属性前者会让工具找不到约束后者在Vivado里虽然能解析但很不推荐。约束文件在Sources面板里有一个单独的Constraints文件夹右键Add Sources选择Add or create constraints就能引入XDC。2.3 工程目录结构谁是谁Vivado创建的工程目录从第一步开始就会自动生成若干子目录和文件。每次有人问我“.runs能不能删”“.cache是什么”我都建议你先看一眼这些目录的实际体积再决定动不动手。目录/文件作用是否可安全删除备注.xpr工程文件工程主入口否双击用它打开工程.srcs你的RTL、约束、Testbench源码否核心资产必须保留.runs综合和实现的运行目录可删删除后需要重新综合实现.cache各类缓存可删删除后工具会自动重建.hw硬件管理器数据可删涉及硬件调试信息一般学习用不到.srcs目录下通常还有sources_1、constrs_1、sim_1这几个二级目录分别对应Design Sources、Constraints和Simulation Sources。也就是说你的工程文件其实都集中在.srcs里。如果某个文件在Vivado界面里被误删了只要它在.srcs里还在重新Add Sources加回来就成所以熟悉目录结构对你恢复工程很有帮助。3. 写好Testbench仿真才有意义3.1 Testbench的正确写法别踩基础坑做FPGA开发仿真和写代码一样重要。热词里“fpga如何正确写testbench”上了榜可见大家普遍意识到这是个问题。Testbench的本质就是一个不带输入输出端口的模块专门用来给DUT被测设计产生激励信号、监测输出。最朴素的结构这样写timescale 1ns/1ps module tb_top; reg clk; reg rst_n; wire led_out; initial clk 1b0; always #10 clk ~clk; initial begin rst_n 1b0; #100; rst_n 1b1; #1000; $finish; end top u_dut( .clk(clk), .rst_n(rst_n), .led_out(led_out) ); endmodule有几个细节新人不注意就容易翻车。第一timescale必须写在文件最开头它定义仿真时间单位是1ns、精度是1ps不写或乱写会导致波形的时间轴含义不清。第二Testbench的端口一定是空的不要像DUT那样写输入输出否则仿真器会报错。第三时钟用always #10 clk ~clk这种写法模拟的是20ns周期的方波想让频率翻倍就把#10改成#5。第四复位激励要给足够的时间让DUT从复位释放到稳定工作时间太短可能看不到正确波形。更复杂的场景我习惯把激励写成task比如定义一个发数据的任务这样在不同测试用例里反复调用代码会干净很多。另一个容易被忽略的点是$finish这个系统任务负责结束仿真如果你没写它仿真会无限跑下去Vivado的波形窗口会一直刷新导致卡顿。3.2 Vivado跑行为仿真完整流程一遍过在Vivado里跑仿真先确认你的Testbench文件被放进了Simulation Sources不是Design Sources。在Sources面板的Simulation Sources下找到sim_1右键Add Sources把tb文件加进去然后右键tb模块选择Set as Top确保仿真入口正确。接着点击Flow Navigator里的Run Simulation选Run Behavioral Simulation。Vivado会调用内置的xsim仿真器默认仿真时间一般只有1000ns如果你自己没写$finish波形窗口会静止在1000ns的位置。这里有个新手高频问题“为什么我点了仿真波形窗口什么都没有”大部分原因是你没有把内部信号拖进波形窗口或者DUT的信号没有被观察。正确做法是在仿真界面的Scope面板里找到DUT的各层模块把reg和wire信号拖到Waveform窗口再点Restart和Run All。改了Testbench之后怎么重新仿真不需要关掉仿真器重启工程在Sources面板的sim_1上右键选Restart再点Run All就能重新跑一轮。如果改了RTL源码则需要重新elaborate或重新启动仿真。Vivado偶尔会弹一些让人看不懂的仿真错误最常见的其实还是文件没添加进去、模块名和文件名不一致、语法里有未声明的信号。别慌看Messages面板里的红色报错定位到具体行号就好。另外一个思路如果你只是写了几行纯组合逻辑或者状态机想快速验证功能不想每次点开巨大的Vivado可以试试Icarus Verilog GTKWave这套轻量组合。分别安装后用命令行iverilog -o sim.vvp tb_top.v top.v vvp sim.vvp gtkwave sim.vcd就能自动编译仿真并打开波形。它没有Vivado那么多图形化辅助但胜在轻快、适合快速迭代我经常用它在Vivado之外做第一轮冒烟测试。4. 综合、实现与比特流从代码到能烧录的Bit文件4.1 把RTL变成比特流完整链路怎么走当你的RTL代码在仿真里表现正常了接下来就是要把它综合成电路、布局布线、生成比特流。Vivado的默认流程很傻瓜写完代码后在Flow Navigator里依次点Run Synthesis、Run Implementation、Generate Bitstream三步走完就能在runs/impl_1目录下看到工程名.bit文件。综合Synthesis是把Verilog转换为逻辑网表的过程。这一步工具会做语法检查、推断寄存器、映射到LUT和FF等基本单元。如果代码有不可综合的写法比如写了一堆延时#10综合时会报warning甚至error。综合完成后会弹一个对话框别急着关你可以点Open Synthesized Design看看综合出的电路结构或者直接点Cancel跳到下一步。Run Implementation是布局布线把网表映射到实际引脚的逻辑单元并完成时钟树等物理设计这一步耗时长、内存占用大小工程几十秒到几分钟大工程就不好说了。出比特流之前的最后一道关卡是时序报告。生成的bit文件能不能稳定跑在目标板卡上关键看Setup和Hold是否满足。在Flow Navigator里运行Report Timing Summary如果出现红色的时序违例negative slack意味着你的时钟频率约束可能太紧了或者代码逻辑路径太长。解决方案通常有优化RTL逻辑、在XDC里放宽约束、调整实现策略而不是死磕代码。工程链路通了以后你后面做滑动窗口滤波、UART收发、FPGA图像处理这类常见FPGA小项目其实都是在同一个工程框架下迭代无非是往Design Sources里多塞几个模块、多写一份Testbench的事。4.2 生成比特流失败最常见的六种原因“vivado生成比特流失败”这个热搜词说明卡在最后一步的人相当多。我自己遇到过的失败原因大致可以归成几类失败现象常见原因处理思路提示时序未收敛时钟约束过紧或逻辑路径过长先看Report Timing Summary确认哪个路径违规从代码和约束两头优化报Place/Route错误引脚约束冲突或资源不足检查XDC是否有重复引脚分配或评估LUT/FF用量是否超过芯片资源提示管脚约束缺失XDC里没有对某些端口做PACKAGE_PIN约束在Constraints里补全所有顶层端口的物理引脚映射License错误使用了免费版不支持的IP或器件更换免费支持的器件/方案或配置合法许可文件路径异常工程或源文件放在中文路径把工程迁移到纯英文路径后重新打开系统内存不足中型工程在高占用环境下容易撑爆关闭无关程序清理缓存或者分步综合实现最常见也最让人头疼的是“时序未收敛”。很多人不理解明明我写的代码看起来没问题怎么就不给我出bit文件其实这是工具在保护你如果时序不满足生成的bit文件烧进板子后器件在目标时钟频率下可能随机出错而且极难调试。所以默认策略下Vivado在有严重时序违例时会拒绝生成比特流。当然你也可以在工程设置里把该错误降级为警告强行出文件但这相当于带病上板除非你只是验证硬件功能否则不推荐。这里还要插一个“生成比特流失败”的另类原因临时文件损坏。有时候你只是改了一行代码重新综合实现就报各种诡异错误这时候右键相应的Run选Reset从头再跑一遍往往就好了。这不叫解决顶多算恢复现场但确实能救急。5. 工程的清理、备份与版本管理5.1 Vivado工程清理的正确姿势搜“vivado工程清理”的人多半是遇到了工程文件夹膨胀的问题。一个只写了几百行Verilog的小工程综合实现跑过几轮之后整个文件夹动辄几个GB其中百分之九十五都是可以重建的中间文件。目录清理的映射关系在第2.3节已经列过这里再强调一下核心原则只保留.xpr和.srcs其他都可以删如果你还想更彻底连.xpr都可以用Write Tcl脚本替代。具体操作很简单在Windows资源管理器里关掉Vivado工程直接删除.runs和.cache两个文件夹再打开工程Vivado会自动重建它们只是之前综合实现的结果丢了需要重跑。如果觉得每次手动删麻烦也可以写一个简单的批处理脚本一键清理把清理前后的工程体积对比一下你会有一种“原来这么多都是垃圾文件”的爽感。更彻底的备份方式是写Tcl脚本重建工程。Vivado提供File Project Write Tcl功能可以把当前工程的所有设置、文件引用、约束都导出成一个.tcl脚本配合你的源码文件将来在任何机器上运行这个脚本就能重新生成一个一模一样的工程。这个方法特别适合交付和跨版本迁移比你打包一个几GB的工程文件夹友好太多。5.2 Git管理FPGA工程的取舍很多FPGA开发者没有用Git的习惯可能是因为觉得工程太大、图形界面太多。实际上只要把生成文件排除掉用Git管理FPGA工程的体验并不差。推荐在工程的根目录放一个.gitignore至少忽略.cache、.runs、.hw、.sim这类生成目录只跟踪.xpr、.srcs源码和约束以及脚本。这样每次改代码、改约束都能留下清晰的版本历史回退也方便。如果担心.xpr文件里记录了太多本地路径那用Write Tcl脚本配合源码文件的方式会更干净。其实还有一个老办法在工程里把RTL、XDC、Testbench这几个文件单独摘出来维护工程文件只是载体必要时删掉重新生成。另外无论用什么方式管理我都强烈建议在工程目录里放一个README.md写下板卡型号、芯片型号、时钟频率、引脚分配说明、烧录方式。很多FPGA工程过两三个月再看连作者自己都记不清当时的设计约束这时候README就是救命稻草。结尾小体会写这篇笔记的过程中我又把几个老工程翻出来看了一遍发现能让我快速上手的工程基本都具备这几个特征目录结构干净、XDC约束完整、Testbench规范、有README。反观那些乱糟糟的工程即使代码写得再妙重新捡起来也要花大量时间。所以我的建议是从第一次创建Vivado工程开始就把这些好习惯立起来路会越走越顺。如果你在创建工程、仿真或生成比特流的过程中遇到其他奇怪的问题欢迎在评论区把报错信息贴出来大家一起分析比一个人对着Messages面板发呆有效率得多。