前言
本节我们要做的是熟练使用 Vivado 创建工程并实现对 LED 灯控制,每秒钟控制开发板上的 LED 灯翻转一次,实现亮、灭、亮、灭的控制。会控制 LED 灯,其它外设也慢慢就会了。
一、PL 和 PS
在FPGA中
- PS:处理系统 (Processing System) :就是与 FPGA 无关的 ARM 的 SOC 的部分。
- PL:可编程逻辑 (Progarmmable Logic): 就是 FPGA 部分。之所以叫 PL,而不是叫 FPGA,用英文简写可能便于理解区分,或者显得比较专业吧。
对于 ZYNQ,就是两大功能块,PS 部分和 PL 部分, ARM 的 SOC 部分,和 FPGA 部分。我们可以通过调用 IP 核,系统会使用 AXI(Advanced eXtensible Interface)接口将 IP 与处理器连接,也就是实现 PL 与 PS 互联。
我们就是要实现基于 PL 的点灯实验。
二、LED 硬件介绍
1、开发板的 PL 部分连接了 1 个红色的用户 LED 灯。这 1 个灯完全由 PL 控制。
2、我们可以根据原理图的连线关系确定 LED 和 PL 管脚的绑定关系。
LED -> R19
3、原理图中以 PS_MIO 开头的 IO 都是 PS 端 IO,不需要绑定,也不能绑定。
三、创建 Vivado 工程
1、启动 Vivado,在 Vivado 开发环境里点击 “Create New Project”,创建一个新的工程
2、弹出一个建立新工程的向导,点击 “Next”
3、在弹出的对话框中输入工程名和工程存放的目录,我们这里取一个 led 的工程名。需要注意工程路径 “Project location” 不能有中文、空格,路径名称也不能太长。点击 next
4、在工程类型中选择 “RTL Project”
5、目标语言 “Target language” 选择 “Verilog”,虽然选择 Verilog,但 VHDL 也可以使用,支持多语言混合编程。
6、点击 “Next”,不添加任何文件
7、在 “Default Part” 选项中,器件家族 “Family” 选择 “Zynq-7000”,封装类型 “Package” 选择 “clg400”,减少我们选择范围。AC7010 在下拉列表中选择 “xc7z010clg400-1”,AC7020 在下拉列表中选择 “xc7z020clg400-2”,“-2” 表示速率等级,数字越大,性能越好,速率高的芯片向下兼容速率低的芯片。
8、点击 “Finish” 就可以完成以后名为 “led” 工程的创建。
9、Vivado 软件界面
四、创建 Verilog HDL 文件
1、点击 Project Manager 下的 Add Sources 图标(或者使用快捷键 Alt+A)
2、选择添加或创建设计源文件 “Add or create design sources”,点击 “Next”
3、选择创建文件 “Create File”
4、文件名 “File name” 设置为 “led”,点击 “OK”
5、点击 “Finish”,完成 “led.v” 文件添加
6、在弹出的模块定义 “Define Module” 中可以指定 “led.v” 文件的模块名称 “Module name”,这里默认不变为 “led”,还可以指定一些端口,这里暂时不指定,点击 “OK”
7、在弹出的对话框中选择 “Yes”
8、双击 “led.v” 可以打开文件,然后编辑
9、编写 “led.v”,这里定义了一个 32 位的寄存器 timer,用于循环计数 0~49999999(1 秒钟),计数到 49999999(1 秒)的时候,寄存器 timer 变为 0,并翻转一个 LED。这样原来 LED 是灭的话,就会点亮,如果原来 LED 为亮的话,就会熄灭。编写好后的代码如下:
`timescale 1ns / 1ps
module led(
input sys_clk,
input rst_n,
output reg led
);
reg[31:0] timer_cnt;
always@(posedge sys_clk or negedge rst_n)
begin
if(~rst_n) begin
led <= 1'b0;
timer_cnt <= 32'd0;
end
else if(timer_cnt >= 32'd49_999_999)
begin
led <= ~led;
timer_cnt <= 32'd0;
end
else
begin
led <= led;
timer_cnt <= timer_cnt + 32'd1;
end
end
endmodule
10、编写好代码后保存,点击菜单 “File -> Save All Files”
五、添加管脚约束
Vivado 使用的约束文件格式为 xdc 文件,xdc 文件里主要是完成管脚的约束,时钟的约束,以及组的约束。这里我们需要对 led.v 程序中的输入输出端口分配到 FPGA 的真实管脚上。
1、点击 “Open Elaborated Design”
2、在弹出的窗口中点击 “OK” 按钮
3、在菜单中选择 “Window -> I/O Ports”
4、在弹出的 I/O Ports 中可以看到管脚分配情况,给 LED 和时钟分配管脚、电平标准,完成后点击保存(ctrl+s)
①、 LED -> R19
②、SYS_CLK -> U18
③、随便选择一个没有接外围设备的引脚,当做 RST 引脚,我这里选择了 T11
RST_N -> T11
④、因此分配情况如下:
6、弹出窗口,要求保存约束文件,文件名我们填写 “led”,文件类型默认 “XDC”,点击 “OK”
此刻我们在这里可以看到多了一个 led.xdc
7、打开刚才生成的 “led.xdc” 文件,我们可以看到是一个 TCL 脚本,如果我们了解这些语法,完全可以通过自己编写 led.xdc 文件的方式来约束管脚
下面来介绍一下最基本的 XDC 编写的语法,普通 IO 口只需约束引脚号和电压。
管脚约束如下:
set_property PACKAGE_PIN "引脚编号" [get_ports “端口名称”]
电平信号的约束如下:
set_property IOSTANDARD "电平标准" [get_ports “端口名称”]
这里需要注意文字的大小写,端口名称是数组的话用 { } 括起来,端口名称必须和源代码中的名字一致,且端口名字不能和关键字一样。
电平标准中 “LVCMOS33” 后面的数字指 FPGA 的 BANK 电压,LED 所在 BANK 电压为 3.3 伏,所以电平标准为“LVCMOS33”。Vivado 默认要求为所有 IO 分配正确的电平标准和管脚编号。
六、添加时序约束
一个 FPGA 设计除了管脚分配以外,还有一个重要的约束,那就是时序约束,这里通过向导方式演示如果进行一个时序约束。
1、点击 “Run Synthesis” 开始综合
2、弹出对话框点击 “OK”
可以看到右上角正在进行综合
3、综合完成以后点击 “Cancel”
4、点击 “Constraints Wizard”
5、在弹出的窗口中点击 “Next”
6、时序约束向导分析出设计中的时钟,这里把 “sys_clk” 频率设置为 50Mhz,然后点击 “Skip to Finish” 结束时序约束向导。
7、点击 “Finish”
8、这个时候 led.xdc 文件已经更新,重新加载文件即可
最下面多了一行约束时钟
七、生成 BIT 文件
1、编译的过程可以细分为综合、布局布线、生成 bit 文件等,这里我们直接点击 “Generate Bitstream”,直接生成 bit 文件。
2、在弹出的对话框中可以选择任务数量,这里和 CPU 核心数有关,一般数字越大,编译越快,点击 “OK”
3、这个时候开始编译,可以看到右上角有个状态信息,在编译过程中可能会被杀毒软件、电脑管家拦截运行,导致无法编译或很长时间没有编译成功。
4、编译中没有任何错误,编译完成,弹出一个对话框让我们选择后续操作,若是接下来想要直接下载到 fpga 上可以选择 “Open Hardware Manger”,跳过下面的八、仿真测试,若是接下来想要先进行仿真一下验证下功能可以继续往下看。我这里先进行一下仿真验证下功能,因此点击 Cancel。
八、仿真测试
仿真在 FPGA 的设计中是很重要的,它可以在前期帮我们验证我们的设计以及功能是否是正确的,可以省去我们后期调试很多的问题。
1、右键 SIMULATION -> simulation Settings
2、仿真时间修改为 50ms(这是一个初始的仿真时间),其他保持不变,点击 “OK”
3、添加源文件
①、点击 “+”
②、添加或者创建仿真源
③、Create File
④、在弹出的窗口输入 File name 为 vtf_led_test
⑤、点击 “Finish”
⑥、弹出窗口再点击 “OK”
⑦、弹出窗口再点击 “Yes”
4、在 Simulation Sources 下面可以看到我们创建的 vtf_led_test.v 文件
5、把下面的测试代码拷贝到 vtf_led_test.v 中
`timescale 1ns/1ps // 时间单位/精度
//------------<模块及端口声明>----------------------------------------
module vtf_led_test;
// Input
reg sys_clk;
reg rst_n;
// Output
wire led;
//------------<例化被测试模块>---------------------------------------
led uut (
.sys_clk(sys_clk),
.rst_n(rst_n),
.led(led)
);
//------------<设置初始测试条件>----------------------------------------
initial
begin
sys_clk = 1'b0; // 初始时钟为0
rst_n = 1'b0;
#5; // 5个时钟周期后
rst_n = 1'b1;
end
//------------<设置时钟>----------------------------------------------
always #10 sys_clk = ~ sys_clk; // 系统时钟周期20ns
endmodule
6、保存后可以看到层级关系
7、进行仿真,左键 Run Simulation -> Run Behavioral Simulation 进行行为级仿真
8、仿真初始界面
9、将 timer_cnt 拖拽到仿真界面 Name 栏目中
10、timer_cnt 右键 -> Radix -> Unsigned Decimal
11、执行 Run All(F3)
12、等待一会儿时间停止运行,搜索 1s 的时候(右键 Go To Time),可以看 led 从 0 变成了 1,如此反复
九、下载测试
1、AC7020 开发平台支持三种启动模式。这三种启动模式分别是 JTAG 调试模式,QSPI FLASH 和 SD 卡启动模式,ZYNQ7000 芯片上电后会检测响应 MIO 口的电平来决定那种启动模式。可以通过核心板上的 J13 的跳线来选择不同的启动模式,我们这里选择链接右边两个引脚,启动模式是 JTAG
2、连接好开发板的 JTAG 接口(仿真器线),给开发板上电(电源线)
3、在 “HARDWARE MANAGER” 界面点击 “Auto Connect”,自动连接设备
4、可以看到 JTAG 扫描到 arm 和 FPGA 内核(图中为 xc7z020,AC7010 开发板实际为 xc7z010_1,AC7020 开发板实际为 xc7z020_1),还有一个 XADC,可以检测系统电压、温度
5、选择 xc7z020_1,右键 “Program Device…”
6、在弹出窗口中点击“Program”
7、等待下载
8、下载完成以后,我们可以看到 1 颗 LED 开始每秒变化一次。(因为未将程序下载到 flash 里面,因此掉电后程序不可保存
)
fpga_led闪烁
我的qq:2442391036,欢迎交流!