有三四个月没有记录blog了,这段时间也参加了一些比赛,以及上课。Vivado的资料还没有记录完,不过还是先记录下这段日子用的比较多的Zynq, 也为接下来的项目做做准备。学习主要还是看官方资料,还有黑金米联的一些教程(虽然一些细节、概念有错误,但能让入门更快也是好事)。
FPGA嵌入式开发概述
使用Xilinx FPGA进行嵌入式设计有两种解决方案:(1).使用MicroBlaze软核处理器进行设计,适用于纯FPGA平台;(2).基于Zynq-7000 AP SoC处理器进行设计,只适用于Zynq系列FPGA。Zynq芯片内部包括ARM处理器(通常称为PS部分)与可编程逻辑部分(通常称为PL部分)。
本系列将讲述如何使用Vivado完成基于Zynq平台的嵌入式系统设计。一个完整的嵌入式系统设计要考虑硬件、软件、FPGA设计三个部分。Xilinx为了尽量简化设计流程,提供如下两个主要设计工具:
-
Vivado IDE中的IP Integrator,将基于处理器的设计连接在一起,以图形化的方式设置器件、选择外设、配置硬件设置。
-
Vivado开发套件中的另一款软件开发工具SDK(Software Development Kit),对基于微处理器的系统和嵌入式软件应用进行设计、调试。
目前Zynq包含Zynq UltraScale+ MPSoC系列(内置Cortex-A53)和Zynq 7000 SoC系列(内置Cortex-A9双核)。本博客系列主要以Zynq 7000系列为主,其嵌入式开发流程相对比较简单,开发板采用米联的MZ7X(淘宝可购买,适合新手)和火龙果、ZedBoard(适合进阶阶段,较贵)。相关学习资料可以参考官方文档UG898、UG940、UG585、UG821、UG782。
嵌入式系统设计流程
Xilinx提供的工具,既支持开发无需操作系统的裸机应用,也支持开发基于开源Linux操作系统的应用。下图给出了一个大致流程:
完成一个嵌入式处理器设计的大致步骤如下:
- 创建一个Vivado工程。
- 在IP Integrator中创建一个块设计,实例化Zynq处理器与其它Xilinx IP和自定义IP。
- 为块设计中的IP生成输出产品。
- 创建顶层封装wrapper,将块设计实例化到顶层RTL设计中。
- 运行综合、实现、生成bit流,导出硬件到SDK中。
- 在SDK中创建软件应用,将可执行的ELF文件与硬件设计联系在一起。
- 下载程序到开发板中。
IP Integrator中的连线
配置好Zynq处理器后,通常还要添加一些其它IP。IP Integrator中的设计助手(Designer Assistance)特性可以帮助设计者完成系统搭建与端口之间的连线,主要包括如下两个功能:
- Block Automation,模块自动化帮助设计者完成一些模块的配置,完成基本系统的创建,支持交叉触发(cross-trigger)特性。
- Connection Automation,连线自动化在检测到当前实例化的IP之间可能需要连线时,可以自动完成连线操作。
当然,连线也可以手工完成。当工具检测到某些工作可以通过设计助手完成时,会在窗口上方给出提示,如下图:
系统搭建完成后,最好运行DRC检查避免设计中存在错误。点击上图中的Validate Design按钮(倒数第4个),如果没有错误会弹出如下提示窗口:
把块设计集成到顶层设计中
本节具体讲述下设计步骤的3、4步。生成输出产品会产生IP核的源文件与约束文件。导出文件的语言由工程设置决定,如果某IP核不支持该语言,导出时会提示相关信息。源窗口中选中IP Integrator验证好的块设计,右键->Generate Output Products,或在左侧Flow Navigator中点击IP INTEGRATOR->Generate Block Design,可导出该块设计中所有IP的输出文件。
点击上图中的Create HDL Wrapper,可以将块设计集成到一个更高层次的设计中。Vivado提供两种封装方式,如下图:
第一项允许设计者修改封装文件,但如果块设计的端口发生变化,设计者要记得更新封装文件。第二项生成的封装文件为Read-Only模式,Vivado自动管理和更新该文件。封装好后便可以执行综合、实现、生成bit流等操作。
硬件设计导出到SDK
当把IP Integrator中的处理器硬件设计导出到SDK时,会生成下表中格式的一些文件。
文件名 | 功能 |
---|---|
system.xml | 运行SDK时默认打开,显示系统的地址映射相关信息 |
Ps<#>_init.c Ps<#>_init.h | 包含Zynq处理器系统的初始化代码,还有DDR、时钟、PLL和MIO的初始化设置信息 |
PS<#>_init.tcl | 初始化文件的Tcl版本 |
PS<#>_init.html | 描述初始化数据 |
SDK提供了为Xilinx嵌入式处理器创建软件应用的完整开发环境,具体包括:基于GNU的编译工具链(GCC编译器、TCF系统调试器、相关单元和库)、JTAG调试器、Flash编程器、Xilinx IP和裸机板级支持包的驱动、使用C/C++进行裸机开发或Linux应用开发的IDE。SDK基于开源的Eclipse平台开发,还包含了C/C++开发工具箱。
当设计已经实现并生成了bit流时,通常都需要将设计导出到SDK中进行软件应用开发。某些设计中PL部分可能不包含任何逻辑(即单纯地把Zynq当作ARM来使用),无需实现和生成bit流便可导出设计。先点击File->Export->Export Hardware,弹出如下窗口:
选中“Include bitstream”,点击OK导出硬件信息。完成后再点击File->Launch SDK即可运行SDK。之后便可以在SDK中进行软件应用设计。设计完成后还可以在SDK中调试、下载软件,也可以导出ELF文件,在Vivado中和bit流一起进行下载、测试。
Hello World实例
本文前面介绍了一些FPGA嵌入式开发的基本知识和软件特性,本小节将以一个完整的Hellow World实例熟悉如何搭建Zynq-700 AP SoC处理器。这个过程中将运用到上述特性,也会出现一些大家不熟悉的概念。本节着重体会一个大致的流程,具体概念在下一篇着重讲述。
- Vivado中建立一个工程,选择芯片时选择一个与开发板相符的型号。
- 点击IP INTEGRATOR->Create Block Design,为块设计命名。
- 白板中添加IP核“ZYNQ7 Processing System”,注意上方弹出设计助手,点击Run Block Automation,弹出窗口如下:
- 设计助手提示我们会自动创建FIXED_IO和DDR,直接点击OK:
- 将M_AXI_GP0_ACLK和FCLK_CLK0手工连在一起:
- 双击ZYNQ,对IP核进行配置。首先在“Clock Configuration”中配置时钟,参数要与开发板相符。这里PS时钟为33.3M。
- DDR Configuration中配置DDR内存,同样要与开发板相符,DDR Controller Configuration->Memory Part中要选择正确的DDR芯片型号。
- 接下来在MIO Configuration中配置PS部分的外部I/O信息,我这里只希望用一组串口打印“Hello World”,因此只配置了UART1,另外Bank0核Bank1的I/O电压设置也要与开发板相符。
- 配置完成后,依次生成输出产品、用wrapper封装、生成bit流、导出硬件、启动SDK(注意某些开发板需要在启动SDK前便与电脑连接好)。
- 耐心等待SDK启动和加载完硬件,窗口如下。左侧Project Explorer显示了硬件平台信息,中间显示了地址映射关系。基于创建好的硬件平台,我们可以创建多个软件应用。
- 点击File->New->New Application Project创建新的应用,这里只设置了工程名,如下:
- 点击Next,选择示例工程Hello World,点击Finish。
- 接下来对该示例工程进行调试,选择如下图:
- 弹出窗口中,Xilinx C/C++ application(System Debugger)->右键->new:
- 弹出如下窗口。如果导出硬件时没有选择Include bitstream,此处Bitstream File窗口显示为空,点击Browse选择即可。选中Reset entire system和Program FPGA,点击Apply,再点击Debug。
- 等待Debug加载完成。注意如果你发生这种情况:Vivado中可以检测到FPGA且正常下载程序,但一到SDK中就检测不到FPGA,最简单的解决方法就是开发板上不要插入带有操作系统程序的SD卡。很多初学者就是犯了这个错误,导致无法从SDK中下载程序。
- 在下方的SDK Termianl窗口中,点击“+”添加串口,Port为对应COM号:
- 连接成功后,SDK Terminal窗口中有相应提示,点击Resume按钮或按F8,终端中打印出Hello World,表明功能正确。
至此便完成了一个简单的嵌入式开发实例,接下来的文章将介绍整个流程中设计到的很多概念,以及一些选项的具体配置方法。本文实验使用的是SDK自带例程,后面的文章中也会讲述如何自己在SDK中编程。