ZYNQ的自定义IP

1、实验原理

在vivado中可以将自己写的verilog模块封装成IP核,并入bd设计,有效地提高了PS到PL的设计内联能力。同时,这部分的学习可以将verilog的基础知识转移到嵌入式设计中。所以,这是一个基本的能力。

2、实验操作

一、创建工程

这一步根据自己的开发板选型即可。没有特殊的设置。

二、新建文件

在source的hierarchy(层次)中添加文件user_gpio.v,就是通过自定义的模块实现GPIO的传输。模块的功能很简单,就是将输入连到输出。

module user_gpio(
input wire gpio_in,
input wire [3:0] ps_gpio_in,
output wire gpio_out,
output wire [3:0] ps_gpio_out
);
assign gpio_out = gpio_in;
assign ps_gpio_out[3:0] = ps_gpio_in[3:0];
endmodule

代码参考小熊猫课堂。

三、基于AXI总线的IP打包

基于AXI总线的IP打包可以将IP快速地部署到总线上,可以与总线上的其他设备充分交互,自然也可以通过总线的引脚接出芯片。

tool》【单击】create and  package new IP》next》【选择】Create AXI4 Peripheral》next》 寄存器数量选择4》【选择】edit》finish

在新弹出的窗口中,就是IP核的编辑界面,其与工程界面分立,说明不依赖于特定工程存在。

在这个窗口可以编辑AXI总线IP核。

和verilog的模块间的调用一样,在IP核的顶端和子模块中加入端口声明也是端口输入输出,例化用点连接。值得注意的是,这里只例化两个端口gpio_in和gpio_out,而对于ZYNQ内核端的输入输出信号在这里并不连接,作为空置引脚。在后面会连接到寄存器。

为了使AXI寄存器控制起效和简洁,需要更改某些寄存器的设置。

在如图所示的位置更改112~114三行代码。从reg变成wire应该好理解,我们做的模块功能单一,不需要使用reg变量实现控制的目的。其他两个变量则是多余的变量。从前面寄存器数量最小为4可以得到,该IP设计默认至少使用4个寄存器,而我们这里太简单,只需两个,所以需要手动删除。

改完之后将下面所有的报错点屏蔽掉,即可完成配置。

这里也从一个侧面说明几个寄存器之间不存在直接关联。

在子模块的尾部插入如下代码:

// User logic ends
wire ps_gpio_in;
wire [3:0] ps_gpio_out;
assign ps_gpio_out[3:0] = slv_reg0;
assign slv_reg1 = ps_gpio_in;
user_gpio test(
.gpio_in(gpio_in),
.gpio_out(gpio_out),
.ps_gpio_in(ps_gpio_in),
.ps_gpio_out(ps_gpio_out)
);

这里也解释了前面为什么要使用wire型的slv_reg1,主要是节约赋值时间。

如果以后有时间可以学习AXI总线协议的话,或许就可以看懂现在的模块,现在不做讨论,主要了解如何在AXI的IP上搭建verilog的自定义IP。

四、打包整合后的工程

tools》Create and package new IP》next》package your current project》next》overwrite》finish

这一步的操作就可以将整合后的工程打包在一个IP。这里也有将这个工程IP添加到全局的设置,如果有需要的可以尝试一下。

五、bd设计,调用自定义IP

首先创建bd文件,然后调用zynq内核,这部分是基础操作,不做过多的说明。

配置内核也是按照开发板的习惯配置。需要添加UART和DDR,其他的基本默认。(在前面的基础实验中的操作都适用)(例如bank0和bank1的电压,我的是3.3和1.8)

调用自定义的IP加入设计

直接搜索输入user好像会自动显示自定义IP,没有试过其他的,我的可以。

加入之后就先自连,再引线,有强迫症的可以用一下整理。

这时候需要引出输入输出引脚到芯片外部,直接在引脚上右击,然后make  external,就可以直接连上外部引脚(当然,你得配置管脚以到具体的引脚)。

这时候的bd设计就已经完成了。

这里要注意系统分配的寄存器地址。在多个自定义设计中可能会用到。这个地址也会直接影响后面的软件操作。

六、构建硬件平台

bd文件只不过是一个IP集合,没有例化,自然不能直接往里面写软件。

在所属bd文件上右击》generate product 》create HDL wizard

这两步理解一下。generate productor是用于例化IP核的。bd文件将所有IP核的关系描述清楚后,需要将设计转化为具体的verilog模块来实现这种关系。至于create HDL wizard,就是自动例化顶层,相当于系统自动将bd的头部用verilog包装(你默认语言是verilog的话)。

分配引脚:在 open elboarded design中分配好管脚。

就可以综合映射得到bit流文件。操作上可以直接生成bitstream。

然后生成硬件平台,这就意味着硬件设计的结束。作为硬件开发者来说,就可以收工了。但是,了解软件部分的设计可以有效提高硬件的设计视野,这也是比较重要的部分。

此外,一定要在Tcl Console中查看一下hardware是否成功。vovado不会自动跳转到tcl,所以要注意一下。反正我的licence在这里总是失效。好像重启软件有用,也没啥好的解决方案。

这里还需要勾选包含bitstream,这个不要忘了。

七、软件设计

进入vitis,出现初始界面。这个过程比较长,不用太过惊讶。

一般来说,vitis默认的进入界面是上次的界面,所以需要整理一下。

加载硬件的方法在前面的GPIO实验中已经说明过了,这里就简述。

new》新建app》输入工程名》创建硬件平台(第二面,加号选择工程的xsa文件)》默认到底。

打开helloworld.c文件:

替换为

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "string.h"
#define IIC_BASEADDRESS 0x43C00000
#define REG0_OFFSET 0
#define REG1_OFFSET 4
u32 gpio_input_value=0;
char buf_print[64]={0};
int main()
{
int i=0;
init_platform();
print("Hello World\n\r");
while(1)
{
for(i=0;i<64;i++)buf_print[i]=0;
gpio_input_value=Xil_In32(IIC_BASEADDRESS+REG1_OFFSET);
sprintf(buf_print,"input gpio_value=%d\r\n",gpio_input_value);
print(buf_print);
Xil_Out32(IIC_BASEADDRESS+REG0_OFFSET,0);
sleep(1);
Xil_Out32(IIC_BASEADDRESS+REG0_OFFSET,0xffffffff);
sleep(1);
}
cleanup_platform();
return 0;
}

代码源自小熊猫课堂

这里同样不分析代码的内容,这是另外一个系列的学习内容,这里只是作为长见识。

保存---编译---调试---运行

就可以快速地将代码运行在开发板上。

3、实验结果

由于前面例化IP核时一个端口声明出现错误,而且当时没有做综合。导致又重来了一遍。教训呀。

这里总结一下更改的经验:

1、不要该IP的顶端,因为后面的输入输出信号与这里直接相关,牵一发而动全身。

2、不要省略每一个检查步骤,因为那都是用时间堆出来的教训。

3、更改的话以内部修改为主,不得已才去动外部设计。

4、总结

不知道是不是由于从SDK移植的代码不适用于vitis,还是代码设置出现错误,最后只是灯闪烁,IO和UART均不工作。果然还是要自己写代码。以后有机会再修正吧,目前暂时这样做。

5、追加

通过一次重头再来的排查,发现只有一个灯闪烁是因为输入输出在位数上发生错位导致数据丢失。串口没有反应是由于手贱多点了一个UART0,(实际上我那时修改过一次但是没有保存)所以在这里提醒操作要细心,不然费时费力、

下面附上实验结果:

实拍视频:

ZYNQ7000系列学习之自定义模块构成IP的更多相关文章

  1. Python开发【第一篇】Python基础之自定义模块和内置模块

    为什么要有模块,将代码归类.模块,用一砣代码实现了某个功能的代码集合. Python中叫模块,其他语言叫类库. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代 ...

  2. nginx自定义模块编写-实时统计模块--转载

    原文:http://www.vimer.cn/2012/05/nginx%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A8%A1%E5%9D%97%E7%BC%96%E5%86%99- ...

  3. ASP.NET自定义模块

    要创建自定义模块,类需要实现IHttpModule接口.这个接口定义了Init和Dispose方法. Init方法在启动Web应用程序时调用,其参数的类型是HttpContext,可以添加应用程序处理 ...

  4. Python爬虫与数据分析之模块:内置模块、开源模块、自定义模块

    专栏目录: Python爬虫与数据分析之python教学视频.python源码分享,python Python爬虫与数据分析之基础教程:Python的语法.字典.元组.列表 Python爬虫与数据分析 ...

  5. python开发学习-day05(正则深入、冒泡排序算法、自定义模块、常用标准模块)

    s12-20160130-day05 *:first-child { margin-top: 0 !important; } body>*:last-child { margin-bottom: ...

  6. optparser 模块 提取IP,端口,用户名,密码参数模板

    import optparse #class FtpClient(object): #自定义类可以自己修改 '''ftp客户端''' #def __init__(self): parser = opt ...

  7. ZYNQ自定义AXI总线IP应用——PWM实现呼吸灯效果

    一.前言 在实时性要求较高的场合中,CPU软件执行的方式显然不能满足需求,这时需要硬件逻辑实现部分功能.要想使自定义IP核被CPU访问,就必须带有总线接口.ZYNQ采用AXI BUS实现PS和PL之间 ...

  8. 【python】用setup安装自定义模块和包

    python解释器查找module进行加载的时候,查找的目录是存放在sys.path变量中的,sys.path变量中包含文件的当前目录.如果你想使用一个存放在其他目录的脚本,或者是其他系统的脚本,你可 ...

  9. angular(3)服务 --注入---自定义模块--单页面应用

    ng内部,一旦发生值改变操作,如$scope.m=x,就会自动轮询$digest队列,触发指定的$watch,调用其回调函数,然后修改dom树. 干货:https://github.com/xufei ...

  10. python基础知识8——模块1——自定义模块和第三方开源模块

    模块的认识 模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需 ...

随机推荐

  1. numpy数组初始化方法总结

    1 使用list初始化 a=np.array([[1,2,3],[4,5,6]],dtype='float32') #a=[[1. 2. 3.],[4. 5. 6.]] 2 赋值与复制 (1)赋值 a ...

  2. fgrep命令

    fgrep命令 当需要搜索包含很多正则表达式元字符的字符串时,例如$.^等,fgrep很有用,其通过指定搜索字符串包含固定字符,从而无需对每个字符进行转义用反斜杠,如果搜索的字符串包含换行符,则每行将 ...

  3. Delphi 实现刘谦春晚魔术

    看了博友的C# 实现刘谦春晚魔术很好,改成了delphi版的. 1 program Project1; 2 3 {$APPTYPE CONSOLE} 4 {$R *.res} 5 6 uses 7 S ...

  4. win32 - GDI+ 高斯模糊的使用

    虽然标题中标有GDI+,但其实真正实施的时候并没有用到. 不过GDI+的相关文档有一些关于高斯模糊的api说明,见下面链接: Blur class (gdipluseffects.h)    使用Bl ...

  5. 信捷电气 - C++工程师面试题(社招:3-5年工作经验)

    1. char i = 1; printf("%d",i);    // char字节用printf以整数型打印出来 2. int (*a[10])int a[10]是函数指针数组 ...

  6. [Revit二次开发] 使用过滤器时,可能存在的坑:FilteredElementCollector.MoveNext()报错

    1.问题描述 在使用FilteredElementCollector时,如果涉及到需要对collector进行多次过滤处理,可能会出现MoveNext的报错. 问题代码如下: 1 var collec ...

  7. python Apscheduler持久化

    from pytz import utc from apscheduler.schedulers.background import BackgroundScheduler from apschedu ...

  8. 【LeetCode剑指offer#05】回文链表的两种解法+删除链表中间节点(链表的基本操作)

    回文链表 给你一个单链表的头节点 head ,请你判断该链表是否为回文链表.如果是,返回 true :否则,返回 false . 示例 1: 输入:head = [1,2,2,1] 输出:true 示 ...

  9. expect tcl 摘录

    目录 部分参考来源说明 例子 expect命令 核心命令有三个 spawn.expect.send 其他expect命令 expect命令的选项 变量 tcl摘录 数据类型 符号 命令 其他说明 部分 ...

  10. ASP.NET Core 选项

    目录 1,选项接口 2,注入配置与IOptions 3,IOptionsSnapshot 首先要了解 ASP.NET Core 中的配置,请点击这里了解:https://www.cnblogs.com ...