【FPGA学习】- SDK实验篇("Hello World")
SDK,即Software Development Kit,中文译作软件开发套件。XILINX SDK是集成型设计环境,可在任何AMD微处理器上创建嵌入式应用。
Zynq-7000系列基于Xilinx SoC架构。这些产品在单个器件中集成了功能丰富的Arm Corte-A9 MPCore处理系统(PS)和Xilinx可编程逻辑(PL),Zynq-7000架构,可以方便地将定制逻辑和软件分别映射到PL和PS中,以实现独特和差异化的系统功能。
PS中的处理器总是首先启动,允许以软件为中心的PL系统引导和PL配置。下图说明了Zynq-7000 SoC的功能模块,其中PS和PL位于不同的电源域中。
Zynq-7000 SoC由以下主要功能模块组成:
Processing System (PS)
· Application processor unit (APU)。应用程序处理器单元(APU)提供了大量高性能特性和符合标准的功能。
· Memory interfaces。多种内存技术的集合。
· I/O peripherals (IOP)。用于外部数据通信交互的工业标准接口的集合。
· Interconnect。负责不同接口之间相互连接。
· · OCM interconnect。提供从中央互连和PL到256 KB内存的访问。
· · Central interconnect。将IOP和DMA控制器连接到DDR内存控制器、片上RAM和用于PL逻辑的AXI_GP接口。
Programmable Logic (PL)
在使用ZYNQ上ARM cortex-A9平台时,最主要的操作就是对I/O的操作。对I/O操作的方式之一就是直接对GPIO(General Purpose Input Output)寄存器操作。在实际使用时ZYNQ又把GPIO分成MIO、EMIO和PL端的IO三种不同的类型。如下图所示。
MIO:Multiplexed I/O,多路复用/O端口。MIO只属于PS端,PL端无法进行操作。PS 所有的外设都可以通过 MIO 访问,这些外设也是与 MIO 进行连接。ZYNQ的PS端外设很多是复用的,相同的引脚标号可以配置成不一样的功能,但是当一个引脚号被确定功能时,则不允许再使用其它功能。
EMIO:Extendable Multiplexed I/O,依然属于Zynq的PS部分,但是连接到了PL上,再从PL的引脚连到芯片外部设备实现数据输入输出。PS端可以通过软件映射连线来对EMIO进行操作,且使用效果与MIO一致。
PL端的IO:PL端所有I/O都属于常规的FPGA的I/O口,可以进行输入输出操作。
使用ARM裸机输出“Hello world”
硬件工作
创建一个工程,点击“Create Block Design”,创建一个Block设计,点击“Add IP”,添加入“ZYNQ7 Processing System”,双击 Block 图中的“processing_system7_0”,配置相关参数。
PS-PL Configuration界面,主要是进行PS与PL之间接口的配置,主要是AXI接口,这些接口可以扩展PL端的AXI接口外设,所以PL如果要和PS进行数据交互, 都要按照 AXI 总线协议进行,由于此实验不需要和PL端进行交互,在这里保持默认。
Periphreal I/O Pins界面,主要用于选择配置PS端的外部设备。PS端分为两个Bank,Bank0选择电压“LVCMOS 3.3V”,Bank1选择电压“LVCMOS 1.8V”。
我们可以通过开发手册知道串口连接在MIO48~49上,在选项使能UART1。
配置 QSPI。QSPI作为ZYNQ的启动存储设备,ZYNQ可以通过读取 QSPI 中存储的启动文件加载ARM和FPGA,从原理图得知,我们在MIO1~6上,使能Quad SPI Flash。
配置以太网。 PS 端设计有以太网接口,根据原理图在MIO16-MIO27,使能 Ethernet 0。在MIO52~53上,使能MDIO。
配置USB。根据原理图在MIO28~39上,使能USB0。在 GPIO MIO 中选择 MIO46 作为 USB PHY 的复位。
配置SD卡。根据原理图在MIO40~46上,使能SD0。选择Card Detection MIO47,用于检测SD卡的插入。
配置GPIO。打开GPIO MIO,PS便可以控制剩余未分配的MIO,用作GPIO。
MIO Configuration界面,主要用于配置MIO的基本参数。修改 Enet0 的电平标准为HSTL 1.8V,Speed为fast。
Clock Configuration界面,配置与时钟相关的参数。此实验上保持默认即可。
DDR Configuration界面,配置与DDR相关的参数。AX7010配置DDR3型号为 “MT41J128M16 HA-125”,Effective DRAM Bus Width”选择为“32 Bit”。
点击“Run Block Automation”,vivad 软件会自动完成一些导出端口的工作。连接 FCLK_CLK0 到 M_AXI_GP0_ACLK,按 Ctrl+S 保存设计。
M_AXI_GP0是通用(General Purpose)AXI接口,它包含了一组信号。首字母M表示PS作为主机(Master),PL中的外设作为从机(Slave)。
M_AXI_GP0_ACLK是M_AXI_GP0的全局时钟信号,它是一个输入信号,M_AXI_GP0接口的所有信号都是在这个全局时钟的上升沿采样的。
FCLK_CLK0是PS输出的时钟信号,它将作为PL中外设模块的时钟源。
FCLK_RESET0_N是由PS输出到PL的全局复位信号,低电平有效。
选择Block设计,右键“Create HDL Wrapper...”,创建一个文件,为block design生成HDL顶层文件。设计完成之后,展开设计可以看到PS被当成一个普通IP来使用。
选择block设计,右键“Generate Output Products”,此步骤会生成block的输出文件,包括IP,例化模板,RTL源文件,XDC约束,第三方综合源文件等等。
点击“File -> Export -> Export Hardware...”导出硬件信息,这里就包含了PS端的配置信息,供后续软件开发人员使用。
软件工作
点击”launch SDK“,打开SDK。其中有一个"system.hdf”文件,这个文件就包含了Vivado硬件设计的信息,可以给软件开发使用,也可以看到PS端外设的寄存器列表。
点击“New -> Application Project”,建立一个新工程。模板选择“Hello World”,点击"Finish"。生成了一个“helloworld”文件和“helloworld_bsp”文件。“helloworld”文件目录中主要包括了应用程序开发的主程序。在“helloworld_bsp” 目录中可以开发所需要的驱动文件,用于应用程序开发。
使用PuTTy软件作为串口调试工具。选择“Serial”,输入serial line和speed,打开软件。将开发板的启动模式设置到 JTAG 模式。
选择helloworld文件,右键“run as”,点击“Run Configurations”。选择“Reset entire system”,点击“Run”。
我们可以看到PuTTy窗口输出了结果。
使用XILINX SDK开发C++程序。创建C++程序,模板选择“Empyt Application”。
创建成功之后,由于没有C++的库,需要手动添加C++库。右键单击”项目“ -> C/C++ Build Settings -> ARM v7 g++ compiler -> Directories -> 单击“添加”按钮 ,添加C++包含路径:、
E:\Xilinx\SDK\2018.1\gnu\aarch32\nt\gcc-arm-none-eabi\arm-none-eabi\include\c++\7.2.1
E:\Xilinx\SDK\2018.1\gnu\aarch32\nt\gcc-arm-none-eabi\arm-none-eabi\include\c++\7.2.1\arm-none-eabi\thumb
E:\Xilinx\SDK\2018.1\gnu\aarch32\nt\gcc-arm-none-eabi\arm-none-eabi\include\c++\7.2.1\backward
添加成功之后,就可以开始编写C++程序了。
参考资料
[1] Zynq-7000 SoC Technical Reference Manual (UG585),https://docs.xilinx.com/v/u/en-US/ug585-Zynq-7000-TRM
[2] Xilinx SDK 创建 C++ 应用工程,CSDN,https://blog.csdn.net/shaolinsdkd/article/details/111294182
[3] 黑金FPGA开发教程
[4] 正点原子FPGA开发教程