新手入门 Makefile:FPGA 项目实战教程(三)

新手入门 Makefile:FPGA 项目实战教程(三)



系列文章目录

1、VMware Workstation Pro安装指南:详细步骤与配置选项说明
2、VMware 下 Ubuntu 操作系统下载与安装指南
3、基于 Ubuntu 的 Linux 系统中 Vivado 2020.1 下载安装教程
4、利用 Makefile 高效启动 VIVADO 软件:深入解析与实践
5、新手入门 Makefile:FPGA 项目实战教程(一)
6、新手入门 Makefile:FPGA 项目实战教程(二)

引言

在上一篇6、新手入门 Makefile:FPGA 项目实战教程(二)文章中,介绍了大概的项目结构和基础知识内容,接下来这一章我们将结合实际的工程。


文章目录


五、FPGA 项目实战:LED 闪烁示例

5.1 项目需求和设计概述

我们将通过一个简单的 LED 闪烁项目来演示如何使用 Makefile 进行 FPGA 项目开发。这个项目的目标是在 FPGA 开发板上实现一个 LED 以约 1Hz 的频率闪烁。

设计概述

  • 使用 25 位计数器对系统时钟进行分频。

  • 当计数器达到最大值时,翻转 LED 输出状态。

  • 系统时钟频率假设为 100MHz,因此计数器最大值设为 25,000,000(产生约 1Hz 的闪烁频率)。

5.2 编写 RTL 代码

创建文件src/rtl/top.v,内容如下:

复制代码
module top (
    input clk,
    output reg led
);

reg [24:0] counter;

always @(posedge clk) begin
    if (counter == 25'd25000000) begin
        counter <= 25'd0;
        led <= ~led;
    end else begin
        counter <= counter + 1'b1;
    end
end

endmodule

这个模块实现了一个简单的 LED 闪烁功能,使用 25 位计数器对系统时钟进行分频,产生约 1Hz 的闪烁频率。

5.3 编写约束文件

创建文件src/constraints/led.xdc,内容如下:

复制代码
# 时钟约束
create_clock -name clk -period 10.000 [get_ports clk]
set_property PACKAGE_PIN R4 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]

# LED输出约束
set_property PACKAGE_PIN U18 [get_ports led]
set_property IOSTANDARD LVCMOS33 [get_ports led]

这些约束指定了时钟频率和 LED 输出的物理引脚。请根据实际使用的 FPGA 开发板调整PACKAGE_PIN的值。

5.4 编写 Makefile

创建文件scripts/Makefile,内容如下:

复制代码
# Makefile for Vivado automation
PROJECT_NAME ?= led_blink
VIVADO_VERSION ?= 2020.1
VIVADO_PATH ?= /tools/Xilinx/Vivado/2020.1/bin
BUILD_TCL ?= /home/zfj/fpga_project/led_blink/build_project.tcl

all:
	@echo "Starting Vivado batch mode..."
	@mkdir -p build && cd build && ${VIVADO_PATH}/vivado -mode batch -source ${BUILD_TCL} -tclargs $(PROJECT_NAME)
	@echo "Bitstream generation completed. Output files in build/ directory."

clean:
	@echo "Cleaning project files..."
	@rm -rf build .Xil
	@rm -f ${PROJECT_NAME}.bit
	@echo "Clean complete."

.PHONY: all clean
变量定义
  • PROJECT_NAME:定义项目名称,默认值为led_blink。这里使用了?=条件赋值运算符,表示如果该变量未被定义过,则使用后面的值进行赋值。

  • VIVADO_VERSION:指定 Vivado 版本,默认值为2020.1

  • VIVADO_PATH:指定 Vivado 安装路径下的bin目录,默认值为/tools/Xilinx/Vivado/2020.1/bin

  • BUILD_TCL:指定 Vivado 项目构建脚本的路径,默认值为/home/zfj/fpga_project/led_blink/build_project.tcl

目标定义
  • all目标:

    • 首先输出提示信息Starting Vivado batch mode...,表示开始 Vivado 批处理模式。

    • 使用mkdir -p build创建build目录(-p选项表示如果父目录不存在则一并创建),然后进入build目录。

    • 执行${VIVADO_PATH}/vivado -mode batch -source ${BUILD_TCL} -tclargs $(PROJECT_NAME)命令,以批处理模式运行 Vivado,并指定构建脚本${BUILD_TCL}以及传递项目名称参数$(PROJECT_NAME)。这一步会根据构建脚本的内容创建项目、添加源文件、约束文件,进行综合、实现等操作,最终生成比特流文件。

    • 最后输出提示信息Bitstream generation completed. Output files in build/ directory.,表示比特流文件生成完成,输出文件在build目录中。

  • clean目标:

    • 输出提示信息Cleaning project files...,表示开始清理项目文件。

    • 使用rm -rf build删除build目录及其所有内容(-rf选项表示强制递归删除),rm -rf .Xil删除.Xil目录(该目录通常包含 Vivado 相关的缓存文件),rm -f ${PROJECT_NAME}.bit删除生成的比特流文件(-f选项表示强制删除,不提示)。

    • 最后输出提示信息Clean complete.,表示清理完成。

5.5 编写 Tcl 脚本

创建文件scripts/build_project.tcl,内容如下:

复制代码
# /home/zfj/fpga_project/led_blink/build_project.tcl
set project_name [lindex $argv 0]

# 设置项目路径
set project_dir [file normalize [file dirname [info script]]]
set src_dir ${project_dir}/src
set constr_dir ${project_dir}/constraints

# 创建项目在build目录
create_project -force $project_name ${project_dir}/build -part xc7z020clg400-1
set_property target_language Verilog [current_project]

# 添加源文件
add_files -norecurse [glob -nocomplain ${src_dir}/*.v ${src_dir}/*.vhd]

# 添加约束文件
if {[file exists ${constr_dir}/top.xdc]} {
    add_files -fileset constrs_1 -norecurse ${constr_dir}/top.xdc
} else {
    puts "WARNING: Constraint file not found at ${constr_dir}/top.xdc"
}

# 设置实现策略
set_property strategy Performance_Explore [get_runs impl_1]

# 运行综合与实现
launch_runs synth_1
wait_on_run synth_1

launch_runs impl_1 -to_step write_bitstream
wait_on_run impl_1

# 生成报告
open_run impl_1
report_utilization -file ${project_dir}/build/${project_name}_utilization.rpt
report_timing_summary -file ${project_dir}/build/${project_name}_timing.rpt

# 导出比特流
set bitstream_path ${project_dir}/build/${project_name}.runs/impl_1/*.bit
if {[llength [glob -nocomplain $bitstream_path]] > 0} {
    file copy -force [lindex [glob $bitstream_path] 0] ${project_dir}/${project_name}.bit
    puts "Bitstream copied to: ${project_dir}/${project_name}.bit"
} else {
    puts "ERROR: Bitstream file not found!"
}

# 关闭项目
close_project
exit
变量设置
  • project_name:通过[lindex $argv 0]获取命令行传递的第一个参数,作为项目名称。

  • project_dir:通过[file normalize [file dirname [info script]]]获取当前脚本所在目录的规范化路径,作为项目目录。

  • src_dir:定义源文件目录为${project_dir}/src

  • constr_dir:定义约束文件目录为${project_dir}/constraints

项目创建与设置
  • create_project -force $project_name ${project_dir}/build -part xc7z020clg400 - 1:在${project_dir}/build目录下创建名为$project_name的项目,并指定芯片型号为xc7z020clg400 - 1-force选项表示如果项目已存在则强制覆盖。

  • set_property target_language Verilog [current_project]:设置当前项目的目标语言为 Verilog。

文件添加
  • add_files -norecurse [glob -nocomplain ${src_dir}/*.v ${src_dir}/*.vhd]:添加src_dir目录下所有的.v.vhd文件作为源文件,-norecurse表示不递归查找子目录,[glob -nocomplain ${src_dir}/*.v ${src_dir}/*.vhd]使用glob命令匹配指定的文件。

  • if {[file exists ${constr_dir}/top.xdc]} {... } else {... }:检查${constr_dir}目录下是否存在top.xdc约束文件,如果存在则使用add_files -fileset constrs_1 -norecurse ${constr_dir}/top.xdc将其添加到constrs_1文件集中,否则输出警告信息。

综合与实现
  • set_property strategy Performance_Explore [get_runs impl_1]:设置impl_1运行的实现策略为Performance_Explore,用于优化性能。

  • launch_runs synth_1:启动综合过程,生成网表文件。

  • wait_on_run synth_1:等待综合过程完成。

  • launch_runs impl_1 -to_step write_bitstream:启动实现过程,直到write_bitstream步骤,即生成比特流文件。

  • wait_on_run impl_1:等待实现过程完成。

报告生成与比特流导出
  • open_run impl_1:打开impl_1运行结果。

  • report_utilization -file ${project_dir}/build/${project_name}_utilization.rpt:生成资源利用率报告,并保存到${project_dir}/build/${project_name}_utilization.rpt文件中。

  • report_timing_summary -file ${project_dir}/build/${project_name}_timing.rpt:生成时序总结报告,并保存到${project_dir}/build/${project_name}_timing.rpt文件中。

  • set bitstream_path ${project_dir}/build/${project_name}.runs/impl_1/*.bit:设置比特流文件路径。

  • if {[llength [glob -nocomplain $bitstream_path]] > 0} {... } else {... }:检查是否生成了比特流文件,如果生成了则将其复制到项目目录下,并命名为${project_dir}/${project_name}.bit,同时输出提示信息;如果未找到比特流文件,则输出错误信息。

项目关闭
  • close_project:关闭当前项目。

  • exit:退出 TCL 脚本。

5.6 实战操作步骤

准备工作

确保已经安装了 Vivado 软件,并且其版本与 Makefile 中指定的VIVADO_VERSION一致。同时,将 FPGA 项目的源文件、约束文件等按照上述项目结构放置在相应目录下。

执行 Makefile

  1. 打开终端,进入 FPGA 项目所在目录。

  2. 执行make all PROJECT_NAME=led_blink命令,Makefile 会按照定义的规则,调用 Vivado 以批处理模式运行build_project.tcl脚本,完成项目的创建、源文件添加、约束文件添加、综合、实现、报告生成以及比特流导出等一系列操作。在执行过程中,终端会输出相应的提示信息,可以根据这些信息了解构建过程的进展情况。

  3. 如果构建过程中出现错误,根据错误提示检查源文件、约束文件以及 Makefile 和build_project.tcl脚本的配置是否正确。常见的错误可能包括文件路径错误、语法错误、芯片型号不匹配等。

  4. bit流文件的生成:

清理项目

当需要重新构建项目或者清理生成的文件时,可以执行make clean命令。该命令会删除build目录及其所有内容、.Xil目录以及生成的比特流文件,确保项目处于初始状态,以便进行下一次构建。

生成比特流后,可以使用 Vivado 的硬件管理器将其下载到 FPGA 板卡上,观察 LED 是否开始闪烁。

5.7 以太网接口项目(高级案例)

对于更复杂的项目,例如以太网接口设计,可以采用类似的方法进行 Makefile 和 Tcl 脚本的编写。

5.7.1 项目结构

以太网接口项目的结构如下:

复制代码
ethernet/
├── src/
│   ├── rtl/
│   │   ├── eth_mac.v     # 以太网MAC模块
│   │   └── eth_top.v     # 顶层模块
│   ├── constraints/
│   │   └── eth.xdc       # 约束文件
│   └── ip/
│       └── clk_wiz.xci   # 时钟IP核
├── scripts/
│   ├── build_project.tcl # Tcl脚本
│   └── Makefile         # Makefile文件
└── output/              # 生成的输出文件
5.7.2 Makefile 特点

以太网接口项目的 Makefile 与 LED 项目类似,但可能需要更多的目标和更复杂的 Tcl 脚本,以处理 IP 核和更复杂的约束:

复制代码
# 以太网接口项目的Makefile可能包含以下目标:

# 生成IP核
ipgen:
        @echo "Generating IP cores..."
        $(VIVADO) -mode batch -source $(TCL_SCRIPT) ipgen

# 综合设计
synth: ipgen
        @echo "Synthesizing design..."
        $(VIVADO) -mode batch -source $(TCL_SCRIPT) synth

# 实现设计
impl: synth
        @echo "Implementing design..."
        $(VIVADO) -mode batch -source $(TCL_SCRIPT) impl

在这个例子中,ipgen目标用于生成 IP 核,synth目标依赖于ipgen,确保在综合前已经生成了必要的 IP 核。

未完待续。。。。

相关推荐
范纹杉想快点毕业8 小时前
嵌入式 C 语言编程规范个人学习笔记,参考华为《C 语言编程规范》
linux·服务器·数据库·笔记·单片机·嵌入式硬件·fpga开发
lazyduck19 小时前
从半年到一年的 bug 往事:TCP modbus的卡死与补救
fpga开发·modbus
范纹杉想快点毕业1 天前
《嵌入式 C 语言编码规范与工程实践个人笔记》参考华为C语言规范标准
服务器·c语言·stm32·单片机·华为·fpga开发·51单片机
Chipi Chipi2 天前
FPGA即插即用Verilog驱动系列——串口数据、命令解析
fpga开发
FPGA_ADDA2 天前
基于 AMDXCVU47P HBM2 FPGA 的 2 路 100G 光纤 PCIe 高性能计算加速卡
fpga开发·vu47p·100g光纤pcie·高性能计算加速卡
霖002 天前
高级项目——基于FPGA的串行FIR滤波器
人工智能·经验分享·matlab·fpga开发·信息与通信·信号处理
I'm a winner2 天前
FPGA+护理:跨学科发展的探索(四)
笔记·fpga开发
霖002 天前
FPGA的PS基础1
数据结构·人工智能·windows·git·算法·fpga开发
燎原星火*2 天前
FPGA信号处理实战
fpga开发