新手入门 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 核。

未完待续。。。。

相关推荐
I'm a winner11 小时前
基于Xilinx FPGA的LVDS高速串行通信系统(三)--数据训练及握手机制【文末源码】
fpga开发
upper202013 小时前
coremark移植坑之-nostartfiles -nostdlib参数
学习·fpga开发·coremark移植·riscv设计
Eloudy20 小时前
Vivado 纯命令行构建 FPGA 项目教程
fpga开发
Rambo.xia21 小时前
AXI跨时钟域与数据一致性——CDC FIFO深度不够、写后读冒险、多Master仲裁、乱序返回,出了Bug根本查不出来
fpga开发·bug
upper202021 小时前
FPGA部署卷积神经网络识别MINST图片
fpga开发·卷积神经网络·minst·minst识别·部署神经网络·神经网络识别图片
你是我的解忧王子1 天前
嵌入式 ADC采样 原始数据分析上层(平均值 波动率 正态分布 线性补偿 系统误差)
fpga开发·数据挖掘·数据分析
9527华安2 天前
FPGA纯verilog代码ISP图像处理培训教程,基于IMX214,提供工程源码+视频教程+FPGA开发板
图像处理·fpga开发·isp·imx214·mipi
千寻xun3 天前
二、实战篇-NVME SSD控制之ZYNQ实现(六)-读写NVME SSD硬盘数据
fpga开发·nvme·nvme ssd
千寻xun3 天前
二、实战篇-NVME SSD控制之ZYNQ实现(三)
fpga开发·nvme ssd·nvme协议
忆锦紫3 天前
vivado报错及解决【十】
fpga开发·fpga·vivado