-
第
9
章
ZedBoard
入门
前面大家已经
对
ZYNQ
架构以及相应的开发工具有一定的认识,接下来我们
将带领大家来一起
体验
ZYNQ
,体验
软硬件协同设计的魅力。由于时间的关系,下面的一些实验(本章及后续章节的实验)
可
能有不完善的地方,欢迎读者向我们反馈。
9.1
跑马灯
本实验将指导大家使用
Vivado
集成设计环境创建本书的第一个
Zynq
设计。这里,我们使用
跑马灯
这个入门实验来向大家介绍
Vivado
IDE
的
IP Integrator
环境,并在
Zedboard
上实现这个简单的
Zynq
嵌
入式系统。之后,我们将会使用
SDK
创建一个简单的软件应用程序,并下载到
Z
ynq
的
ARM
处理器中,
对在
PL
端实现的硬件进行控制。本实验分为三个
小节来向大家进行介绍:
?
第一节我们将使用
Vivado
IDE
创建一个工程。
?
在第一节的基础上,第二节我们将
继续构建一个
Zynq
嵌入式处理系统,并将完成后的硬件导入
到
SDK
中进行软件设计。
?
最后一节我们将使
用
SDK
编写
ARM
< br>测试应用程序,
并下载到
Ze
dBoard
上进行调试。
实验环境:
Windows 7
x64
操作系统,
Vivado2013.4
,
SDK 2013.4
9.1.1 Vivado
工程创建
1)
双击桌面
Vivado
快捷方式
,或者浏览
S
tart > All Programes > Xilinx Design Tools >
Vivado
2013.4 > Vivado
2013.4
来启动
Vivado.
2)
当
Vi
vado
启动后,可以看到图
9-1
的
Getting
Started
页面。
图
9- 1 Vivado
开始界面
3)
选择
Create New Project
< br>选项,图
9-2
所示的
New
Project
向导将会打开,点击
Next
。
图
9- 2 New Project
对话框
4)
在
Project
Name
对话框中,输入
first_zynq_design
< br>作为
Project
name
,
选择
C:/XUP/Zed
作为
Pr
oject location
,确保
Create
project subdirectory
被勾选上,如图
9
-3
,点击
Next
。
图
9- 3
Project Name
对话框
5)
在
Project
Type
对话框中,选择
RTL
Project
,确保
Do not specify
sources at this time
选项没有
被勾选,如图
9-4
,点击
< br>Next
。
图
9- 4 Project
Type
对话框
6)
在
Add
Source
对话框中,
选择
Verilog
作为目标语言,如果你对
p>
VHDL
熟悉的话,
你也可以
选择
VHDL
,如果这里
你忘记了选择,在工程创建完成后,也可以在工程设置中选择你熟悉的
HDL
语言。如果你已经有了源文件,在这里就可以选择
Add
file
或者
Add
directory
p>
进行添加,
由于我们没有任何的源文件,
所以这里我们直接点击
Next
即可,
如图
9-5
。
图
9- 5
添加源文件
7)
在
Add Existing IP
对
话框中,点击
Next
。
8)
在
Add Constraints
对
话框中,点击
Next
。
9)
在
Default
Part
对话框中,在
Specify
框中选择
Boards
选项,在下面的
Board
列表中选择
ZedBoard Zynq Evaluation
and Development Kit
,点击
Next
p>
,如图
9-6
。
图
9- 6
芯片选择
10)
在
New
Project
Summary
对话框中,点解
p>
Finish
完成工程创建,至此,我们已经使用
< br>Vivado
创建了一个
Zynq
设计的工程框架,图
9-7
为
Viv
ado
的工程界面,在第四章我们已经对该界面
进行过介绍,如
果还不熟悉的读者再回到前面复习一下。下面我将使用
Flow
Navigator
的
IP
Integrator
功能完成
第二节的嵌入式系统设计。
图
9- 7
Vivado
工程界面
9.1.2
在
Vivado
中创建
Zynq
嵌入式系统
这一节我们将创建一个简单的
Zynq
嵌入式系统,该系统使用
Zynq
PL
部分实现一个通用
I/O
控制
器
p>
(GPIO)
,控制器同
ZedBoard
上的
8
个<
/p>
LED
相连接,并且通过
AXI
总线连接到
PS
端,这样我们就可
以通过将要在第三小节中实现的
ARM
应用程序来对
LED
进行控制。系统结构图如图
9-
8
所示。
ZYNQ
< br>PS
AXI
AXI
GPIO
ZYNQ PL
Development
Board
图
9- 8
系统结构图
1)
创建一个
Block
Design
。在
Flow
Navigator
窗口中展开
IP
Intergrator
,选择
Create Block D
esign
,
如图
9-9
。
图
9- 9
创建
Block Design
2)
在
Block Design
对话框中
输入
zynq_system_1
作为
Design name
,如图
9-10
,点击
OK
继续。这时,
在
workplace
区域将会打开
IP
Integrator
的图表画布,我们将在这个空白区域中像画画一
样的
构建自己的系统。这里操作的最小单位是
IP
核,
Xilinx
官方还有一些第三方机构给我们提
供了
很多的免费
IP
核,你可以直接在
这里添加使用,当然,用户也可以自定义自己的
IP
核,然后<
/p>
添加到工程中使用,或者提供给其他用户使用,在
13
章第一节我们将会向大家介绍如何制作
自己的
IP
核。
图
9- 10
输入设计名称
3)
在空白画布中,右键空白区域,并选择
Add
IP
选项,或者点击画布最上方的绿色提示信息中的
A
dd IP
链接,如图
9-11
。
p>
4)
这时一个
IP
核列表将会弹出,在
Search
一栏输入
Zynq
,在搜索结果列表中
双击
ZYNQ7
Processing System
添加
PS
端的
IP<
/p>
核到画布中,如图
9-12
所示。由于我
们使用的是
ZedBoard
,
这一步
完成后
Vivado
会对
Zynq
p>
处理器进行相应的配置。同时在
IDE
的下
面,选择
TCL
Console
你将
看到如下的信息,其实我们在
Vivado
图形化界面所做的所
有操作都将转化为
TCL
命令来
执行。
create_bd_cell -type ip
-vlnv :ip:processing_system7:5.3
processing_system7_0
图
9- 11
添加
IP
图
9- 12
添加
PS
IP
核
在空白画布中,
可以看到
ZYNQ7
Processing
System
被以图形化的方式添加进来,当前的
IP
模
块是一个初始化界面,如果要使这个模块能在
ZedBoard
工作起来,首先对其进行相应的配置。
5)
双击
ZYNQ7 Processing
System
模块,打开其配置界面,
如图
9-13
所示,首先先来熟悉一下这个
< br>界面。
?
< br>Documentation
:提供该
IP
模块相关的文档帮助。
?
Page
Navigator
: <
/p>
这里提供了该
IP
模块的详细配置列表。
Zynq
Block
Design
页面显示了
ZYNQ7
Processing
System
的总体概貌,我们可以通过点击绿色部分对相应的模块进行查看或者配
置;
PS-PL
Configuration
页面提供
了
PS
到
PL
的相关接口配置信息以及
PS
部分一些配置信
< br>息;
Peripheral I/O
Pins
页面主要是对一些通过外设接口的配置;
MIO Co
nfiguration
页面主
要是对
MIO
以及
EMIO
的分配控制。
p>
Clock
Configuration
页面主要是对
PS
端时钟资源的配
置及
管理。
DDR
Configuration
< br>页面主要是对
DDR
控制器一些参数的配置。
Interrupts
页面
主要是对中断进行配置
管理。
?
Presets
:
这里主要提供了一些开发板的预定义配置功能
,
Vivado
将会按照已经设置好的配置信
< br>息来对该
IP
核进行配置,而不需要我手动的来配。点击
该按钮,我们可以看到
Vivado
现
在已经支持的开发板有
Microzed
、
ZC702
、
ZC706
、
ZedBoard
以及一个
Default<
/p>
配置选项。
?
Import XPS Settings
:这个功能主要是将
XPS
中的
ZYNQ7
Processing System
的配置信息导入进
来,其
实就是导入一个
xml
文件。由于我们使用的是
ZedBoard
开发板,且只用到
Vivado
p>
提供的默认配置,所以这里选择
Presets
>
Zedboard
,
点击
OK
来完成对
ZYNQ
7
Processing
System
的配置。下一步我们将要连接
PS
端的
DDR
与
FIXED_IO
接口到
顶层接口。
6)
左建选择
ZYNQ7
Processing
System
模块上的
DDR
接口,当光标变成笔装的时候右键并选择
Make External
,
如图
9-14
,对于
FIXED_IO
使用同样的方法。
1
2<
/p>
3
4
5
图
9- 13 ZYNQ7 Processing
System
界面
注:
5
、
6
两步更加简单的方法
是点击
Diagram
顶端的
Run
Block
Automation
设计协助链接来完成对
ZYNQ7
Processing System IP
核的配置并将
DD
R
与
FIXED_IO Make External
,如图
9-15
所示。当选择
< br>/processing_system7_0
的时候,相应的
< br>IP
核图形界面会变成高亮显示,表示其已被选中,并将会被自
< br>动配置。在弹出的
Run Block
Automation
对话框中确保
Apply Board
Preset
被勾选,否则其只会将
DDR
与
FIXED_IO
连接到顶层端口,而不会对
ZYNQ7
进行默认配置。如果你在手动完成了
ZYNQ7
的配置又
要使用
Run
Block
Automation
这个功能,那么一定要确保
Apply
Board Preset
选项没有被选中,
否则它
将会使用默认配置来覆盖你原来的配置。
图
9- 14 Make
External Interface
操作
图
9- 15 Run Block
Automation-ZYNQ
当完成了
ZYNQ7
Processing
System
IP
核的添加并对其进行配置后,你的
Block
Design
应该如图
9-16
所示。下面将添加
AXI
GPIO
IPcore
到系统中,该
IP
核被放在
PL
端,通过
AXI
总线同
ARM
相连接,并通过
GPIO
接口控制
ZedBoard
< br>上的
8
个
LED
小灯。我们将使用
IP
Integrator
的设计
协助工具来将
AXI GPIO
连接到
PS
端。
图
9- 16 ZYNQ7
Processing System
外部连接
7)
右键
D
iagram
窗口的空白区域,在弹出的菜单列表中选择
Add
IP
选项,在搜索栏中输入
GPIO<
/p>
,
并在搜索结果列表中双击
AXI GP
IO
将该
IP
添加到系统中。
8)
在
Diagram
窗口顶部点击
Run
Connection
Automation
链接,并选择
/axi_gpio_0/S_AXI
选
项
,
这时
可以看到
GPIO IPcore
的
S_AXI
接口被高亮显示,如图
9-17,
点击
OK
完成。
图
9- 17 Run Connection
Automation-GPIO
这时可以看到有两个新的
I
P
模块自动被添加了进来:
?
Processor
System
Reset:
p>
这个
IP
提供一个定制化的
Reset
功能,包括所有外设,互联以及处
理器生。
?
AXI
Interconnect
:
提供
AX
I
总线互联控制,它将
PL
端外设同
PS
端连接起来。
9)
同
样<
/p>
点
击
Run
Connection
Automation
链
接
,
并
选
择
/axi_gpio_0/GPIO
< br>,
Run
Connection
Automation
对话框将被打开,在
Select
Board Interface
的下拉菜单中选择
leds_
8bit
选项,点击
OK
,如图
9-18
所示。
图
9- 18 Run Connection
Automation-GPIO
注:当使用如上的方式来对
GPIO Make Extern
al
时,
Vivado
会自动在系统中
添加约束文件,将
GPIO
连
接到
p>
ZedBoard
的
LED
引脚上。
10)
当完成上面一步,在
Diagram
中应该看到
如图
9-19
所示的画面。
图
9- 19 Module Connect
System
11)
IP Integrator
将会自动为挂在
< br>AXI
总线上的逻辑设备分配地址空间,
这样
ARM
才可以寻址到
P
L
端的逻辑设备。选择
Address
Editor
选项,并展开
Data
,如图
9-20
。可以看到
IP
p>
Integrator
已
经为
AXI
GPIO
分配了
64K
的地址空间,基地址为
0x41200000
。由于
ARM
是统一编址的,所以
在编写
ARM
程序的时候就可以像读写内存一样直接对
该地址进行读写,从而实现对该
IP
核的
控制。
图
9- 20
地址编辑器
12)
保存工程:
Ctrl + S
13)
在
D
iagram
窗口的左面工具栏中选择
Validate
Design
按钮
检测设计的有效性。这个操作将会
调用一次
DRC
检测,如果检测正确,
Validation
successful
对话框将会弹出,
否则根据错误信
息
进行改正。点击
OK
完成设计有效性检测。至此,一个简单的<
/p>
IP
子系统已经设计完成,下面
我们将设
计完成
Block Design
生成可以综合的
HDL
设计文件。
14)
在
S
ource
窗口中
,
选择
Sources
选项,右键
Block
设计
zynq_system_1
,
选择
Generate Output
Produc
ts
…
,如图
9-21
。
图
9- 21
生成
HDL
文件
15)
在弹出的对话框中直接点击<
/p>
Generate
。这一步将会生成
Di
agram
Block
Design
的
HDL
源文件以
及相应端口的约束
文件。
16)
继续右键
zynq_system_1
,
< br>选择
Create HDL Wrapper
,保持默认
选项,点击
OK
关闭
Create
HDL
Wrapper
对话框。这里,
Vivado
会为
IP
子系统生成一
个顶层文件,这样我们就可以对该系统
进行综合、实现并生成
b
it
流了。
17)
在
Flow
Navigato
r
中
,
展
开
Program
and
Debug
,
点
击
Generate
Bitstream
,
这
时
NoImplementation
Result Available
对话框被打开,
点击
YES
,如图
9-
22
。
18)
当
b
it
流生成完成,
Bitstream
Generation
successful
completed
对话框被打开,
选择
Open
Implementation Design
对话框,点击<
/p>
OK
完成,如图
9-23
所示。
当
bit
流生成完成后,在
Vivado
中最后的工作就是
要将设计导入到
SDK
中,然后对
AR
M
进行编程,
控制
ZedBoard<
/p>
上的
LED
灯,实现我们这次实验的目的
。
图
9-
22
生成
bit
流
图
9- 23
打开实现设计
19)
在
IP
Integrator
下点击
Open Block Desi
gn
,选择
zynq_system_
,重新打开前面创建的
Block
Design
,如图
9-24
。
图
9-
24
打开
Block Design
20)
选择
File > Export > Export
Hardware for SDK
…
.
,
Export Hardware for SDK
对话框将被打开,确保
Include bitstream
和
Launch SDK
两个选项被
选中,如图
9-25
,点击
OK
。
注意:这里要导入的
Source
是
Block Design
,所以必须要先将
zynq_system_
打开,否
则会出现错
误;要想将
bitstream
导入到
SDK
,
必须先打开
implementation
design
,否则这里的
Include Bitstrea
m
将会是
disable
的。
21)
到此,在<
/p>
Vivado
下的工作就算完成了,如果没有出现错误,说明我们
的硬件工程总体上是没
有问题的。下面一节我们将在
SDK
p>
中创建一个简单的应用程序,来完成软硬件协同设计中的软
件部分。
图
9- 25
将硬件设计导入到
SDK
9.1.3 SDK
应用程序编写
这一节我们将讲解如何使用
SDK
来创建一个简单的软件应用程序,并使用该程序来对
ZedBoard
上的
LED
进行控制。从前面可以看到,系统已经为
AXI
GPIO
分配了一个地址空间,
ARM
处理器通
过访
问该地址空间中的寄存器来对
GPIO
进行控制寄存器,从而达到控制
ZedBoard
上的
p>
LED
。
如果你是接着
9.1.2
来做这一节实验的话,当你完成
9.1.2
最后一
步的时候,
SDK
就会自动的启
动了,
否则我们可以通过浏览
Start >
All
Programs >
Xilinx
Design
Tools > Vivado
2013.4
> SDK
>
Xilinx
SDK 2013.4
来启动
SDK
,并将
Worksp
ace
定位到
:
C:XUPZedf
irst_zynq_designfirst_zynq_SDK_Export
当
SDK
打开后我们就可以创建自己的应用程序了。
1)
选择
File > New > Application
Project
。
2)
在
Application
Proj
ect
对话框中输入
Marquee
作
为
Project
Name
,其他的
保持默认设置,如图
9-26
,点击
N
ext
。
图
9- 26
新建
< br>SDK
工程
3)
在
Te
mplates
对话框中,选择
Empty Applicat
ion
,这里我们创建一个空工程,如图
9-27
所示,点
击
Finish
完
成工程创建。
图
9- 27
创建一个空白模版
4)
当
工<
/p>
程
编译
完
成,<
/p>
SDK
会
自
动<
/p>
打开
文
件
,
该文
件
存在
于
板级
支
持
包文
件
夹
Marque
e_bsp
下。该文件提供了系统中所有的外设详细信息。
Do
cumentation
和
Example
提供
了该外设很详细的设计参考,
包括一些重要的数据结构以及
API
,或一些可用的参考例程
,如
图
9-28
。
图
9- 28
文件
5)
选择
File > New > Source File
p>
,
在弹出的对话框中点击
Browse
p>
按钮,选择
Marquee/src
作为<
/p>
Source
Folder
,在
Source
p>
File
输入框中输入
Marquee.c
,点击
Finish
完成
Source
File
的添加
,
如图
9-29
。
图
9- 29
新建
Source File
6)
下面来编写
Marquee.c
,具体代码如下所示。
#include
/*
Peripheral parameters */
#include
/* GPIO
data struct and APIs */
#include
< br>#include
#define
GPIO_BITWIDTH
8
/* This is
the width of the GPIO */
#define
GPIO_DEVICE_ID
XPAR_AXI_GPIO_0_DEVICE_ID//device id
#define
LED_DELAY
10000000/* times delay*/
#define
LED_MAX_BLINK
0x1
/* Number of times the
LED Blinks */
#define
LED_CHANNEL 1/* GPIO channel*/
#define
printf xil_printf
/* A smaller footprint printf */
XGpio
Gpio; /* The Instance
of the GPIO Driver */
XGpio
GpioOutput; /* The driver instance for GPIO Device
configured as O/P */
int
GpioMarquee
(
u16
DeviceId,
u32
GpioWidth)
{
volatileint
Delay;
u32
LedBit;
u32
LedLoop;
int
Status;
/*
* Initialize the GPIO driver so that
it's ready to use,
*
specify the device ID that is generated in
xparameters.h
*/
Status =
XGpio_Initialize(&GpioOutput, DeviceId);
if
(Status !=
XST_SUCCESS) {
return
XST_FAILURE;
}
//Set the direction for all signals to
be outputs
XGpio_SetDataDirection(&GpioOutput, LED_CHANNEL,
0x0);
// Set the GPIO
outputs to low
XGpio_DiscreteWrite(&GpioOutput, LED_CHANNEL,
0x0);
for
(LedBit = 0x0; LedBit < GpioWidth; LedBit++) {
for
(LedLoop = 0; LedLoop < LED_MAX_BLINK; LedLoop++)
{
//Set the GPIO Output to High
XGpio_DiscreteWrite(&GpioOutput,
LED_CHANNEL,
1
<< LedBit);
//Wait a small amount of time so the
LED is visible
for
(Delay = 0;
Delay < LED_DELAY; Delay++);
//Clear the
GPIO Output
XGpio_DiscreteClear(&GpioOutput,
LED_CHANNEL,
1
<< LedBit);
// Wait a small amount of time so the
LED is visible
for
(Delay = 0;
Delay < LED_DELAY; Delay++);
}
}
return
XST_SUCCESS;
}
int
main
(
void
)
{//Application start
/* loop forever*/
while
(1){
u32
status;
status =
GpioMarquee (GPIO_DEVICE_ID,GPIO_BITWIDTH);
if
(status == 0)
printf(
);
else
printf(
);
}
return
XST_SUCCESS;
}
7)
保
存工程,等待编译结束。该程序以
main
函数开始,之后进入
一个无限循环,不断的调用
GpioMarquee
函数。
p>
Xgpio_Initialize
函数在
gpio.h
中被定义,它的功能是对
XGpio
句柄进
行
初
始
化
,
XPAR_AXI_GPIO_0_DEVIC
E_ID
在
xparameters.h
文
件
中
被
定
义
,
该
文
p>
件
是
Vivado
IDE
自
动
生
成
并
导
入
到
SDK
中
的
,
它
包
含
了
p>
所
有
的
系
统
硬
件
设
备
参
数
。
< br>XGpio_SetDataDirection(&Gpio, LED_CHANNEL, 0xFF )
函数设置
GPIO
指定通道的
I/O
方