概述
本文介绍使用 Git 对 Vivado 和 Vitis 工程进行版本管理和备份的方法。整个流程大致可分为三步:修改工程结构、上传到远程仓库、从远程仓库克隆并重建。
一、将工程结构修改为易于管理的形式
假设你现在的工程是按照 Vivado 默认形式管理的,则需要先按照如下格式对 Vivado 工程文件进行分类:
- doc:工程需要的数据,如 coe 文件、mem 文件等。
- scripts:重建.xpr 和.bd 需要的 tcl 文件。
- src:编写的模块、仿真代码、约束文件和 ip 核配置文件,可细分为 hdl、sim、constrs、ip 等文件夹。
- vitis:Vitis 的工作文件夹,包含所有 Vitis 相关文件。
- work:Vivado 实际工程文件,包括.xpr、编译结果、.xsa 等等,此文件夹不被纳入 Git 管理。
上述分类方法只是一个参考,关键是要将 Vivado 的实际工程文件与需要管理的 source 文件分离。
由于原来的工程的各项源文件索引还是原来的路径,因此需要新建一个工程,将源文件索引到新文件夹的路径下。创建一个新工程,将工程路径放置在新建的 work 文件夹下。
在 add sources 界面,点击 add files,将 hdl 文件导入;点击 add directories,将 ip 文件夹整体导入(单独将.xci 文件用 add files 方式导入更保险)。之后用同样的方式导入 constrs 文件夹下的约束文件,完成工程创建。
进入 Vivado 界面后,用 add or create simulation sources 的方式导入仿真文件。检查所有源文件是否导入完整,如果有缺失,使用 add files 的方式单独导入即可。
如果原工程中有 block design,也需要迁移到新工程中。首先打开原工程,打开需要导出的 block design,通过 file→export→export block design 的方式导出 bd.tcl,并将路径指定在新建的 scripts 文件夹下。
然后打开新工程,在 Tcl Console 中,执行下列命令重建 block design:
source new_project/scripts/bd.tcl
Vivado 会在 src/ip 路径下寻找需要的 ip 核配置文件,完成 block design 的重建。至此完成了工程结构的修改和迁移。
二、将工程上传到远程仓库
通过 file→project→write tcl 导出工程描述文件,路径选择为新建的 scripts 文件夹。
然后就是常规的 Git 流程,新建本地仓库、创建.gitignore 文件(需要把 work 文件夹整个忽略,其他都保留)、添加、提交、上传。后续对工程进行修改后,也是通过常规的 Git 方法进行添加、提交、上传即可。
三、从远程仓库中克隆工程
现在假设你在一台新电脑上,想把远程仓库中的工程克隆下来继续开发。克隆可分为两个部分:Vivado 部分和 Vitis 部分。
1、Vivado 部分
使用 git clone 将工程下载到本地后,工程结构已经变成之前修改好的形式,包括 src、scripts、doc、vitis,可以看到没有 work 文件夹。
下面需要对工程 tcl 文件作一些修改:
-
将 origin_dir 改为脚本所在目录:
- 原文:
set origin_dir "." - 改为:
set script_dir [file dirname [file normalize [info script]]] set origin_dir $script_dir
- 原文:
-
新增 project_root_dir,固定工程根目录:
- 原文:
set orig_proj_dir "[file normalize "$origin_dir/../work"]" - 改为:
set project_root_dir [file normalize "$origin_dir/.."] set orig_proj_dir "[file normalize "$project_root_dir/work"]"
- 原文:
-
将从前目录新建工程,改为固定建到./work:
- 原文:
create_project ${_xil_proj_name_} ./${_xil_proj_name_} -part xczu19eg-ffvc1760-2-i - 改为:
create_project ${_xil_proj_name_} [file normalize "$project_root_dir/work"] -part xczu19eg-ffvc1760-2-i
- 原文:
-
若有些模块导入时采用了绝对路径,要改为相对路径:
- 原文:
if { [get_files pixel_counter.v] == "" } { import_files -quiet -fileset sources_1 /home/aa/lebron/OV2766/src/hdl/pixel_counter.v } - 改为:
if { [get_files pixel_counter.v] == "" } { import_files -quiet -fileset sources_1 [file normalize "$origin_dir/../src/hdl/pixel_counter.v"] }
- 原文:
-
BD 生成从调用脚本内嵌过程,改为调用外部 design_1.tcl:
- 原文:
cr_bd_design_1 "" - 改为:
set bd_script [file normalize "$origin_dir/design_1.tcl"] if { ![file exists $bd_script] } { error "Required block design script not found: $bd_script" } if { [get_files -quiet design_1.bd] eq "" } { source $bd_script }
- 原文:
-
incremental_checkpoint 等路径不再写死旧工程名:
- 原文:
set_property -name "incremental_checkpoint" -value "$proj_dir/mipi_dp_20251104.srcs/utils_1/imports/synth_1/pixel_counter.dcp" -objects $obj - 改为:
set_property -name "incremental_checkpoint" -value "$proj_dir/${_xil_proj_name_}.srcs/utils_1/imports/synth_1/pixel_counter.dcp" -objects $obj
- 原文:
-
修正 src/ip 检查路径层级:
- 原文:
set paths [list \ "[file normalize "$origin_dir/../../../src/ip"]"\ ] - 改为:
set paths [list \ "[file normalize "$origin_dir/../src/ip"]"\ ]
- 原文:
接着修改 bd.tcl:
-
新增工程根目录和默认工程名:
- 原文:
variable script_folder set script_folder [_tcl::get_script_folder] - 改为:
variable script_folder set script_folder [_tcl::get_script_folder] set project_root_dir [file normalize "$script_folder/.."] set default_project_name "mipi_dp_20260325" if { [info exists ::user_project_name] } { set default_project_name $::user_project_name }
- 原文:
-
单独运行 bd.tcl 时,不再创建 myproj/project_1,改为创建到./work:
- 原文:
set list_projs [get_projects -quiet] if { $list_projs eq "" } { create_project project_1 myproj -part xczu19eg-ffvc1760-2-i } - 改为:
set list_projs [get_projects -quiet] if { $list_projs eq "" } { create_project $default_project_name [file normalize "$project_root_dir/work"] -part xczu19eg-ffvc1760-2-i }
- 原文:
-
把 src/ip 加入 IP 仓库:
- 原文:无
- 改为:
set ip_repo_dir [file normalize "$project_root_dir/src/ip"] if { [file isdirectory $ip_repo_dir] } { set current_ip_repo_paths [get_property ip_repo_paths [current_project]] if { [lsearch -exact $current_ip_repo_paths $ip_repo_dir] < 0 } { set_property ip_repo_paths [concat $current_ip_repo_paths [list $ip_repo_dir]] [current_project] } update_ip_catalog -rebuild }
最后打开 Vivado,在 Tcl Console 中输入:
source new_project_clone/scripts/new_project.tcl
2、Vitis 部分
由于对整个 Vitis 工作文件夹进行了克隆,理论上新建一个将 new_project_clone/vitis 作为工作空间的 Vitis 工程就能直接跑。
但这种方式会导致一些临时文件、历史记录也被纳入管理,比较浪费空间。也有分享过如何将工作文件夹区分为 workspace(存储元数据、临时文件、历史记录和日志等)和 working directory(包括应用工程、系统工程、平台工程以及源代码),对 working directory 单独进行管理,但对具体实现细节需自行探索。
更新说明
在跨平台迁移时,发现部分 Tcl 脚本路径处理存在兼容性问题,已优化相关逻辑。可将修改后的脚本封装为通用流程自动执行。

