AXI总线协议小记
参考
H.c版本AXI文档使用的manager(master)与subordinate(slave)在此用主机与从机表示
介绍#
根据文档所说,AXI协议可以做到:
- 地址可以在数据之前传输,也就是先传地址,再传数据,emm...
- 支持多个未完成的传输(看了这个协议的文档才知道,outstanding还有未完成的意思)
- 支持乱序完成传输
接下来看看AXI抽象出来的五个传输通道
通道 | 信号命名前缀 |
---|---|
读地址通道 | AR |
读数据通道 | R |
写地址通道 | AW |
写数据通道 | W |
写响应通道 | B |
一图胜千言,文档中用几张图简单描述了上面几个通道所携带的数据以及时序关系:
写操作
读操作
ok,简单来说就是将一堆信号抽象成五个通道,在主从之间控制传输的行为,每个通道包含各自的信号。
Channel(通道)#
五个通道的共同点#
都由valid、ready和其他信号组成。其中valid和ready就如同字面意思,分别表示发送方数据是否有效,以及接收方是否准备好接收数据,这两个信号是握手的基础。另外还约定last信号来指示本次数据是否最后一个数据。
各自通道还有他们的不同点
ARC/AWC(读地址通道/写地址通道)#
包含地址和控制信号
RC(读数据通道)#
包含数据总线(宽度可以是8、16...1024位)、用于指示本次读事务是否完成的读响应信号
WC(写数据通道)#
包含数据总线(宽度可以是8、16...1024位)、用于指示数据中有每个字节是否有效的strobe信号(strobe似乎是一个固有名词,大概作用就是指示接收者总线上的数据什么时候是有效的)
BC(写响应通道)#
类似读响应信号,用于指示本次写事务是否完成的响应信号。为什么写响应需要单独一条通道是显而易见的,因为读响应信号可以与读数据合并在一次传输,而“写”这个操作本来是不需要响应的,因此单独用一条通道来传递写响应信号。
设备之间的连接#
AXI给出了接口的定义。系统拓扑可以是:
- 共享地址线和数据线
- 共享地址线和多个数据线
- 多个地址线和数据线
多数情况下地址带宽比数据带宽小很多,因此可以选择第二种拓扑结构。
Register slice#
不知道是什么,暂时不管
信号定义#
信号不多且好理解,有的信号用于支持一些可选的特性。可以看一下,有个大致印象
全局信号#
时钟信号ACLK和复位信号ARESETn,复位低电平有效。所有信号都是ACLK上升沿同步的
AWC信号#
信号名称 | 信号源 | 说明 |
---|---|---|
AWID | M(Manager) | 写事务ID |
AWADDR | M | 写事务起始地址 |
AWLEN | M | 写事务中传输次数 |
AWSIZE | M | 写事务中一次传输的数据大小 |
AWBURST | M | 突发类型 |
AWLOCK | M | 原子操作相关 |
AWCACHE | M | 内存类型 |
AWPROT | M | 访问控制:权限、安全级别等 |
AWQOS | M | QoS相关 |
AWREGION | M | region指示器 |
AWUSER | M | 用户自定义信号 |
AWVALID | M | 数据是否有效 |
AWREADY | S(Subordinate) | 是否准备好接收数据 |
WC信号#
信号名称 | 信号源 | 说明 |
---|---|---|
WID | M | 写传输ID |
WDATA | M | 写数据 |
WSTRB | M | 写strobe,指示数据中哪些字节有效 |
WLAST | M | 指示是否写事务中最后一次传输 |
WUSER | M | 用户自定义信号 |
WVALID | M | 数据是否有效 |
WREADY | S | 是否准备好接收数据 |
BC信号#
信号名称 | 信号源 | 说明 |
---|---|---|
BID | S | 写响应ID |
BRESP | S | 写响应 |
BUSER | S | 用户自定义信号 |
BVALID | S | 数据是否有效 |
BREADY | S | 是否准备好接收数据 |
ARC信号#
与AWC信号类似,只是从写操作换成读操作相关,并且信号以AR为前缀
RC信号#
信号名称 | 信号源 | 说明 |
---|---|---|
RID | S | 读传输ID |
RDATA | S | 读数据 |
RREST | S | 读响应 |
RLAST | S | 指示是否读事务的最后一次传输 |
RUSER | S | 用户自定义信号 |
RVALID | S | 数据是否有效 |
RREADY | S | 是否准备好接收数据 |
一对一接口定义#
这个小节介绍一对一主从事务中信号实现的要求和定义
时钟和复位#
时钟ALCK#
所有输入都是ACLK上升沿有效。
注意,主从接口之间的输入输出信号不能有组合电路
复位ARESETn#
ARESETn异步低电平有效,但必须同步释放。复位使得:
- 主机接口拉低ARVALID、AWVALID、WVALID
- 从机接口拉低RVALID、BVALID
- 其他信号可以是任意电平
ARVALID、AWVALID、WVALID最早能置1的时刻为:ARESETn置1后的第一个ACLK上升沿
基础读/写事务#
握手#
当VALID和READY同时为高电平时才能开始传输数据,利用这点,发送方和接收方可以很方便地控制数据的传输速率。
注意,主从接口之间的输入输出信号不能有组合电路。
下图展示VALID在READY之前有效的一次握手:
文档中还提到:
A source is not permitted to wait until READY is asserted before asserting VALID
我一开始也不理解这句话,以为是VALID必须在READY有效之前就有效,但这样下面的「READY在VALID之前有效的握手」就不成立了。因此结合知乎大佬的文章,应该修正为:发送者不允许主动等待READY有效之后再置VALID有效,而是应该数据一旦有效就应当置VALID为有效
VALID一旦有效,就必须保持到握手完成,即VALID和READY均有效的上升沿。
下图展示READY在VALID之前有效的一次握手:
相应地,文档提到:
A destination is permitted to wait for VALID to be asserted before asserting the corresponding READY
也就是接收者可以等VALID有效之后再令READY有效,并且READY在有效之后,在VALID有效之前即握手完成之前将READY置无效。直观地看,接收者对于设置READY比发送者VALID的自由度更大。
各通道的握手信号及约定#
各通道的xVALID和xREADY的共同规则同「握手」小节中的VALID和READY。
AWC#
协议推荐AWREADY默认为高电平,不推荐默认低电平的原因是这样会使得传输需要至少两个周期,第一个周期用于使能AWVALID,另一个周期用于使能AWREADY。(???这不太理解)
WC#
WREADY的默认可以是高电平。当事务中最后一次传输的时候,主机必须置WLAST有效。协议推荐WDATA无效字节为低电平
BC#
BREADY的默认可以是高电平
ARC#
协议推荐ARREADY默认为高电平,理由同AWREADY。
RC#
从机只能在响应数据读取时才置RVALID有效。RREADY默认值可以是高电平。当事务中最后一次传输时,从机必须置RLAST有效。协议推荐RDATA无效字节置0
通道之间的关系#
AXI协议对于通道之间的关系只作了如下规定:
- 写事务最后一次传输必须跟着写响应
- 读地址后必须跟着读数据
- 握手必须遵循下面的「握手信号间的依赖」规则
对于其他情况,通道间保持独立互不影响。
当主机发起写请求事务,所有写数据的提供不能依赖于该主机其他的事务
握手信号之间的依赖#
再次总结VALID和READY的关系如下:
- VALID不能依赖于READY
- READY可以依赖VALID
其中第二点有利于设计更高效的通信。
对于不同通道,上述的两个规则有不同的具体表现,并用依赖图表示。在依赖图中:
- 单箭头:被指的信号不依赖于起始端信号,即可以在箭头起始端信号置有效前或置有效后置有效。
- 双箭头:被指的信号依赖于箭头起始端信号,即必须在箭头起始端信号置有效后再置有效。
起始端信号这里有点疑惑,起始端信号是依赖于被指信号还是不依赖?其实是起始端信号不能主动等待被指信号的有效而置有效,即起始端信号不能依赖于被指信号,比如读事务依赖中,ARVALID不能依赖于ARREADY,而ARREADY可以依赖于VALID也可以不依赖。
读事务依赖#
依赖图如下,可以看到RVALID必须在ARVALID有效之后有效,对应了「通道之间的关系」中的读地址后必须跟着读数据
写事务依赖(AXI3)#
依赖图如下,可以看到
由于写数据通道与写地址通道没有依赖关系,因此可以看到WREADY并不依赖于AWVALID。另外手册中图 A3-6 即上图中的注释部分似乎将 BVALID 误写为 WVALID,因为主机置起 WVALID 似乎与本次传输的 WLAST 无关,而且文本中也提到 BVALID 依赖于 WLAST(摘自参考链接)
写事务依赖(AXI4 & AXI5)#
这个版本协议的新增内容是,BVALID依赖于AWVAID、AWREADY、WVALID、WREADY,即地址和数据握手都成功的情况下才能响应。这个新增的依赖补充了当只有数据而没提供地址的时候,数据是不会被写入的,因此从机自然也不应该响应。
事务结构#
在 AXI 传输事务(Transaction)中,数据以突发传输(Burst)的形式组织。一次突发传输中可以包含一至多个数据(Transfer)。每个 transfer 因为使用一个周期,又被称为一拍数据(Beat)。
这个小节在五个传输通道与突发传输的基础上,探讨一下AXI突发传输的地址、数据读写与响应的具体细节,包括使用到的信号以及如何应对一些传输中的特殊情况。
地址结构#
AXI是基于突发传输的,也就是主机向从机发送控制信息+起始地址,就可以一次性传输多个数据单元,并且后面的地址都由从机自行给出。
一个突发传输地址不能跨越 4KB 边界,之所以这样规定是为了避免访问两个subordinate(每个subordinate的地址空间是4K/1K对齐的)。
-
突发传输长度(burst length)
长度指的是传输次数,由AxLEN给出。AXI3最大支持16,AXI4的INCR突发类型最大为256,其他类型仍为16。因此,传输次数:
- AXI3:Burst_Length = AxLEN[3:0] + 1
- AXI4:Burst_Length = AxLEN[7:0] + 1
突发传输的使用规则如下:
- 对于 WRAP 模式,突发传输长度仅能为2,4,8,16
- 在一次突发传输中,地址不能跨越一个 4KB 分区
- 一次突发传输不能在完成所有数据传输前提前结束(early termination)
注意,突发传输是不能提前停止传输的。如要要减少数据量,对于写突发传输,主机置strobes(WSTRB)无效即可。对于读突发传输,主机丢弃读到的数据即可,但是对于FIFO这样的读敏感设备,读操作是consuming的(无法再次读出来),简单丢弃的话第二次再读数据就已经不存在了,因此突发传输长度必须得刚好就是所要读的长度。
-
突发传输大小(burst size)
大小指的是每次传输(transfer/beat)的字节数,由AxSIZE给出:
当AXI总线宽度大于突发传输大小,需要根据传输地址决定哪些字节需要传输。
-
突发传输类型(burst type)
AXI协议规定了三种突发传输类型,由AxBURST给出:
- FIXED:突发传输中所有beat的地址都相同。例如可以用于加载或清空FIFO
- INCR:简单递增,比如访问一个对齐地址,大小4B,那么下个beat的地址+4
- WRAP:这个传输类型用于cache行访问,我暂时用不到,先简单有个印象:定义访问的最低地址对齐于突发传输总大小,且这个地址名为wrap boundary,而最高地址则为(wrap boundary + 突发传输总数据大小)。如果下一个访问的地址小于最高地址,则下一个地址如同INCR的简单递增,否则下一个地址又回到wrap boundary,一直这么循环往复。还有一些具体细节规定可查阅文档。顾名思义,wrap这个词就有一种将东西包回来的含义
-
突发传输地址(burst address)
这个小节中,文档给出了不同突发模式下地址和字节的计算,如地址对齐、wrap boundary、lower byte lane的值究竟是什么,这些都是前文用到的,如果阅读前文时不确定的话则可以查阅该小节。
文档还有一个小节A3.4.2专门是突发传输伪代码,用伪代码的方式帮助理解突发传输操作的行为。
数据读写结构#
-
写strobe
用WSTRB[n:0]表示,对于其中一个位,WSTRB[n]=1对应于WDATA[(8n)+7:(8n)]有效,即WSTRB一位对应WDATA一字节,当WVALID=0,WSTRB可以为任何值
-
窄传输(narrow transfers)
对于写操作,使用WSTRB作为mask,例如:
- burst有5个beats
- 起始地址为0
- 每个beat传输8bits
- 总线宽度32bits
- burst类型INCR
再看一个例子:
写入字节的起始地址不是byte line的起始地址,而是实际有效数据的起始地址,即高32位,地址0x4为起始地址。
-
字节不变性(byte invariance)
按照个人理解,这个特性是用于「同一个结构体但其中的字段是混合大小端」应当如何处理。当遇到多字节的字段,字节按照其endianess顺序存储,但是字节本身内的8位不会发生变化。同样地,还有16-bites invariance、32bits等。具体请参考文档,或者这个参考链接
-
非对齐传输(unaligned transfers)
比如地址0x1002传输4B,这个地址对于4B是非对齐的。AXI协议规定的做法是,传输仍然是对齐的,但数据可以是不对齐的,所谓传输对齐指的是AXI会给传输的数据填充无效字节,而数据不对齐指的是使用WSTRB标识无效字节(写操作)或者主机自行丢弃(读操作),从而有效数据确实是不对齐的。
例子1:
例子2:
例子3:这个例子同时触发了窄传输+非对齐传输,因此可以更加明确地看到,非对齐数据的填充是对于传输大小来说的,在这里填充的是0x04~0x06这三个字节,因此对于传输来说,起始地址是0x04,那么如何确定下一次传输的地址呢?由于是INCR类型,因此下一个地址为0x04+传输大小=0x08、0x0C、0x10....
读写响应结构#
之前说过,读响应信号在WC传输,写响应信号单独在BC传输,信号分别定义为
- RREST[1:0]
- BRESP[1:0]
信号含义如下:
- OKAY:成功/独占访问失败/独占访问一个不支持独占访问的从机
- EXOKAY:独占访问成功
- SLVERR:失败的事务,协议建议这个信号用于从机发生异常的情况,如FIFO溢出、企图写ROM等
- DECERR:访问从机失败,比如无效地址。既然访问从机失败,谁来返回这个错误呢?协议建议将请求重定向到一个默认从机,且该从机可以返回DECERR
事务中不管出现任何错误,已约定好的传输次数必须执行完毕
对于写事务,一个写响应信号对应于一个burst;对于读事务,一个读响应信号对应于一个transfer
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律