学习FPGA part.2

进入下一步,传统的点灯工程少不了

​ 首先先理清ZYNQ芯片的专用术语,

  • PS: 处理系统 (Processing System) , 就是与FPGA无关的ARM的SOC的部分。
  • PL: 可编程逻辑 (Progarmmable Logic), 就是FPGA部分。
  • APU: 应用处理器单元(Application Processor Unit).双ARM-CortexA9核,加上高速缓冲,DMA,定时器,中断控制,浮点和NEON协处理,硬件加速器一致性控制器。
  • TTC:(Triple Time Counter)3个独立计数通道,挂在APB上,为系统或外设提供定时或计数服务。
  • WDT:看门狗定时器
  • SWDT:系统级看门狗定时器
  • SCU: Snoop Control Unit, 用来保持双核之间的数据Cache的一致性。
  • AXI : 先进的可扩展接口(Advanced eXtensible Interface),是 Xilinx 从 6 系列的 FPGA 开始引入的一个接口协议,主要描述了主设备和从设备之间的数据传输方式。在 ZYNQ 中继续使用,版本是 AXI4,所以我们经常会看到 AXI4.0,ZYNQ 内部设备都有 AXI 接口。

按键控制LED实验

​ ZYNQ 芯片的 GPIO 分为三种,分别是 MIO、EMIO 和 AXI_GPIO,其中 MIO是 PS 的专用 I/O,作为普通输入输出或者外设驱动 I/O 来使用,EMIO 是扩展的MIO,当 MIO 不够时,可以使用部分 PL 的 I/O 做为 MIO 来使用,而 AXI_GPIO 是一个可以实现 GPIO 功能的 IP 核,PS 端可以通过 AXI 总线对其进行操作。在需要众多 I/O 口的应用场合,AXI_GPIO 可以将所有可用引脚作为 I/O 口使用。

基础知识介绍

​ 在芯片的数据手册中我们可以看到芯片 GPIO 的组成,GPIO分为 4 个 Bank,其中 Bank0 有 32bit,Bank1 有 22bit 共 54bit 属于 MIO,Bank2和 Bank3 各有 32bit 属于可扩展的 EMIO,所以对于用户而言有最多 64 个 I/O 可以使用。

  • PS端的MIO共有54个GPIO可控,序号为0:53,这个很重要,之后EMIO作为MIO使用时,根据设置的引脚号从54开始计数
  • PL端的EMIO有32个bit可控
  • MIO 是最常用也是使用最多的应用,但是 ZYNQ 最多只有 54 个 MIO 可以使用,如果 MIO 不够怎么办?这个时候就需要用到 EMIO,EMIO 是对于 MIO 的扩展 I/O,它是将 PL 端的部分 I/O 作为 MIO 供 PS 使用。

另外由于 AXI_GPIO 的使用方法有所不同,所以不在这里列出

​ MIO 是沟通 PS 内核和外设的桥梁,PS 所有的外设都可以通过 MIO 访问,也可以将外设与 MIO 连接,在使用上具有极大的灵活性,为项目硬件设计提供了许多便利,降低了电路板布局布线的难度。但是即使如此,在给不同外设分配引脚时也不是随心所欲的,必须遵循一定的规范。

芯片GPIO框图

硬件设计

​ 如下图示,可以看到许多外设能够分配的 I/O 是有限制的,当你在创建 Vivado 工程进行硬件设计时,使能了某个外设时也就分配了该外设连接的引脚,不需要后续添加引脚束。像 QSPI、Ethernet0、Ethernet1 只能分配在固定引脚。所以在进行硬件设计时必须要考虑好引脚分配的问题,合理分配引脚,才能降低后续电路板绘制的难度。
MIO 可分配功能

​ 按照之前实验的步骤建立 Vivado 工程,命名为“mio_key_led”,工程创建完成后,按照之前的步骤创建 Block Design,添加 ZYNQ7 Processing System IP 核,双击 IP 核进入配置页面基本配置与之前相同,在此不再赘述,重点讲解本次实验需要配置的项目。在本次实验中,我们需要用到 MIO,所以在配置中使能 GPIO MIO

使能 MIO

​ 配置完成后点击“OK”保存并返回。接下来参照之前实验的操作在 sources面 板 中 , 右 键 选 择Design Sources下 的mio_key_led_wrapper中 的mio_key_led_i: mio_key_led,在弹出的菜单中选择 Generate Output Products…生成输出文件,然后在相同位置右键选择 Create HDL Wrapper…生成顶层 HDL 文件。由于本次实验不需要用到 PL 部分,所以不需要生成 Bitstream 文件,直接导出即可。
​ 这样就完成了硬件方面的设计。

软件设计

​ 完成硬件设计并导出到 SDK 后,我们就可以开始进行软件方面的设计工作

​ 我们按照之前的步骤创建一个新的“hello world”工程,命名为“mio_key_led”创建好之后打开板级支持包 mio_key_led_bsp 下面的 system.mss 文件如图 2.3.2所示,在文件中可以看到本实验所用到的芯片上的所有资源,在这个文件下点击外设后面的“Docunmentation”可以打开关于该外设的数据手册,里面会详细描述该外设的功能,使用方法,库函数等信息,能有效帮助我们学会使用该外设,在项目开发过程中多阅读这些文档能加深我们我们的理解。除此之外,Xilinx 官方还提供了一些示例程序供使用者参考,点击外设后面的“Import Example”可以导入这些例程,这些例程都是该外设的基本应用,对于初学者是非常好的参考。

system.mss 文件

gpio 数据手册

​ Xilinx 官方提供了功能详尽库函数,免去了用户在使用外设时查阅手册配置寄存器的烦恼,极大的提高了开发效率,降低了出
错的概率。相关库函数的文件保存在 mio_key_led_bsp 板级支持包下面 ps7_cortrxa9_0> libsrc> gpios_v3_4 >src里面。

GPIO 库函数文件

​ 在程序中我们需要做的事情就是

1、初始化 GPIO;

2、配置 LED 接口为输出,KEY 接口为输入;

3、LED 接口输出使能;

4、读取 KEY 接口状态,根据 KEY 接口状态改变 LED 接口的高低电平输出。

​ 在明确了需要完成的任务之后,要做的事情就是查找相关的库函数,并确定要配置的参数等相关设置。

​ 实验代码为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xgpiops.h"
#include "xgpiops_hw.h"

#define MIOLED1 0 //LED1 连接 至 MIO0

#define MIOKEY1 9 //KEY1 连接至 MIO9

#define input 0
#define output 1

XGpioPs Gpios;

int main()
{
init_platform();

int Status;
XGpioPs_Config *ConfigPtr;

//初始化GPIO
print("MIO Text! \n\r");
ConfigPtr = XGpioPs_LookupConfig(XPAR_XGPIOPS_0_DEVICE_ID);
Status = XGpioPs_CfgInitialize(&Gpios,ConfigPtr,ConfigPtr->BaseAddr);
if(Status != XST_SUCCESS)
{
return XST_FAILURE;
}

//设置LED接口方向为输出
XGpioPs_SetDirectionPin(&Gpios,MIOLED1,output);
//设置KEY接口方向为输入
XGpioPs_SetDirectionPin(&Gpios ,MIOKEY1 ,input);

//使能LED接口输出
XGpioPs_SetOutputEnablePin(&Gpios ,MIOLED1 ,1);
while(1)
{
//读取KEY状态,改变LED输出电平
if(XGpioPs_ReadPin(&Gpios,MIOKEY1))
{XGpioPs_WritePin(&Gpios ,MIOLED1 ,1);}
else
{XGpioPs_WritePin(&Gpios ,MIOLED1 ,0);}
}

cleanup_platform();
return 0;
}

​ 该程序实现了按键控制 LED 的功能,按键按下 LED 点亮,按键松开 LED 熄灭。在上述代码中我们添加了一些注释描述了各函数的功能,所以不再进行详细讲解。

​ 程序修改完成后点击保存,软件自动编译生成可执行文件。至此软件设计完成。

下载验证

​ 完成硬件和软件的设计之后,我们就可以将程序烧录到开发板上进行验证。首先按照之前的方式连接串口,可以通过串口打印判断程序是否在运行。

​ 烧录完成后可以开发板上可以看到按下 PS_KEY1,PS_LED1 点亮,说明硬件设计和软件设计都是正确的。

实验现象