zynq 7000 自定义IP 实验

本文通过一个简单例子介绍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/1b9tTFK 密码:vn92

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 <stdio.h>
#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<<Ledwidth);
              for (Delay = 0; Delay < 18000000; Delay++);
          }
      }
    cleanup_platform();
    return 0;
}


文件中有

#define MY_IP    0x43c00000 ,其来由在Vivado 的地址中得到。

保存文件并编译链接,Run AS-> 或者 Debug As ->  Launch on Hardware(System Debugger

就看到流水灯的运行了。


原文链接:https://blog.csdn.net/leon_zeng0/article/details/78674832

猜你喜欢

转载自blog.csdn.net/lyfwill/article/details/81156459