对于使用Xilinx平台的FPGA开发工程师来说,AXI总线开发可以说是一项不得不掌握的技能。因为在Xilinx家的硬件平台下,AXI总线基本上无处不在,在Vivado的IP库中,但凡和数据传输有点关系的IP也全是采用AXI总线接口。
如果只是做纯FPGA逻辑开发,或许没有AXI总线也无妨。但对于Zynq开发来说,AXI总线似乎就是一道不得不跨过去的坎了,因为Zynq的架构下,PS与PL的数据交互全是采用AXI总线,不掌握AXI总线,简直寸步难行。
作为一名学习时长两年半的FPGA工程师,搞Zynq开发也有些时日了,从本篇开始,我将用一个系列文章记录下学习AXI协议需要注意的方方面面,内容包括学习方法、协议解读和开发实例等。以期对大家对学习AXI有所帮助,并能最终拿下AXI。
介绍AXI之前,要知道ARM AMBA(Advance Microcontroller Bus Architecture),这是ARM在1996年提出的一个微控制器的片上总线协议,大家熟悉的AHB或APB等总线协议都是AMBA的一部分,而AXI在AMBA 3.0版本成为该协议的一部分,目前Xilinx的7系列FPGA中用的是AMBA 4.0版本中的AXI协议,所以你会看到Vivado中带AXI接口的IP介绍都是AXI4打头。它们的关系如下图所示:
AXI4总线有四种类型:AXI4、AXI4-Lite和AXI4-Stream。
AXI4用于高性能内存映射(Memory-Mapped)型的通信上。
AXI4-Lite用于简单低吞吐量的内存映射型通信上(比如简单的寄存器读写)。
AXI4-Stream用于高速的数据流传输,无需地址管理。
从以上介绍和实践开发来看,AXI4主要用于大块的数据读写,如DDR、BRAM的数据搬移;AXI4-Lite主要用于外设模块的配置,状态寄存器的读写等;而AXI4-Stream主要用于高速数据的传输,如高速AD数据、视频数据等的传输。
我入门学习过程大致分为以下三个阶段:
下面谈谈这三个阶段的具体实践经验。
当然了,搞硬件开发其实规范文档和说明文档都是工程师第一个应该看的文档。学习AXI总线也是这样,AXI的规范文档(第四版)可以在ARM的官网下载,地址如下:
AMBA AXI and ACE Protocol Specification:https://documentation-service.arm.com/static/5f05e40edbdee951c1cded41?token=
AMBA AXI-Stream Protocol Specification:https://documentation-service.arm.com/static/5f106cd00daa596235e813f8?token=
第一个文档是AXI和ACE的规范,我们只需要阅读学习Part A和Part B与AXI有关的内容即可,第二个文档是AXI-Stream的规范。
其实整个文档内容并不是很多,这也说明其实AXI协议没那么难懂(如果你看过PCIe等总线的文档就更加明白我的意思了←_←)。
首次阅读AXI规范,肯定多少有些难以理解,会遇到很多新概念,如Burst、Transfer、Alignment之类的。我的建议是先跳过这些概念和具体的信号定义,先通读三五遍协议,掌握整个协议的框架,再深入学习这些重点概念和具体的信号。那么AXI协议的框架应该掌握些什么内容呢?
第一,AXI协议是一个点对点的传输协议。总线两端发起读写事务的一端称为主设备,响应事务的一端是从设备。点对点传输意味着本条总线只能用于两个设备间通信,和SPI等接口不一样,不存在片选从设备这样的机制。那你肯定会问,那如果主设备想访问多个从设备该怎么办?或者某个从设备需要被多个主设备访问该怎么办?这就需要AXI总线中一个重要的设备:中央互联(Interconnect)。一般来说,系统中的电路结构如下图所示:
中央互联提供了设备间一对多,多对多的访问能力。可以把它理解为AXI总线版的路由器。
第二,AXI协议是一个读写通道分离的总线协议。可能是受大学学习计算机原理影响较深,我在首次理解通道分离还是用了些时间。AXI协议的读写分离不仅仅是数据总线是分离的,地址和控制总线也是分离的。这样的特性导致我们可以在总线上全双工的读写数据,提高总线带宽。而且AXI通道分离的特性也意味着,通道之前几乎没有任何关系(注意是几乎没有,后面会重点了这个话题),怎么理解?例如,写事务并不一定非要等地址和控制信号发送以后再发送写数据,AXI允许先发送写数据再发送写地址和写控制;AXI也允许先发送多个写地址和写控制,再慢慢发送写数据,而不是一次地址一次数据这样的传统总线模式。可以看到,AXI协议读写通道分离的特性,会带来很多的不一样的总线使用方式,在以后的文章会逐一介绍。
第三,掌握AXI的通道握手机制。握手机制可谓是AXI总线的精髓所在,很简单却又很巧妙,一定重点优先掌握。AXI总线的各通道都会有一对握手信号:Valid信号和Ready信号,只有在两个信号都有效时,通道数据才开始传输。这样的设计导致AXI总线上的主从设备都可以随时根据自身情况开启或中断通道的数据传输,即所谓的双向流控机制。
上述内容是理解AXI总线的前提,一定要优先掌握。之后就可以深入学习具体的信号定义了。
在学习完AXI总线规范后,接下来就应该找一些别人的代码进行学习,达到快速入门的目的。这里提一句,规范看完后肯定多少有些云里雾里,这个时候也不用担心,拿着人家的代码慢慢看,慢慢仿真,再回过头去理解规范,反复搓揉几次自然就懂了。
按照我的经验,中文互联网上找不到太多值得仔细阅读的代码。大多是教你怎么创建一个AXI外设这样的入门第一步的东西,有些甚至连Vivado提供的AXI模板代码都不清楚怎么回事直接拿来就用。这对于入门来说是极其不友好的,在后续的文章中我也会详细讲解Vivado的模板代码,以及拿我平时写的一些AXI设备为例进行讲解,让大家更好理解AXI。
在模仿学习阶段,一定要自己动手仿真,且要吃透仿真结果,切记不可轻易放过任何疑点。一方面是熟悉AXI规范;另一方面也是锻炼自己的仿真工具熟练度以及分析问题的能力。
有了AXI协议的基本认识后,也认真动手仿真了,接下里就该尝试自己独立开发啦。
这个过程就比较漫长了,由浅入深。可以先试着用总线点个灯,自己写个计数器总线来控制初值,再到操作DDR,配合Vivado提供其他AXI外设完成较大的工程等。我自己也还在不断的学习探索,这时候主要看个人兴趣和工作需要了。
但在独立开发AXI设备时候一定要学会一项技能:学会使用Vivado提供的AXI验证IP。AXI验证IP可以完成协议检查,事务完整性检查,可以充当主设备发起各种总线事务,也可以充当从设备响应各种事务,还可以纯粹的作为一个观察总线数据的窗口。总之,你不用吭哧吭哧写Testbench,谁用谁说好,以后文章也会重点介绍。
本篇对AXI做了简单介绍,重点和大家聊了如何学习AXI协议,以及学习过程中需要注意的重难点。在以后的文章中,我们将参考规范文档结合具体的实例,给大家一一分析解读AXI协议,以及上文提到的重难点。
下一篇文章,我们重点解读AXI协议的精髓:握手机制。