[X]关闭

1-4-01 FPGA流水灯实验

文档创建者:uisrc
浏览次数:359
最后更新:2023-12-27
文档课程分类
AMD: FPGA部分(2024样板资料) » 1_START(适配所有型号) » 4-硬件功能案例
软件版本: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
2504661-20231227175806870-264783848.jpg
Step2:单击NEXT
2504661-20231227175807376-1224050664.jpg
Step3:创建名为fpga_prj的工程到对应的文件目录,文件路径自定义,不能有中文或非法字符,之后单击NEXT
2504661-20231227175808043-611416078.jpg
Step4:选择RTL Project并且勾选复选框,之后单击NEXT
2504661-20231227175808449-1429903502.jpg
Step5:选择芯片的型号和封装速度等级:
100T的选项:Artix-7 系列,封装FGG484,速度等级-2
本文本是比较通用于不同板子的的教程,教程中代码、配图可能与工程中代码稍有不同,请以实际工程为准。
2504661-20231227175808833-1159583358.jpg
Step:6 单击Finish完成工程创建。
2504661-20231227175809181-1735055481.jpg
3 添加代码管理文件夹
米联客的代码管理规范,在对应的FPGA工程路径下创建uisrc路径,并且创建以下文件夹
01_rtl:放用户编写的rtl代码
02_sim:仿真文件或者工程
03_ip:放使用到的ip文件
04_pin:放fpga的pin脚约束文件或者时序约束文件
05_boot:放编译好的bit或者bin文件(一般为空)
06_doc:放本一些相关文档(一般为空)
2504661-20231227175809522-1356033295.jpg

4 添加工程文件
Step1:打开VIVADO软件
2504661-20231227175814888-1291332556.jpg
Step2:单击 Add Sources
2504661-20231227175815299-132157593.jpg
Step3:选择单击Add or Create Design Sources 然后单击NEXT
2504661-20231227175815694-1776166266.jpg
Step4:单击Create File 来创建文件
2504661-20231227175816072-438001328.jpg
Step5:创建一个run_led的文件,并且文件类型选择Verilog,路径可以选择存放在工程默认路径下,米联客推荐存放在创建的FPGA工程目录的uisrc\01_rtl目录下,方便管理。
2504661-20231227175821397-631615505.jpg
Step6:添加完成后如下图所示之后单击finish完成文件的创建
2504661-20231227175821777-1588239308.jpg
Step7:继续弹出的对话空中,可以设置一些端口,但是我们现在什么都不做。单击OK
2504661-20231227175822112-326838314.jpg
Step8:创建完成后可以看到Design Sources文件夹中有了run_led.v这个文件,这个文件就是我们可以编写verilog程序的文件。
2504661-20231227175822577-187645283.jpg
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:单击 2504661-20231227175822935-170813301.jpg (和添加.v文件一样)
Step2:选择Add or create constraints 然后单击NEXT
2504661-20231227175823261-1440702849.jpg
Step3:点击Create File,创建一个新的.xdc文件。
2504661-20231227175823631-111441608.jpg

Step4:路径选择FPGA工程目录的uisrc\04_pin目录下,方便管理。
2504661-20231227175823971-1657895801.jpg
Step5:新建的xdc文件出现在工程中。
2504661-20231227175824307-441477556.jpg
:uisrc文件管理文件夹中存放的xdc文件
2504661-20231227175824625-1732882708.jpg
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:单击 2504661-20231227175824967-1957829974.jpg (和添加.v文件一样)

Step2:选择Add or create constraints 然后单击NEXT
2504661-20231227175825439-1240246816.jpg
Step3:单击Add Files
2504661-20231227175825793-222572310.jpg
Step4:将要添加的.xdc文件添加进来,然后点击OK。
2504661-20231227175826173-8873955.jpg
Step5:点击Finish完成约束文件的添加
2504661-20231227175826509-1085710674.jpg
6.3 综合并添加管脚约束
Step1:打开RTL原理图。
2504661-20231227175826854-1918466311.jpg
Step2:管脚配置。
选择I/O Planning
2504661-20231227175827232-677788719.jpg
根据原理图配置Package Pin
2504661-20231227175827590-1221253912.jpg
Step3:保存,给XDC文件命名,生成.XDC文件,并保存到fpga_prj\uisrc\04_pin。
2504661-20231227175827945-1399887916.jpg
创建一个fpga_pin.xdc的文件
2504661-20231227175828273-888593688.jpg

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的数值转换成二进制。
2504661-20231227175828650-2063471467.jpg
转换完成后,我们明显看到数值为1的高电平在向右进行偏移,反应到我们的开发板上,就形成了流水效果。
2504661-20231227175828977-1875317411.jpg
9 编译并且产生bit文件
Step1:单击综合
Step2:单击执行
Step3:单击产生bit
2504661-20231227175829300-1655781483.jpg
2504661-20231227175829645-1942727281.jpg
10 下载程序
Step1:给开发板通电,并且连接下载器
Step2:单击OpenTarget 然后单击Auto Connect
2504661-20231227175829984-146765414.jpg
Step3:连接成功后如下图所示:
2504661-20231227175830318-2124052647.jpg
Step4:单击Program Device
2504661-20231227175830786-765723990.jpg

Step5:单击选择上图的 FPGA,再单击Program Device,并且选择bit文件
2504661-20231227175831146-1391706710.jpg
Step6:下载过程
2504661-20231227175831540-260199554.jpg
11 实验结果
2504661-20231227175831890-797214691.jpg
下载过程下载完成后4个PL端LED流水灯就运行起来了。
12 总结
能做出结果一方面是证明代码工作,但是更重要的是从中学习到知识以及技巧,以及从一个简单的例子发散性思维去思考广泛的问题,举一反三。只有做到这样,对于初学者才能培养学习的兴趣,掌握更多的知识。一套书本,一套教程,给不同的人学习结果往往不一样,关键还是我们要学会思考,不要满足于功能的实现。以后做项目可以快一点,但是做完项目一定要总结,不能做一个丢一个,每次做的都是皮毛,而没有挖掘更深的本质。学习完流水灯实验至少有以下4个要点可以总结,包括IO约束、时钟约束。
12.1 IO约束
通过本文你得自己掌握FPGA IO的管脚约束。我们编写的代码的顶层文件里面,引出的用户IO部分都是需要约束的。约束的意思就是把程序的引出管脚绑定到FPGA芯片上的IO管脚。IO约束可以通过手工填入,也可以通过软件配置。软件配置除了前面综合后点击Open Synthesized Design 窗口也可以通过打开原理图,如下图所示:
2504661-20231227175832475-1395499821.jpg
修改后记得保存,否则不会更新到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不支持

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则