01 FPGA流水灯实验
软件版本:VIVADO2021.1
操作系统:WIN10 64bitaa
硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA
登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!
1 概述
本章课程以大家熟悉的流水灯为例子,详细讲解了VIVADO软件的使用,包括创建FPGA工程,编写Verilog代码,添加管脚约束,最后编译,下载bit文件到开发板测试。对于初学XILINX FPGA的读者请注意,bit文件断电后就丢失了。如果实现上电能够启动程序,需要把BIT文件打包成bin或者MCS文件才可以。由于是基础课程,读者一定不要停留在实现了功能的目的,而是要真正掌握代代码的编写能力,写出优秀的代码。即便是功能实现了,但是不同的代码也代表了不同的水平,作为编程者一定要时刻要求自己写出高水平的代码。
2 新建VIVADO工程
Step1:启动VIVADO,单击Create Project
Step2:单击NEXT
Step3:创建名为fpga_prj的工程到对应的文件目录,文件路径自定义,不能有中文或非法字符,之后单击NEXT
Step4:选择RTL Project并且勾选复选框,之后单击NEXT
Step5:选择芯片的型号和封装速度等级:
100T的选项:Artix-7 系列,封装FGG484,速度等级-2
本文本是比较通用于不同板子的的教程,教程中代码、配图可能与工程中代码稍有不同,请以实际工程为准。
Step:6 单击Finish完成工程创建。
3 添加代码管理文件夹
米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹
01_rtl:放用户编写的rtl代码
02_sim:仿真文件或者工程
03_ip:放使用到的ip文件
04_pin:放fpga的pin脚约束文件或者时序约束文件
05_boot:放编译好的bit或者bin文件(一般为空)
06_doc:放本一些相关文档(一般为空)
4 添加工程文件
Step1:打开VIVADO软件
Step2:单击 Add Sources
Step3:选择单击Add or Create Design Sources 然后单击NEXT
Step4:单击Create File 来创建文件
Step5:创建一个run_led的文件,并且文件类型选择Verilog,路径可以选择存放在工程默认路径下,米联客推荐存放在创建的FPGA工程目录的uisrc\01_rtl目录下,方便管理。
Step6:添加完成后如下图所示之后单击finish完成文件的创建
Step7:继续弹出的对话空中,可以设置一些端口,但是我们现在什么都不做。单击OK
Step8:创建完成后可以看到Design Sources文件夹中有了run_led.v这个文件,这个文件就是我们可以编写verilog程序的文件。
5 Verilog FPGA流水灯实验
双击run_led.v打开流水程序源码,并且修改为如下代码。
`timescale 1ns / 1ns
module run_led# ( parameter T_INR_CNT_SET = 32'd49_999_999 //分频时钟计数,初始时钟过快,人眼观察会导致LED常亮 ) //设置分频系数,降低流水灯的变化速度 ( //该参数可以由上层调用时修改 input I_sysclk, //系统时钟信号 input I_rstn, //全局复位 output [3:0] O_led //LED灯输出 );
reg [3:0] led_r; //设置一个LED的寄存器,用来存储LED信号状态 reg[32:0] t_cnt;
assign O_led = led_r; //将寄存器内信号输出 always @(posedge I_sysclk or negedge I_rstn)begin if(I_rstn==1'b0) //系统复位 t_cnt <= 0; else if(t_cnt == T_INR_CNT_SET) //计数t_cnt达到目标时清零 t_cnt <= 0; else t_cnt <= t_cnt + 1'b1; //否则计数+1 end
always @(posedge I_sysclk or negedge I_rstn)begin //系统时钟的上升沿触发以及复位的下降沿触发 if(I_rstn==1'b0) led_r <= 4'b1000; //设置LED 寄存器的初始状态,1表示灯亮,0表示灯灭 else if( t_cnt == 0) //当计数器计数达到预定值被清零时 led_r <= {led_r[0],led_r[3:1]}; //LED寄存器将最低为左移至最高位,通过{}来完成数据的拼接 end endmodule |
可以看出这是一个空的工程,我们现在要添加代码同时也要添加工程信息。
这样我们就编写好了代码下面还要添加管脚约束文件。
6 添加管脚约束文件
管脚约束文件,即.xdc文件,默认工程路径,会存放在fpga_prj.srcs\constrs_1文件夹中,这里的"fpga_prj.srcs"对应的是创建工程的名称,米联客建议将引脚.xdc文件存放到创建的FPGA工程目录的uisrc\04_pin目录下,方便管理。
添加管脚约束有三种方法,分别是新建XDC PIN脚约束文件、添加已经写好的约束文件、综合后添加管脚约束,用户根据实际情况选择其中一种方法,可以提高工作效率。
6.1 新建XDC PIN脚约束文件
Step1:单击(和添加.v文件一样)
Step2:选择Add or create constraints 然后单击NEXT
Step3:点击Create File,创建一个新的.xdc文件。
Step4:路径选择FPGA工程目录的uisrc\04_pin目录下,方便管理。
Step5:新建的xdc文件出现在工程中。
:uisrc文件管理文件夹中存放的xdc文件
Step6:从工程中打开我们例程提供例的PIN脚文件,对照我们米联客提供的编译好的程序的PIN脚约束文件以及硬件原理图,完成xdc文件PIN脚的约束。
#系统时钟周期约束 create_clock -period 20.000 -name sysclk [get_ports I_sysclk] #时钟管脚物理,物理约束为具体的芯片管脚号约束 set_property PACKAGE_PIN V4 [get_ports I_sysclk] #电平属性为SSTL135,代表了1.35V的IO BANK,电平约束不会改版实际的IO BANK电平,如果电平约束和实际的BANK电平不匹配,可能会导致工作异常 set_property IOSTANDARD SSTL135 [get_ports I_sysclk]
#复位管脚约束,这里绑定到按键输入 set_property PACKAGE_PIN R14 [get_ports I_rstn] #复位输入的电平约束为3V3的IO BANK电平 set_property IOSTANDARD LVCMOS33 [get_ports I_rstn] set_property PULLUP true [get_ports I_rstn]
#绑定led输出管脚到FPGA IO上 set_property PACKAGE_PIN E21 [get_ports {O_led[3]}] set_property PACKAGE_PIN D21 [get_ports {O_led[2]}] set_property PACKAGE_PIN E22 [get_ports {O_led[1]}] set_property PACKAGE_PIN D22 [get_ports {O_led[0]}] set_property IOSTANDARD LVCMOS33 [get_ports {O_led[*]}]
#bit compress set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.COMPRESS true [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design] |
Step7:保存,XDC文件生成完成。
6.2 添加XDC PIN脚约束文件
Step1:单击(和添加.v文件一样)
Step2:选择Add or create constraints 然后单击NEXT
Step3:单击Add Files
Step4:将要添加的.xdc文件添加进来,然后点击OK。
Step5:点击Finish完成约束文件的添加
6.3 综合并添加管脚约束
Step1:打开RTL原理图。
Step2:管脚配置。
选择I/O Planning
根据原理图配置Package Pin
Step3:保存,给XDC文件命名,生成.XDC文件,并保存到fpga_prj\uisrc\04_pin。
创建一个fpga_pin.xdc的文件
7 优化管脚约束文件
为了减少bit文件大小,提高加载速度,在管脚约束文件中添加如下代码:
set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.COMPRESS true [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design] |
8 RTL仿真
8.1 添加仿真测试源码
仿真测试文件存放在工程目录uisrc\02_sim中,源码如下:
`timescale 1ns / 1ns
module tb_run_led();
reg I_sysclk,I_rstn; //时钟信号以及复位信号 wire [3:0] O_led; //仿真的LED 信号
run_led# ( .T_INR_CNT_SET(1000) //设置一个较小的时钟计数参数,可以大大缩小我们仿真需要的时间 ) run_led_inst( .I_sysclk(I_sysclk), //例化时钟接口 .I_rstn(I_rstn), //例化复位接口 .O_led(O_led) //例化led接口 );
initial begin I_sysclk <= 1'b0; //时钟信号的寄存器设置初值 I_rstn <= 1'b0; //复位信号的寄存器设置初值 #100; //延时100个时间单位 I_rstn <= 1'b1; //复位恢复高点平,模拟复位完成 end
always #20 I_sysclk=~I_sysclk; //每过20个时钟周期,模拟的系统时钟信号进行一次翻转
endmodule |
为了减少我们的仿真时长,我们将T_INR_CNT_SET的计数值减小至1000。
8.2 仿真结果
为了方便观察现象,我们将LED的数值转换成二进制。
转换完成后,我们明显看到数值为1的高电平在向右进行偏移,反应到我们的开发板上,就形成了流水效果。
9 编译并且产生bit文件
Step1:单击综合
Step2:单击执行
Step3:单击产生bit
10 下载程序
Step1:给开发板通电,并且连接下载器
Step2:单击OpenTarget 然后单击Auto Connect
Step3:连接成功后如下图所示:
Step4:单击Program Device
Step5:单击选择上图的 FPGA,再单击Program Device,并且选择bit文件
Step6:下载过程
11 实验结果
下载过程下载完成后4个PL端LED流水灯就运行起来了。
12 总结
能做出结果一方面是证明代码工作,但是更重要的是从中学习到知识以及技巧,以及从一个简单的例子发散性思维去思考广泛的问题,举一反三。只有做到这样,对于初学者才能培养学习的兴趣,掌握更多的知识。一套书本,一套教程,给不同的人学习结果往往不一样,关键还是我们要学会思考,不要满足于功能的实现。以后做项目可以快一点,但是做完项目一定要总结,不能做一个丢一个,每次做的都是皮毛,而没有挖掘更深的本质。学习完流水灯实验至少有以下4个要点可以总结,包括IO约束、时钟约束。
12.1 IO约束
通过本文你得自己掌握FPGA IO的管脚约束。我们编写的代码的顶层文件里面,引出的用户IO部分都是需要约束的。约束的意思就是把程序的引出管脚绑定到FPGA芯片上的IO管脚。IO约束可以通过手工填入,也可以通过软件配置。软件配置除了前面综合后点击Open Synthesized Design 窗口也可以通过打开原理图,如下图所示:
修改后记得保存,否则不会更新到XDC约束文件中。当然对于笔者,很多时候我都是直接编辑XDC文件。
12.2 时钟约束
一般我们需要对输入的时钟至少做周期约束,这个很简单,时钟约束的模板为:
create_clock -name <clock_name> -period <period> [get_ports <clock port>] |
create_clock是生成约束约束命令。
name后面表示给这个时钟命名,您可以命为其他您所想要的名字,即使跟代码中的时钟名不同,都是可以的。
period后面表示约定该时钟的周期,默认单位为纳秒
所以我们这里对输入的50M时钟(有的板子是100M时钟)做周期约束,如下:
create_clock -period 20.000 -name sysclk [get_ports I_sysclk] |
12.3 压缩程序
FPGA编译后的程序往往太大,通过压缩,可以减少大小,这样有几点好处:下载速度快,占用FLASH更小的体积,加载速度更快,通过配置FLASH为4线加载,以及配置FLASH的加载时钟。这个很简单,只要加入以下代码:
set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.COMPRESS true [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property BITSTREAM.CONFIG.SPI_FALL_EDGE Yes [current_design] |
如果你是ZYNQ 的FPGA,由于ZYNQ的FLASH不是通过FPGA加载的,而是通过ARM,那么只要以下几行代码:
set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] set_property BITSTREAM.GENERAL.COMPRESS true [current_design] |
如果你是ZYNQ UltarScale+ 的FPGA,那么只要以下几行代码:
set_property BITSTREAM.GENERAL.COMPRESS true [current_design] |
以上是代码各式说明含义呢?
FPGA工程师学习的东西挺多的,我们要还有了解硬件:
1、CFGBVS参数:
当 CFGBVS 连接至Bank 0的VCCO时,Bank 0的VCCO必须为2.5V或3.3V。如果Bank 14或15的I/O用于配置,则这些 Bank(14和15)的VCCO也必须为2.5V或3.3V。在 CFGBVS 连接至GND时,Bank 0的VCCO应为1.8V。如果Bank14或15的I/O用于配置,那么这些Bank14和15的VCCO也必须为 1.8V。
2、CONFIG_VOLTAGE
设置为对应配置电压我们这里是3.3V
3、BITSTREAM.GENERAL.COMPRESS
压缩BIT文件
4、BITSTREAM.CONFIG.CONFIGRATE
设置FLASH配置速度,仅纯FPGA有作用,对于ZYNQ不支持
5、BITSTREAM.CONFIG.SPI_BUSWIDTH
设置FLASH配置的位宽, 仅纯FPGA有作用,对于ZYNQ不支持
6、BITSTREAM.CONFIG.SPI_FALL_EDGE
设置FLASH接口的时钟加载沿, 仅纯FPGA有作用,对于ZYNQ不支持
本文来米联客(milianke),作者:米联客(milianke),转载请注明原文链接:https://www.cnblogs.com/milianke/p/17931101.html