ZYNQ上手教程1-软硬件协同设计流程

我们将在ZYNQ的PL部分添加两个GPIO的IP核,通过PL中的GPIO IP核来扩展PS部分的功能。本实验中的两个GPIO IP核将用来控制板卡上的拨码开关和LED灯,GPIO IP核将通过AXI Interconnect 模块来连接到PS的M_AXI_GP0接口上。GPIO IP核中的寄存器会作为Memory-mapped的方式映射在PS的地址空间上,PS端即可通过对相关地址的控制来完成对相应外设的控制。

基于Vivado IP集成器的ZYNQ软硬件设计流程

本节实验的步骤说明如下
1. 创建Vivado工程;
2. 在IP集成器环境中添加并配置ARM硬核;
3. 添加并配置GPIO IP核;
4. 执行Vivado综合、实现并生成配置文件;
5. 将硬件工程导出至Vivado SDK;
6. 编写C源文件并编译;
7. 硬件验证。

作为玩家们的首个ZYNQ实验,博主会在本实验中尽可能详细的介绍基于Vivado工具的ZYNQ软硬件设计细节。将会向各位玩家介绍以下内容。
基于Vivado的ZYNQ工程创建,尤其是基于我们ZYPI实验平台的工程创建;

  • 基于IP集成器这种图形化、智能化的开发环境中加入ARM硬核以及其他IP核的方式来创建一个ZYNQ嵌入式硬件工程;
  • 通过图形化的配置界面来完成对ARM硬核的配置,如时钟频率、复位、中断、与PL的接口等相关设置;
  • 在IP集成器中添加、配置软核,如GPIO IP核。并通过AXI Interconnect 模块将各种IP核外设与ARM硬核通过AXI接口连接起来;
  • IP集成器中添加的软核IP模块的时钟以及复位信号的配置;
  • IP集成器的智能化设计辅助完成功能;
  • 通过将顶层信号make external的操作来将其与芯片外设备/接口相连接;
  • 通过对不同IP映射不同地址的方式,在软件层面进行控制;
  • 通过创建XDC约束文件,编写IO约束的方式来完成对输入输出IO的位置锁定,使用板卡上对应的资源;
  • 通过执行validation的功能,来对整个IP集成器搭建的系统进行验证;
  • 通过ps7_init.c、ps7_init.h、ps7_init.tcl文件理解Vivado工具是如何完成对硬件的抽象;
  • 通过Vivado SDK完成对ZYNQ嵌入式软件的编写、编译以及调试;
  • 在Vivado SDK环境下编写一个无os、裸跑的应用程序;了解裸跑程序如何使用处理器cache、中断、输入输出以及其他基本处理器特性。
  • 实验流程
    那么,我们开始进入实验阶段。首先,创建新工程。
    这部分在之前的博文中也有详细讲解,点击这里查看

    打开Vivado集成开发套件

    选择创建一个新的工程,工具会自动打开一个新工程创建向导


    点击下一步,填写工程名称以及工程目录,可勾选创建工程子目录。注意,工程的名字以及工程目录均不能出现空格或中文字符。(尤其注意,某些机器的系统桌面路径是含有空格的)

    下一步,选择工程类型。我们选择RTL型工程,即我们通过添加HDL源码或通过IP集成器的方式生成源文件,然后经过综合、实现生成配置文件的工程类型。

    其余几种工程类型,从上至下分别为以综合后网表为顶层的工程、IO规划工程、导入的工程以及Vivado自带的实例工程。

    下一步,选择器件或板卡。该步骤,我们需要根据工程中所用到的Xilinx FPGA器件的型号来选择对应的器件,我们可以在Board选项中选择对应的板卡型号。

    添加板卡文件。首次在新装Vivado中使用ZYPI板卡的同学,可以看到在Board选项中尚未加入该板卡,因此我们需要使用官方提供的板卡文件手动添加。将提供的board_files文件解压至:installdir\Vivado\2016.4\data\boards\board_files然后重新启动Vivado后即可在Board下看到ZYPI板卡了。

    选择ZYBO板卡,并点击下一步。即完成工程创建。

    点击完成后,即进入Vivado工程主界面。

    其中主要有以下几个区域:
    1. 菜单/工具栏:Vivado IDE工具命令
    2. 流程向导:工程管理、IP集成器、仿真、综合、实现以及下载调试各阶段流程控制
    3. 工程管理区域:源文件层级结构、网表、库文件、编译顺序视图
    4. 工程状态/属性区域:对象属性视图
    5. 主工作区域:源文件编辑、原理图、网表、器件、封装等视图
    6. 状态/结果显示以及交互区域:TCL交互、信息、log记录、报告、设计运行状态等视图

    搭建ZYNQ硬件系统设计
    在IP集成器中加入ZYNQ ARM硬核。
    在流程向导区域IP集成器栏目下单击Create Block Design,创建一个新的Block Design源文件。其中设计名称、路径等可保持默认。

    点击OK后,即可看到主工作区域打开一个空白的Block Design。

    在空白区域右键,选择Add IP选项,打开添加IP向导,即IP列表。

    在上方搜索框内键入“ZYNQ”,搜索ZYNQ ARM硬核模块。

    双击ZYNQ处理器系统条目,将其加入进IP集成器中,可以看到在IP集成器环境中ZYNQ ARM硬核模块就被加入进来了。这时,该模块上的接口为系统默认接口。稍后,我们将会按照使用需求,对ZYNQ的ARM硬核模块进行配置。

    ZYNQ 硬核配置
    首先,我们双击打开ZYNQ配置界面。

    可以看到配置界面右侧为详细配置界面首页,左侧为分项页面,依次为:
    1. ZYNQ模块视图:ZYNQ总体内部模块结构,绿色显示说明为可配置,单击相应绿色模块可进入对应配置页面;
    2. PS-PL配置:PS与PL之间通信接口相关配置,在PL与PS之间有多种不同接口可用于PS-PL数据交互,依据对数据量以及速度的要求来选择不同接口;
    3. 外设IO引脚:ZYNQ 的PS部分拥有多种共计20多个接口控制器硬核,在本页面中可选择使能硬核,以及对其引脚进行分配;
    4. MIO配置:ZYNQ PS部分拥有2个BANK共计54个PS专属的IO,即MIO。在本页面中可对MIO的使用进行配置;
    5. 时钟配置:PS部分内置PLL,本页面可针对不同模块的时钟属性进行设置;
    6. DDR配置:PS部分内置DDR控制器硬核模块,本页为DDR控制器相关属性配置页面;
    7. SMC时序配置:SMC(Static Memory Controller)亦为PS内置硬核模块,本页为SMC相关属性配置页面;
    8. 中断系统配置:ZYNQ的中断系统配置页面,对PS to PL的中断以及PL to PS的中断进行配置。

    好了,熟悉了ZYNQ配置界面后,我们可以先使用Vivado工具的设计辅助功能进行ZYNQ的自动配置。注意,正式由于我们在创建工程的时候选择了基于ZYPI板卡创建工程,因此Vivado工具可自动将ZYNQ PS硬核与ZYPI板卡硬件实现细节相匹配,完成ZYNQ PS的自动配置。首先,我们点cancel关掉ZYNQ配置向导,并单击IP集成器上方的Run Block Automation选项,保持默认设置,确保Apply Board Preset选项处于勾选的状态,然后点击OK。



    可以看到,Vivado工具自动完成针对ZYPI板卡的ZYNQ PS自动配置,将所有ZYPI上用到的接口/外设均设置为合适的状态。如打开ZYNQ配置界面外设IO页面,我们可以看到在ZYPI板卡PCB上连接到相应IO的外设,均按照ZYPI板卡的实际情况完成了对ZYNQ PS的配置。

    这时,我们可基于这个配置状态进行相应修改,如关掉我们在设计中使用不到的接口或外设。但是,需要注意的是在目前的配置下,没有被使能的外设或接口基本是由于ZYPI板卡物理上没有连接的,因此是不能使用的。

    本实验中,我们会使用PL部分资源构建GPIO IP核,通过AXI互联方式挂在PS端,因此,我们要打开PS中AXI接口以及PS给PL的时钟和复位信号。这部分配置在默认设置中均已打开。



    第一个实验,可以为了工程清晰简洁以及节省运行时间,我们可以将本实验中不需要用到的接口,在MIO配置页面暂时关掉。如以太网、USB、SD接口以及默认打开的Timer 0关闭。

    这部分若选择不关闭亦不会影响后续实验步骤。


    最后,点击OK,完成对ZYNQ ARM硬核的配置。此时可以看到ZYBQ PS模块上DDR以及FIXED_IO已经作为顶层信号连接至外部。其中,DDR这组信号即为PS内部DDR控制器硬核与外部DDR存储芯片之间的信号线。FIXED_IO这组信号中,主要包含54根MIO信号线,其中就包含有我们使用到的串口TX、RX信号,即对应到MIO配置页面中uart 1 MIO(48..49)。

    利用PL资源扩展系统

    添加GPIO IP核
    再次通过Add IP的方式打开IP列表,找到GPIO IP并双击加入进IP集成器中。


    双击GPIO IP核模块,打开GPIO IP核配置界面。在Board Interface选项处下拉选择leds 8bits,将该GPIO IP核的通道1配置为与芯片外板卡上8个LED灯相连;同时可以切换到IP Configuration选项卡,可以看到通道1已经被自动设置为位宽为8bit。完成后点击OK,回到IP集成器。


    在IP集成器中选中GPIO IP核模块的情况下,在属性窗口中可对该IP模块的名称进行修改。通常,对GPIO模块名称修改为对应功能名称,以方便后续硬件搭建以及软件编写与调试。

    返回到IP集成器,选择Run Block Automation,在弹出的向导中选中leds_8bits这个GPIO模块下的GPIO以及S_AXI,保持默认设置,点击OK完成对GPIO模块的自动连接。


    在完成自动连接后,可以看到,Vivado工具自动添加了AXI Interconnect模块来实现leds_8bits与PS之间的连接。ZYNQ PS模块上打开的是一个Master的GP接口,通过AXI Interconnect模块,ZYNQ PS以及与多个Slave的AXI IP相连接。单个AXI Interconnect的Master接口最多有64个,Slave接口最多有16个。

    通过ADD IP的方式,再次添加一个GPIO IP核,配置连接至板上按键,即btns_5bit,同时修改IP名称为btns_5bit。并按照上述步骤,Run Block Automation进行自动连接。

    在IP集成器界面下,切换至Address Editor选项卡中,展开Data项目,可以看到leds_8bits与btns_5bit两个GPIO IP核映射到PS的地址空间。一般来讲,通过Run Block Automation方式完成的IP核,地址会被Vivado工具自动分配,而手动连线方式完成连接的IP核,需要在本页面进行分配地址,即点击页面左侧最下方的按钮Auto Assign Address。

    完成上述步骤后,可点击保存按钮,来保存IP集成器中的硬件设计。同时,可通过运行Vivado 校验工具来检查是否有连接错误的情况。

    硬件工程的综合、实现以及生成配置文件

    bd封装
    在工程文件管理窗口,点击Source选项卡,其中我们看到design_1.bd即是我们刚刚在IP集成器中完成的block design。对其点击右键,选择Create HDL Wrapper选项,在弹出的窗口中选择有Vivado来管理Wrapper文件的自动更新,并点击OK。


    工具会自动生成一个block design 的HDL顶层封装文件,我们后续的综合、实现等过程即是以该文件为顶层进行的。

    设计综合

    在Vivado流程向导中开启设计综合,用户可选择运行该次综合所使用的CPU线程数量。根据不同的机器性能配置,综合过程可能会持续若干分钟不等。综合完成后,我们可以选择打开综合后的设计,工具会自动打开器件Device视图。



    综合后的视图
    我们可以在工具栏上选择不同的视图。此处,我们切换至I/O规划视图。

    在Vivado下方窗口自动切换至IO管脚窗口,我们展开GPIO IP模块,可以看到对应的信号已经自动的锁定在对应的管脚上。若使用的板卡非官方板卡,则对外信号的引脚锁定需要手动在该界面进行设定或者通过编写XDC约束文件的方式来进行IO的约束。

    设计实现并生成配置文件
    确认引脚锁定正确后,再次回到流程向导区域,执行过程的实现。在实现过程执行完成后,可直接进行配置文件的生成步骤。

    在配置文件生成之后,选择打开实现后的设计(若提示是否先关闭综合后的设计,请选择YES)。


    导出硬件
    至此,本实验的硬件工程就完成了,下面我们需要将硬件工程导出至Vivado SDK以便做后续的软件工程。通过File > Export > Export Hardware,打开导出窗口,注意此处我们需要点击勾选Include birstream来将配置文件同时导出。


    开启SDK
    OK,Vivado中的工作就到一段落了。接下来我们就要转战SDK,进行ZYNQ软件设计了。通过File > Launch SDK来打开SDK工具。

    ZYNQ软件开发-SDK流程
    通过Vivado打开SDK工具。SDK首先将导入Vivado导出的硬件工程信息文件。并自动创建一个硬件平台工程。其中包含硬件工程生成的配置文件(.bit),以及Vivado工具导出的硬件平台描述文件(.hdf),以及其他PS部分启动文件。

    SDK初始界面

    SDK下的硬件平台工程
    SDK会默认打开hdf文件,hdf文件中详细的描述了当前系统的硬件信息,如目标器件、硬件工程创建时间,以及工程中包含的全部IP列表(包括PS内部以及PL中的IP)和地址映射关系。

    在SDK自动创建的硬件平台工程中,包含有一个ps7_init.html文件,该文件详细描述了当前ZYNQ PS系统的细节信息,如MIO、CLK、DDR、SMC等部门的配置信息以及全部寄存器的详细描述。

    BSP与APP工程
    创建应用程序以及BSP工程。在SDK环境下,通过File > New > Application Project打开应用工程创建向导。工程名称自拟,OS选择standalone操作系统(Xilinx提供的一个轻量级操作系统,屏蔽掉若干底层细节,提供诸多API可直接使用),硬件平台选择SDK自动导入并创建的硬件平台工程,并选择创建一个新的BSP工程。点击下一步,选择一个空的模板来创建应用工程。


    点击完成后,SDK开始自动编译应用工程以及BSP工程源码。完成后,可以在工程浏览器窗口看到新建的lab1工程以及lab1_bsp工程。

    创建或添加源文件
    创建源文件。在lab1工程src目录上右键选择New-Source File,在打开的新建源文件向导窗口中输入新建源文件的名称以及后缀,如lab1.c,并点击完成,则可以看到src中新增了一个c源文件,并在在右侧窗口中打开了该c文件。


    通过复制粘贴的方式,将下面提供的lab1.c中的程序copy进SDK中的lab1.c中,保存并编译。

    lab1.c
    int main(void)
    {
    //Variables Declarations
    XGpio push, led; // instance pointer for the push buttons and LEDs
    int i,push_check;
    int out = 0;
    int val=1;
    xil_printf("Lab1 application started.... \r \n");
    int delay_value=9999999;
    //AXI GPIO Initialization
    XGpio_Initialize(&push,XPAR_BTNS_5BITS_DEVICE_ID);
    XGpio_Initialize(&led,XPAR_LEDS_8BITS_DEVICE_ID);
    //AXI GPIO Set Direction
    XGpio_SetDataDirection(&push,1,0xffffffff);
    XGpio_SetDataDirection(&led,1,0x00000000);
    while (1){
    //Reading from the push buttons
    push_check= XGpio_DiscreteRead(&push,1);
    switch (push_check){
    //Checking if BTNC was pressed
    case 1:
    delay_value=9999999;
    break;
    //Checking if BTND was pressed
    case 2:
    val = -1;
    break;
    //Checking if BTNL was pressed
    case 4:
    delay_value=19999999;
    break;
    //Checking if BTNR was pressed
    case 8:
    delay_value=4099999;
    break;
    //Checking if BTNU was pressed
    case 16:
    val =1;
    break;
    default:
    break;
    }
    //Printing the value returned by XGpio_DiscreteRead
    xil_printf("Push Buttons Status: %d \r \n",push_check);
    //Printing the value of variable val and out
    xil_printf("Value of val: %d \r \n",val);
    xil_printf("Value of out: %d \r \n",out);
    // Incrementing the value of out by val
    out = out+val;
    // Checking boundaries
    if (out > 15){
    out=0;
    }
    if (out< 0) {
    out=15;
    }
    //Writing the value of variable out to the LEDs
    XGpio_DiscreteWrite(&led,1,out);
    // Creating a software delay
    for (i=0;i }
    return (0);
    }

    硬件验证
    硬件连接
    将ZYPI板卡连接至PC。使用USB连接线将PC与板卡USB-UART接口(如图标示3处)进行连接;使用USB连接线将PC与板卡USB-JTAG接口(如图标示2处)进行连接以便进行配置文件下载以及工程调试。同时在硬件管理器中观察被PC识别到的串口COM号。可在SDK中或单独的串口终端中来观察PS串口的输出。

    硬件配置
    在Xilinx Tools下选择Program FPGA完成对FPGA的硬件配置。在弹出的窗口中会自动识别当前工程对应的配置文件,点击Program在进行配置。配置完成后可观察到此时板卡上的Done信号亮起(蓝色LED灯)。


    软件调试
    应用工程lab1上右键,选择Run As - Launch on Hardware在硬件上进行运行。
    此时,可以观察到LED流水灯效果,并且按下不同按键会有相应变化,同时串口终端会打印出程序运行输出的相关信息。

    后续
    相关软硬件协同设计、AXI总线、自定义ZYNQ PL IP核、ARM CPU调试、相关AXI IP使用等内容,咱们后面接着聊。

    作者:FPGAPlayer
    出处: http://FPGAPlayer.com