Xilinx FPGA 实用开发教程
前言:为什么选择 Xilinx?
Xilinx(现为 AMD 旗下公司)是 FPGA 领域的绝对领导者,其产品线(如 Artix, Kintex, Virtex, Zynq 系列)被广泛应用于工业、通信、人工智能、汽车电子等各个领域,学习 Xilinx FPGA 开发,意味着你掌握了行业标准的技术和工具。

(图片来源网络,侵删)
第一部分:基础知识准备
在开始动手之前,你需要了解一些基本概念。
什么是 FPGA?
- 全称:Field-Programmable Gate Array(现场可编程门阵列)。
- 核心思想:它是一种半定制集成电路,用户可以通过硬件描述语言(HDL)如 Verilog 或 VHDL 来定义其内部逻辑结构,烧录”到芯片中,实现特定的数字电路功能。
- 与 CPU 的区别:
- CPU:执行指令,是“软件”思维,顺序执行。
- FPGA:实现硬件,是“硬件”思维,并行执行,它的逻辑电路是“硬连线”的,因此对于特定任务(如数据包处理、图像算法),速度和效率远高于 CPU。
- 基本结构:由可配置的逻辑块、输入/输出块 和可编程的内部连线 组成。
开发环境
- 核心工具:Vivado Design Suite,这是 Xilinx 的官方集成开发环境,用于设计、综合、实现和调试。
- 版本选择:初学者建议使用 Vivado WebPACK Edition,它免费且功能强大,足以满足大部分学习和开发需求。
- 语言:
- Verilog:语法类似 C 语言,结构清晰,入门相对简单,业界使用更广泛。
- VHDL:语法严谨,类似 Ada 语言,在航空航天和军工领域使用较多。
- 建议:选择一种并精通它,本教程将以 Verilog 为主。
开发板
- 初学者首选:Digilent Basys 3 或 Nexys Video,这两款板子资料丰富,社区活跃,非常适合入门。
- Basys 3:Artix-7 FPGA,资源适中,有 LED、七段数码管、拨码开关、按键、串口等基础外设。
- Nexys Video:Artix-7 FPGA,资源更丰富,还包含了 HDMI 输入/输出、SD 卡、麦克风等高级外设,适合做更复杂的项目。
- Zynq 系列:如 Zybo Z7,这类芯片是 SoC(System on Chip),将 ARM 处理器核心和 FPGA 逻辑集成在同一个芯片上,可以实现软硬件协同设计,是高级应用的方向。
第二部分:标准开发流程
一个典型的 FPGA 项目开发流程如下:
- 设计输入
- 功能仿真
- 设计综合
- 实现
- 时序仿真
- 生成比特流并下载
下面我们用一个最经典的 LED 闪烁灯 项目来走一遍这个流程。
项目目标:让开发板上的一个 LED 灯以 1Hz 的频率闪烁。
步骤 1:设计输入
这是将你的想法转化为代码或原理图的过程,我们使用 Verilog。

(图片来源网络,侵删)
创建新项目
- 打开 Vivado,选择 "Create Project"。
- 给项目命名(如
led_blink),选择一个存放路径。 - 选择 "RTL Project"(寄存器传输级项目),并勾选 "Specify sources"。
- 在 "Add Sources" 界面,选择 "Add or create design sources" -> "Create File",创建一个 Verilog 模块,命名为
led_blink.v。
编写 Verilog 代码
双击 led_blink.v,打开代码编辑器,输入以下代码:
// led_blink.v
// 这是一个简单的 LED 闪烁模块
module led_blink(
input wire clk, // 输入时钟,通常来自板载晶振,如 100MHz
input wire rst_n, // 输入复位,低电平有效,通常来自板载按键
output reg led // 输出,连接到板载 LED
);
// 参数定义
// 系统时钟为 100MHz,周期为 10ns。
// 要实现 1Hz 闪烁,需要计数到 50,000,000 (100MHz / 2 / 1Hz) 次翻转。
parameter CLK_FREQ = 100_000_000; // 100 MHz
paramter CNT_MAX = CLK_FREQ / 2 - 1; // 计数器最大值
// 内部寄存器,用于分频计数
reg [26:0] counter; // 27位计数器,最大可计数 2^27-1,远大于 50M
// 时序逻辑:计数器进程
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
// 复位时,计数器清零,LED 熄灭
counter <= 27'd0;
led <= 1'b0;
end else begin
// 计数器累加
if (counter == CNT_MAX) begin
// 达到最大值,清零计数器并翻转 LED 状态
counter <= 27'd0;
led <= ~led;
end else begin
// 继续计数
counter <= counter + 1;
end
end
end
endmodule
代码解释:
module ... endmodule:Verilog 的基本单元,定义了模块的输入输出。input wire,output reg:定义端口类型。wire是线网,用于组合逻辑;reg是寄存器,用于时序逻辑(在always块中赋值)。parameter:定义常量,方便代码修改和重用。always @(posedge clk or negedge rst_n):这是最核心的时序逻辑块,它表示在时钟的上升沿 或 复位信号的下降沿 时执行块内的代码。if-else:条件判断,实现复位逻辑和计数逻辑。
步骤 2:功能仿真
在将代码下载到硬件之前,必须进行仿真,以验证代码的逻辑功能是否正确,而不用关心时序。

(图片来源网络,侵删)
创建仿真文件
- 在左侧 "Flow Navigator" 窗口,点击 "Simulation" -> "New Simulation Source"。
- 创建一个名为
tb_led_blink.v的文件,类型选择 "Verilog Testbench"。
编写 Testbench 代码 Testbench 是一个“测试环境”,它会实例化你的设计模块,并模拟输入信号。
// tb_led_blink.v
`timescale 1ns / 1ps
module tb_led_blink();
// 定义内部信号,用于连接到 DUT (Design Under Test)
reg clk;
reg rst_n;
wire led;
// 实例化被测试的模块
// .(端口名) (内部信号名)
led_blink uut (
.clk(clk),
.rst_n(rst_n),
.led(led)
);
// 产生时钟信号:周期为 10ns,即 100MHz
initial begin
clk = 0;
forever #5 clk = ~clk; // 每5ns翻转一次
end
// 产生复位和测试激励信号
initial begin
// 初始化
rst_n = 0;
// 等待100个时钟周期后释放复位
#100 rst_n = 1;
// 让仿真运行足够长的时间,观察LED闪烁
// 由于是1Hz,仿真100ms应该能看到大约50次闪烁
#100000000 $finish; // 仿真 100ms 后结束
end
// 监控输出,方便调试
initial begin
$monitor("Time = %t, rst_n = %b, led = %b", $time, rst_n, led);
end
endmodule
运行仿真
- 在 "Simulation" 窗口中,点击 "Run Simulation" -> "Run Behavioral Simulation"。
- Vivado 会启动内置的仿真器(如 xsim),并显示波形图。
- 在波形图中,你可以观察到
clk,rst_n,led的变化,检查led是否在rst_n释放后,大约每 1 秒钟翻转一次,如果逻辑正确,说明你的设计功能没问题。
