封装带AXI接口的自定义IP核
为了更方便地使用外部接口驱动或进行系统级的设计时,可以考虑将RTL设计打包制作成自定义的IP核,Vivado会自动生成相关的IP核接口;或者为了在ZYNQ中使用AXI总线将硬核与FPGA硬件部分互联,可以将FPGA部分的RTL设计打包成自定义IP核,Vivado会自动将生成的IP核的接口制作好,使用图形化界面就能快速实现SoC设计。特别地,可以使用这种方法在硬核外挂载软核
在Vivado的设计思想中,一个IP核就相当于一个函数,可以通过重用IP核做到模块化设计的效果
可以参考Xilinx Vivado封装自定义IP参考手册【代号ug1118】来获得更详细的操作指示
第一部分仅说明带AXI接口的自定义IP核封装方法
创建与封装自定义IP的意义
在Vivado中含有一个IP Catalog流程,可以将下列源文档封装成自定义的IP
- RTL级HDL源文件
- 模拟模型文件
- 示例设计文件
- Testbench
- 项目文件目录
- Block Design
同时Vivado也内置了Xilinx自制IP、第三方IP、用户定义IP的库
比起传统“Add Module”将RTL代码以中间级模块的方式例化添加到顶层模块,再封装出统一的顶层模块这样的操作流程,通过可视化的IP核管理可以更快速地实现项目模块化和后期完善修改流程
创建自定义IP
示例程序使用自定义的IP实现LED呼吸灯效果
这个IP使用AXI接口与ZYNQ的硬核连接,可以使用软件控制IP核的“外设控制寄存器”来对自定义IP核的工作状况进行控制
创建IP工程
为了更好管理自定义IP核,通常将用户的RTL代码统一管理在独立目录下
在Vivado开始界面选择【Tasks】-【Manage IP】,选择新建一个IP核管理目录或打开已有目录,并新建项目
根据自己的硬件设备和习惯使用的HDL选择针对性的选项
完成创建后,选择【Tools】-【Create and Package New IP】
如果准备创建一个单独的IP,可以直接Next,相关内容在下一部分介绍;在这里因为准备创建的项目需要使用到AXI4接口与硬核交互,所以选择最后这个选项
设置IP核名称后如下图进行AXI接口设置
其中AXI接口有三种类型:
- Lite:适合数据量较小、速度较快的信号传输
- Full:全规格的AXI总线,适合标准类型的数据传输
- Stream:数据流传输,适合音视频信号等大规模数据的高速传输
还有两种模式:
- Slave:从模式,IP接受外部数据控制
- Master:主模式,IP控制外部设备
完成设置后可以看到右侧User Repository中出现了自定义IP核
这里右键IP核,选择【Edit in IP Packager】,之后Vivado会打开一个新界面用于管理IP核的RTL代码
自动生成的RTL代码分为两部分,一个是顶层模块,另一个是AXI总线接口逻辑;RTL代码中还默认生成了AXI总线相关逻辑的例化和提供给用户使用的区域(包括自定义参数、自定义端口、自定义顶层模块例化),但是需要注意:如果在AXI总线上开辟了独立的新端口,需要将相关代码单独添加到AXI总线逻辑的RTL代码中
编写IP内部RTL代码
顶层例化代码如下所示:
1 |
|
默认生成的顶层代码大同小异,无非是AXI总线有无的区别
这里省略AXI总线逻辑代码(太长了)
注意改动代码时如果涉及到接口,需要同时修改顶层代码和AXI总线实现
其中比较常用的部分已经被Vivado自动空出来,如下所示:
1 | //在开头有这四行代码 |
右键点击【Design Sources】,选择添加新的HDL文件,编写呼吸灯控制代码,如下所示,并保存
1 | module breath_led( |
在Vivado自动生成的AXI总线逻辑文件中如下编写例化:
1 | // Users to add parameters here |
在Vivado自动生成的顶层文件中如下编写例化:
1 | // Users to add parameters here |
编辑完成后即可退回原菜单
点击左侧流程中的【Run Synthesis】即可进行IP核的综合
设置IP的可视化界面
打开xml文件后即可在Vivado中进行编辑,
按顺序设置即可
其中在【Customization Parameters】菜单下会出现“更新参数”的选项提示,更新后会现多出一行自定义的参数,双击它如下图进行设置,即可将这个参数反映到IP可视化界面
完成所有设置并确认无误后,即可在最后选项【Review and Package】中点击【Re-Package IP】即可封装IP
关闭项目后可以在原来的Vivado窗口中看到如下显示
证明完成了IP封装
使用自定义IP
硬件部分
完成封装IP后,在任意工程中点击左侧【IP INTERGRATOR】-【Create Block Design】创建基于IP核的FPGA设计
但此时IP选项列表中没有自定义IP核,需要自己将IP核添加到工程
选择【Tools】-【Settings】-【IP】-【Repository】-【Add(加号+)】选择存放自定义IP的文件目录,即可将自定义的IP核添加到项目
如下图对IP核进行设置
设置ZYNQ系统的DDR控制器和外设后,先进行自动生成原理图,再进行自动布线即可
注意要在led引脚处右键选择【Make External】生成一个引出的外部引脚,并将其改名为led
生成外部引脚的过程就是使能逻辑块与IO块连接的过程
接下来按照正常步骤生成硬件平台配置
由于led端口连接到PL部分,所以需要进行管脚约束才能使用
点击左侧综合按钮,综合后打开引脚设置(I/O Ports),将led_0的引脚映射到PL部分MIO上
根据手头的开发板选择引出引脚即可
这里选用的是PL Bank的P15引脚
最后生成比特流并导出到硬件即可
软件部分
还是原来的步骤从.xsa文件导入配置到Vitis,并创建一个新应用程序
使用的软件代码如下所示
总体思路就是读写外设寄存器映射来的地址对外设寄存器进行操作
1 |
|
烧录后LED呈呼吸灯效果,且可以看到呼吸灯闪烁频率变化
封装不带AXI接口的IP核
Vivado支持将独立的RTL代码封装为IP核,方便以类似函数的方式重用IP核,同时可使用用户自定义的IP核接口协议
参考【ug1118】手册来获取详细信息
创建自定义IP
IP核逻辑封装
- 创建一个RTL工程
- 编辑IP核的RTL代码
- 验证IP核逻辑并进行仿真
- 创建一个基于已有RTL代码的IP核封装
- 修改顶层文件
- 设置IP核端口和控制引脚端口输入输出模式(端口映射)
- 修改IP核的可视化界面配置进行封装
- 创建接口定义
接口封装
- 编辑接口协议的RTL实现
- 在IP核封装完成后在配置接口定义部分对接口进行相关设置
- 依次调整接口协议封装
- 添加接口协议的RTL文件
- 进行接口RTL文件的顶层文件端口映射
- 点击【Package IP】完成IP核封装
使用自定义IP核
封装好的IP核如果出现适用设备相关的错误,可以直接删除对应的封装信息
使用IP核前需要先对IP核进行验证,可以选择编写testbench(普普通通的ZYNQ-7020板子配那么小的LUT规模直接烧就完事了!),也可以直接烧录到开发板(如果开发板很贵就别这样干了)
IP核验证完毕后就可以随意使用了
封装IP核时可能遇到的问题
封装的IP核中包含了其他IP核
如果包含了.xci文件(IP核的配置文件),Vivado会直接用新生成的子IP创建输出文件
如果包含IP核的输出文件,Vivado则会从IP设置中生成HDL和XDC代码
封装时推荐直接使用包含.xci文件的方式打包IP核,这样会方便重用IP和生成输出文件
只要在打包当前IP的时候选择相关选项即可
如果在封装前分配好了引脚约束应该怎么办
一般来说使用IP核的时候再进行引脚约束的过程会把之前的引脚约束覆盖掉
但是为了保证不出错,一般在打包前或打包后将IP核的.xdc文件删除