本文通过一个简单例子介绍zynq 7000中自定义ip 的设计过程。 此例子就是控制4个led 。 在ps-pl 试验中,一般用的就是Vivado 自带的GPIO ip。 所以如果你熟悉了PS端和PL端协同设计流水灯试验,对于本例子就只需关注自定义ip 的设计了。如果你还不熟悉这种协同设计,那你就得先学习好了,再来看本文试验。
本文就是用自定义的ip 替代自带的gpio ip来控制流水灯。其主要意义是掌握自定义ip 的设计过程。
本文测试环境是Vivado 2015.4, 测试硬件是黑金的AC7010, AX7010。
本文的源代码下载地址:
链接:https://pan.baidu.com/s/1N6VyY7bZ0dX-KIkQfrmWrw
提取码:yri1
1:新建一个试验工程
打开Vivado, 点击新建工程,工程取名custom_ip。
一路Next , 在这个界面设置好你所用的硬件,我的是这样的。
工程建立好是这样的,点击Create Block Design。
取名system。
在原理图里右键添加ip , 添加ZYNQ Processing System. 添加完成后点击 Run Block Automation。
然后 点击图标, recustom ip, 设置处理器。首先设置好DDR, 我的是这样选择的。
设置信息监控端口, UART1, 其实也不是很重要。
时钟设置比较重要,选择Clock Configuration,点开 IO Peripheral Clocks, PL Fabric Clocks, 检查FCLK_CLK0 是否已勾上,并且频率设置为100 MHZ。
PS-PL Configuration 这里也要选择好。
2: 建立自定义IP 。 菜单选择 Tools -> Create and Package IP... 。
Next 到这个界面, 做如下选择: 选择 Create a new AXI peripheral
在这个界面做好设置和选择;
这个接口设置很重要,按如下设置好。
到这个界面,选择 Edit IP, 然后点击Finish。
Finish 后界面是这样的。
3: 自定义ip 的设计
我们先来看看主界面。在 Design Source 下面有2个.v 文件。上面的myip_led_v1_0.v 是顶层文件, top level,但他只是实现接口界面,并调用实例函数。所以真正实现是在 下面的文件, myip_led_v1_0_S00_AXI.v, 当然这个文件主要是实现AXI接口。重要的逻辑实现需要我们另外添加自己的函数。但在这个例子,我们把这部分最简单化,只是实现一个很简单的功能。
这个实现文件很长,有400行多,但层次很清楚,每段实现一个逻辑点,并且有注释。这里不分析那么多了。
上图里是添加参数的位置,简化一点,不改参数了,所以这段后来取消了,就是取消了参数添加段,但保持注释。
寻找到下面注释段(line 16-20):
// Users to add ports here
// User ports ends
// Do not modify the ports beyond this line
这里是添加ports 的地方,我们添加ports, 结果如下
// Users to add ports here
output wire [3:0]LED,
// User ports ends
// Do not modify the ports beyond this line
寻找到下面注释段(line 392-394):
// Add user logic here
// User logic ends
这里是添加逻辑的地方,可能有很多逻辑设计,或者调用自己定义的很多函数实现
但这里我们简单化, 只是添加一点点assign LED[3:0]=slv_reg0[3:0];
结果如下:
// Add user logic here
assign LED[3:0]=slv_reg0[3:0];
// User logic ends
以上是我们对AXI接口实现函数的修改。很简单,找到地方添加2行。
下面我们对顶层文件做一点修改,点击并打开 myip_led_v1_0.v,找到如下地方(line 16-20)
(
// Users to add ports here
// User ports ends
// Do not modify the ports beyond this line
这是添加ports 的地方,添加后结果如下:
(
// Users to add ports here
output wire [3:0]LED,
// User ports ends
// Do not modify the ports beyond this line
找到如下位置(line 46-51), 就是AXI实例化开始的地方,上面部分是参数设置的地方。
// Instantiation of Axi Bus Interface S00_AXI
myip_led_v1_0_S00_AXI # (
.C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
.C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
) myip_led_v1_0_S00_AXI_inst (
.S_AXI_ACLK(s00_axi_aclk),
我们需要让2部分是端口对应起来,所以添加了 .LED(LED), 结果如下:
// Instantiation of Axi Bus Interface S00_AXI
myip_led_v1_0_S00_AXI # (
.C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
.C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
) myip_led_v1_0_S00_AXI_inst (
.LED(LED),
.S_AXI_ACLK(s00_axi_aclk),
好的,代码修改的任务完成了。保存此2个文件,特别是检查是否有错误。 有错误会告诉你错误了,但具体是哪里,我不知道,我一般综合一下,容易定位错误的具体地方。
双击IP-XACT下的component.xml ,返回到Package IP 窗口。下面是各种对应关系。
在左边没有绿勾的地方点一下,应该最开始是 Ports and Interface, 但我没截图,这里是 File Groups, 看看蓝色的提示条: Merge changes from File Group Wizard ,点击它。
点击后就全变绿勾了。右边的东西点开看看:
选择 Reviews and Package。 可以看到一些信息, 红框里说 inarchive will not be generate. Use the setting link before to change。
你想改变的话,可以点击试试看。 点击Re-Package IP。这样就完成了IP的设计了。
4:添加自定义ip 到原理图中验证
re-package ip 后,如下提示,我选择Add IP to Block Design,添加到原理图中。 如果不是这样, 你可能需要一个添加自定义ip 的程序。 自定义ip 路径设置,然后添加ip。
ip 添加到原理图中如下,点击Run Connection Automation。
所有线都连接好了, 但Led 还没有输出。 选择ip 的LED,
选择ip 的 LED,并右键选择 Make External
这样LED有了输出。
添加约束文件
此后就是常规操作了,在Source 中选中system.v,右键并先后选择 Generate Output Products 和 Create HDL Wrapper。 然后产生流文件。
硬件输出,菜单File -> Export -> Export Hardware , 这里要选择包含流文件。
菜单选择File -> Launch SDK 启动SDK开发环境。
5: SDK软件编程
新建工程:
菜单 File -> New -> Application Project
工程取名为test_led。
选择hello world 工程样本。
然后修改helloworld.cpp 如下:
#include
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#define MY_IP 0x43c00000
int main()
{
init_platform();
print("Hello World\n\r");
u32 Delay;
u32 Ledwidth;
while (1)
{
for (Ledwidth = 0x0; Ledwidth < 4; Ledwidth++)
{
Xil_Out32(MY_IP,1 << Ledwidth);
//printf("led=%x\n\r",1<
}
}
cleanup_platform();
return 0;
}
文件中有
#define MY_IP 0x43c00000 ,其来由在Vivado 的地址中得到。
保存文件并编译链接,Run AS-> 或者 Debug As -> Launch on Hardware(System Debugger
就看到流水灯的运行了。