01AMD FPGA vitis-vivado软件快速入门课程

软件版本:vitis2021.1(vivado2021.1)

操作系统:WIN10 64bit

硬件平台:适用AMD-XILINX A7/K7/Z7/ZU/KU系列FPGA

登录"米联客"SOC|SOC社区-www.uisrc.com视频课程、答疑解惑!

1 概述

本实验通过一个基本的FPGA工程创建,编译,下载测试,演示如何快速上手AMD-FPGA开发工具软件vitis-vivado。本实验通过vivado创建一个PLL工程,通过PLL输出的时钟驱动计数器,使用计数器的高2bits驱动LED。

下面先了解下什么是PLL:

PLL 的英文全称是 Phase Locked Loop,即锁相环,是一种反馈控制电路。PLL 对时钟网络进行系统级的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。AMD-XILINX 7 系列器件中的时钟资源包含了时钟管理单元 CMT,每个 CMT 由一个 MMCM 和一个 PLL 组成。对于一个简单的设计来说,FPGA 整个系统使用一个时钟或者通过编写代码的方式对时钟进行分频是可以完成的,但是对于稍微复杂一点的系统来说,系统中往往需要使用多个时钟和时钟相位的偏移,且通过编写代码输出的时钟无法实现时钟的倍频,因此学习 AMD-XILINX MMCM/PLL IP 核的使用方法是我们学习 FPGA 的一个重要内容。本章我们将通过一个简单的例程来向大家介绍一下 MMCM/PLL IP 核的使用方法。

2 新建VIVADO工程

Step1:启动VIVADO,单击Create Project

Step2:单击NEXT

Step3:创建名为fpga_prj的工程到对应的文件目录,文件路径自定义,不能有中文或非法字符,之后单击NEXT

(路径涂掉是为了教程的通用性,米联客板卡比较多,教程图片通用,客户选择自己电脑上的路径)

Step4:选择RTL Project并且勾选复选框,之后单击NEXT

Step5:选择芯片的型号和封装速度等级:

35T的选项:Artix-7 系列,封装FGG484,速度等级-2

100T的选项:Artix-7 系列,封装FGG484,速度等级-2

本教程具有通用性,可作为其他型号的FPGA参考学资料,如果作为其他型号的FPGA参考使用,配图中相关芯片型号有差异的情况需要读者自己调整下芯片型号,通常来说只要修改芯片型号和管脚约束就能满足使用。

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添加PLL IP核

Step1:打开VIVADO软件

 

Step2:打开IP Catalog,也就是IP库

Step3:打开"IP Catalog"窗口后,在搜索栏中输入"clock"关键字,可以看到 Vivado 已经自动查找出了与关键

字匹配的 IP 核名称,如下图所示。

我们直接双击选择Clocking Wizard这个IP,接下来就是配置 IP 核的时钟参数。最上面的"Component Name"一栏设置该 IP 元件的名称,这里保持默认即可。

在第一个"Clocking Options"选项卡中,"Primitive"选项用于选择是使用 MMCM 还是 PLL 来输 出不同的时钟,对于我们的本次实验来说,MMCM PLL 都可以完成,这里我们可以保持默认选择 MMCM。 需要修改的是最下面的"Input Clock Information"一栏,把"Primary"时钟的输入频率修改为我们开发板的系统时钟50M,类型设置成"Global buffer"

系统时钟通过硬件原理图确认,原理图如下图

接下来切换至"Output Clocks"选项卡,在"Output Clock"选项卡中,将其"Output Freq(MHz)"设置为 100。其他设置保持默认即可,如下图所示。

"Port Renaming"选项卡主要是对一些控制信号的重命名。这里我们只用到了锁定指示 locked 信号,其名称保持默认即可,如下图所示。

"MMCM Setting"选项卡展示了对整个 MMCM/PLL 的最终配置参数,这些参数都是根据之前用户输入的时钟需求由 Vivado 来自动配置,Vivado 已经对参数进行了最优的配置,在绝大多数情况下都不需要用户对它们进行更改,也不建议更改,所以这一步保持默认即可,如下图所示

 

最后的"Summary"选项卡是对前面所有配置的一个总结,在这里我们直接点击"OK"按钮即可,如下图所示。

接着就弹出了"Genarate Output Products"窗口,我们直接点击"Generate"即可,如下图所示。

等待一段时间后,我们点击IP Sources就能看到我们添加的IP了。

在Out-of-Context综合的过程中,我们可以开始编写代码。首先打开IP核的例化模板,在"Source"窗口中的"IP Sources"选项卡中,依次用鼠标单击展开"IP"-"clk_wiz_0"-"Instantitation Template",我们可以看到"clk_wiz.veo"文件,它是由 IP 核自动生成的只读的 verilog 例化模板文件,双击就可以打开它,在例化时钟 IP 核模块的时钟,可以直接从这里拷贝,如下图所示。

5 新建工程文件

我们接下来创建一个 verilog 源文件,其名称为 ip_clk_wiz.v

Step1:单击 Add Sources

Step3:选择单击Add or Create Design Sources 然后单击NEXT

Step4:单击Create File 来创建文件

Step5:创建一个pll_test的文件,并且文件类型选择Verilog,路径可以选择存放在工程默认路径下,米联客推荐存放在创建的FPGA工程目录的uisrc\01_rtl目录下,方便管理,注意整个路径不允许出现中文

Step6:添加完成后如下图所示之后单击finish完成文件的创建,当然如果你还要添加更多文件,还可以继续添加。

Step7:继续弹出的对话空中,可以设置一些端口,也可以修改我们这个module的名字,我们这边保持默认。单击OK

Step8:创建完成后可以看到Design Sources文件夹中有了pll_test.v这个文件,这个文件就是我们可以编写verilog程序的文件,目前该文件还是空的。我们之前添加的clk_wiz_0这个IP处于跟这个文件并列的状态,那是因为我们并没有在TOP文件也就是我们的pll_test.v这个文件中例化这个IP。

 

Step9:我们直接利用前面说的"clk_wiz.veo"文件完成例化,只有完成例化,才算真的调用了这个IP,否则即使你工程里面有这个IP,但是并不会有什么效果,这是初学者在使用的过程中经常犯的一个错误。

我们直接复制"clk_wiz.veo"中的内容,修改一下模块块的命名以及信号名。

修改完成后点击保存

//例化PLL模块

mypll mypll_u(

.reset(1'b0),         //PLL复位

.clk_out1(clk0),  //PLL输出时钟

.locked(pll_lock),      //PLL锁住

.clk_in1(I_sysclk_p)     //PLL输入时钟

);  

保存后发现,代码的结构已经发生了改变,PLL IP核已经处在了主程序的下级,说明例化成功,IP核已经被成功调用。

6完善RTL代码

成功调用之后,我们还得将我们所使用的信号进行一个简单的定义,模块与模块之间连接的信号,我们之间定义wire即可。输入信号我们习惯设置"I_"开头,同理输出信号我们设置为"O_"开头,方便我们检查代码,所以我们的系统时钟输入为"I_sysclk",并且我们将I_sysclk设置为输入,例化输入接口。

我们修改完成后,一个较为完整的程序就已经初具规模了,当然这个仅仅只是对于PLL IP的一个简单调用,把时钟作为计数器驱动,产生的信号赋值给LED灯。

`timescale 1ns / 1ps

 

module pll_test(

input I_sysclk_p,//系统时钟输入

output [1:0]O_up_led//LED输出

  );

     

wire        clk0;

wire        pll_lock;

reg [25:0]  cnt;

 

//例化PLL模块

mypll mypll_u(

.reset(1'b0),         //PLL复位

.clk_out1(clk0),  //PLL输出时钟

.locked(pll_lock),      //PLL锁住

.clk_in1(I_sysclk_p)     //PLL输入时钟

);      

 

assign O_up_led = {cnt[25:24]};//输出计数器的高位用于驱动LED

 

//计数器

always @ (posedge clk0 or negedge pll_lock)begin

    if(pll_lock==1'b0)

      cnt <= 26'd0;

    else

      cnt <= cnt + 1'b1; //cnt power on initial value is all 1

end

 

endmodule

7 添加管脚约束文件

管脚约束文件,即.xdc文件,默认工程路径,会存放在fpga_prj.srcs\constrs_1文件夹中,这里的"fpga_prj.srcs"对应的是创建工程的名称,米联客建议将引脚.xdc文件存放到创建的FPGA工程目录的uisrc\04_pin目录下,方便管理。

添加管脚约束有三种方法,分别是新建XDC PIN脚约束文件、添加已经写好的约束文件、综合后添加管脚约束,用户根据实际情况选择其中一种方法,可以提高工作效率。

7.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脚的约束。(本教程是通用于不同板子的的教程,教程中代码、配图可能与工程中代码稍有不同,请以实际工程为准。)

set_property -dict {PACKAGE_PIN V4 IOSTANDARD SSTL135} [get_ports I_sysclk_p]

set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS33 } [get_ports {O_up_led[0]}]

set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS33 } [get_ports {O_up_led[1]}]

Step5:保存,XDC文件生成完成。

7.2 添加XDC PIN脚约束文件

Step1:单击(和添加.v文件一样)

Step2:选择Add or create constraints 然后单击NEXT

Step3:单击Add Files

Step5:将要添加的.xdc文件添加进来,然后点击OK。

Step6:点击Finish完成约束文件的添加

7.3 综合并添加管脚约束

Step1:打开RTL原理图,如果你的Schematic选项是灰色的,说明你没有综合,你需要先综合,再打开RTL原理图。

Step2:管脚配置。

选择I/O Planning

根据原理图配置Package Pin,(本文本是比较通用于不同板子的的教程,教程中代码、配图可能与工程中代码稍有不同,请以实际工程为准。)

Step3:保存,给XDC文件命名,生成.XDC文件,并保存到fpga_prj\uisrc\04_pin。

创建一个fpga_pin.xdc的文件

7.4 优化管脚约束文件

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]

8添加时序约束

我们添加时序约束文件的方法跟我们管脚约束相同,这边不再赘述,我们新建一个文件"fpga_timing.xdc"用来保存我们时序约束代码。

一般我们需要对输入的时钟至少做周期约束,这个很简单,时钟约束的模板为:

create_clock -name <clock_name> -period <period> [get_ports <clock port>]

create_clock是生成约束约束命令。

name后面表示给这个时钟命名,您可以命为其他您所想要的名字,即使跟代码中的时钟名不同,都是可以的。

period后面表示约定该时钟的周期,默认单位为纳秒

所以我们这里对输入的50M时钟(有的板子是100M时钟)还有我们的PLL输出时钟做周期约束,如下:

create_clock -period 20.000 -name sysclk -waveform {0.000 10.000} [get_ports I_sysclk_p]

create_clock -period 10.000 -name clk0 -waveform {0.000 5.000} -add [get_nets mypll_u/clk_out1]

9编译测试

修改完成后,我们编译工程,为了方便产生我们后期的固化所需要的BIN文件,我们需要勾选BIN文件选项。

Step1:点击Settings

Step2:点击Bitsterm,把bin_file勾选给上。然后点击Apply和OK。

Step3:点击开始编译,点击OK,开始编译,等待编译完成。

10下载程序

Step1:给开发板通电,并且连接下载器

Step2:单击OpenTarget 然后单击Auto Connect

Step3:连接成功后如下图所示:

Step4:单击Program Device

Step5:单击选择上图的 FPGA,再单击Program Device,并且选择bit文件

Step6:下载过程

11实验结果

可以观察到,2个LED灯开始闪烁。

 

12本章小结

本章节主要学习了新建一个完整的FPGA工程,并且成功驱动了LED 灯。

posted @ 2023-09-11 14:41  米联客(milianke)  阅读(183)  评论(0编辑  收藏  举报