0.前言
本人自学AXI总线做的一些记录,会根据以后的学习不断补充完善
1.简介
AXI(Advanced eXtensible Interface)是一种总线协议,该协议是ARM 公司提出的 AMBA(Advanced Microcontroller Bus Architecture)3.0 协议中最重要的部分,是一种面向高性能、高带宽、低延迟的片内总线。它的地址/控制和数据相位是分离的,支持不对齐的数据传输,同时在突发传输中,只需要首地址,同时分离的读写数据通道、并支持显著传输访问和乱序访问,并更加容易就行时序收敛。AXI 是 AMBA 中一个新的高性能协议。AXI 技术丰富了现有的 AMBA 标准内容,满足超高性能和复杂的片上系统(SoC)设计的需求。
特点
- 单向通道体系结构。信息流只以单方向传输,简化时钟域间的桥接,减少门数量。当信号经过复杂的片上系统时,减少延时。
- 支持多项数据交换。通过并行执行猝发操作,极大地提高了数据吞吐能力,可在更短的时间内完成任务,在满足高性能要求的同时,又减少了功耗。
- 独立的地址和数据通道。地址和数据通道分开,能对每一个通道进行单独优化,可以根据需要控制时序通道,将时钟频率提到最高,并将延时降到最低。
2.通道结构
AXI 总线共有 5 个通道分别是
- read address channel(读地址通道)
- write address channel(写地址通道)
- read data channel(读数据通道)
- write data channel(写数据通道)
- write response channel(写应答通道)
每一个 AXI 传输通道都是单方向的。地址通道(address channel)传输地址和控制信息,用来描述被传输数据的性质。
这 5 条独立的通道都包含一个信息信号和一个双路的 VALD、READY 握手机制。VALID 和 READY 同时为高时有效。信息源用 VALID 信号来指示通道中的数据或控制信息什么时候有效。目地源用 READY 信号来表示何时能够接收数据。读数据和写数据通道都包括一个LAST 信号,用来指明一个事物传输的最后一个数据。
写数据通路传送主机向从机写入的数据。每八个数据都会有一个 byte lane ,用来指明数据总线上面的哪些 byte 有效。写响应通道提供了从机响应写任务的一种方式。这响应信号每一次突发式读写会产生一个。
AXI 协议支持乱序传输。首先分配给每个通过接口的任务一个 IDtag,要求相同 ID tag 的任务必须有序完成,而不同 ID tag 可以乱序完成。
读数据时通道结构如下,主机通过读地址通道发送地址和控制信息,从机通过读数据通道返回数据信息
写数据时通道结构如下,主机通过写地址通道发送地址和控制信息同时通过写数据通道发送数据信息,从机通过写响应通道返回一个响应信号表示任务完成
3.突发式读写时序
这里先对读写时序有个大概的了解,后面会具体介绍
突发式读数据的时序如下,当地址出现在地址总线后,传输的数据将出现在读数据通道上。从机保持 VALID为低直到读数据有效。为了表明一次突发式读写的完成,从机用 RLAST 信号来表示最后一个被传输的数据。(主机还会驱动一路控制信号用来显示突发长度和类型的信息,下列时序图中并未标出)
连续式突发读数据时序如下,从机会在第一次突发式读完成后处理第二次突发式读数据。也就意味着,主机一开始传送了两个地址给设备。从机在完全处理完第一个地址的数据之后才开始处理第二个地址的数据。
突发式写数据的时序如下,主机发送地址和控制信息到写地址通道中,然后主机发送每一个写数据到写数据通道中。当主机发送最后一个数据时,WLAST 信号就变为高。当从机接收完所有数据之后将一个写响应发送回主机来表明写任务完成。
4.信号描述
全局信号
信号 | 源 | 描述 |
ACLK | Clock source | 全局时钟信号 |
ARESETn | Reset source | 全局复位信号,低电平有效 |
写地址通道信号
信号 | 源 | 描述 |
AWID[3:0] | 主机 | 写地址 ID,这个信号是写地址信号组的 ID tag |
AWADDR[31:0] | 主机 | 写地址 |
AWLEN[3:0] | 主机 | 突发式写长度,决定突发式写传输的数据个数 |
AWSIZE[2:0] | 主机 | 突发式写的大小 |
AWBURST[1:0] | 主机 | 突发式写的类型 |
AWLOCK[1:0] | 主机 | 锁类型 |
AWCACHE[3:0] | 主机 | cache类型,指明任务的bufferable、cacheable、write-through、write-back、allocate attributes 信息 |
AWPROT[2:0] | 主机 | 保护类型 |
AWVALID | 主机 | 写地址有效 1 = 地址和控制信息有效 0 = 地址和控制信息无效 这个信号会一直保持,直到AWREADY变高 |
AWREADY | 从机 | 写地址准备好。这个信号用来指明从机已经准备好接受地址和控制信息了。 1 = 设备准备好 0 = 设备没准备好 |
写数据通道信号
信号 | 源 | 描述 |
WID[3:0] | 主机 | 写 ID tag,WID 的值必须与 AWID 的值匹配 |
WDATA[31:0] | 主机 | 写的数据 |
WSTRB[3:0] | 主机 | 写阀门。WSTRB[n]标示的区间为 WDATA[(8*n)+7 : (8*n)] |
WLAST | 主机 | 写的最后一个数据 |
WVALID | 主机 | 写有效 1 = 写数据和阀门有效 0 = 写数据和阀门无效 |
WREADY | 从机 | 写就绪。指明从机已经准备好接受数据了 1 = 从机就绪 0 = 从机未就绪 |
写响应通道信号
信号 | 源 | 描述 |
BID[3:0] | 从机 | 响应 ID , 这个数值必须与 AWID 的数值匹配 |
BRESP[1:0] | 从机 | 写响应。这个信号指明写任务的状态。可能有的响应:OKAY、EXOKAY、SLVERR、DECERR |
BVALID | 从机 | 写响应有效。 1 = 写响应有效 0 = 写响应无效 |
BREADY | 主机 | 接受响应就绪。该信号表示主机已经能够接受响应信息。 1 = 主机就绪 0 = 主机未就绪 |
读地址通道信号
信号 | 源 | 描述 |
ARID[3:0] | 主机 | 读地址 ID,这个信号是读地址信号组的 ID tag |
ARADDR[31:0] | 主机 | 读地址 |
ARLEN[3:0] | 主机 | 突发式读长度,决定突发式读传输的数据个数 |
ARSIZE[2:0] | 主机 | 突发式读大小 |
ARBURST[1:0] | 主机 | 突发式读的类型 |
ARLOCK[1:0] | 主机 | 锁类型 |
ARCACHE[3:0] | 主机 | cache类型 |
ARPROT[2:0] | 主机 | 保护类型 |
ARVALID | 主机 | 读地址有效 1 = 地址和控制信息有效 0 = 地址和控制信息无效 这个信号会一直保持,直到ARREADY变高 |
ARREADY | 从机 | 读地址准备好。这个信号表示已经准备好接受数据了。 1 = 设备准备好 0 = 设备没准备好 |
读数据通道信号
信号 | 源 | 描述 |
RID[3:0] | 从机 | 读 ID tag,RID 的值必须与 ARID 的值匹配 |
RDATA[31:0] | 从机 | 读的数据 |
RRESP[3:0] | 从机 | 读响应。这个信号指明读传输的状态:OKAY、EXOKAY、SLVERR、DECERR。 |
RLAST | 从机 | 读的最后一个数据标志位 |
RVALID | 从机 | 读数据有效 1 = 读数据有效 0 = 读数据无效 |
RREADY | 主机 | 读数据就绪 1 = 主机就绪 0 = 主机未就绪 |
低功耗接口信号
信号 | 源 | 描述 |
CSYSREQ | CLOCK controller | 系统低功耗请求。此信号来自系统时钟控制器,使外围从机进入低功耗状态 |
CSYSACK | 外围从机 | 低功耗请求应答 |
CACTIVE | 外围从机 | Clock active 1 = 外围设备时钟请求 0 = 外围设备时钟无请求 |
5.握手机制
全部 5 个通道使用相同的 VALID/READY 握手机制传输数据及控制信息。传输源产生 VLAID 信号来指明何时数据或控制信息有效。而目地源产生 READY信号来指明已经准备好接受数据或控制信息。传输发生在 VALID 和 READY 信号同时为高的时候。VALID 和 READY 信号的出现有三种关系。
(1) VALID 先变高 READY 后变高。时序图如下
在箭头处信息传输发生。
(2) READY 先变高 VALID 后变高。时序图如下
在箭头处信息传输发生。
(3) VALID 和 READY 信号同时变高。时序图如下
此时信息传输立马发生,在箭头处信息传输发生。
握手信号间存在的依赖关系
读数据时,从机可以在 ARVALID 出现的时候在给出 ARREADY 信号,也可以先给出ARREADY 信号,再等待 ARVALID 信号。但是设备必须等待 ARVALID 和 ARREADY 信号都有效才能给出 RVALID信号,开始数据传输。
写数据时,主机必须在从机给出 AWREADY 或 WREADY 信号前给出 AWVALID 或 WVLAID信号。从机可以等待AWVALID或WVALID信号有效或者两个都有效之后再给出 AWREADY 信号。从机可以等待AWVALID或WVALID信号有效或者两个信号都有效之后再给出 WREADY 信号。
通道间的关系
地址、读、写和写响应通道之间的关系是灵活的。例如,写数据可以出现在接口上早于与其相关联的写地址。也有可能写数据与写地址在一个周期中出现。
但是必须遵循以下关系:
(1)读数据必须总是跟在与其数据相关联的地址之后。(写数据可以先决定写的数据再决定写在哪里,读数据必须先知道读哪里的数据,然后才能得到数据)
(2)写响应必须总是跟在与其相关联的写任务的最后出现。
6.突发读写详解
突发式读写的地址必须以 4KB 对齐,即突发读写不能超过4KB长度,以防止跨越从机的边界信号 AWLEN 或信号 ARLEN 指定每一次突发式读写所传输的数据的个数
ARLEN[3:0] AWLEN[3:0] | b0000 | b0001 | b0010 | ... | b1110 | b1111 |
number of data transfers | 1 | 2 | 3 | ... | 15 | 16 |
ARSIZE 信号或 AWSIZE 信号指定每一个时钟节拍所传输的数据的最大位数,不能超过数据总线的宽度
ARSIZE[2:0] AWSIZE[2:0] | b000 | b001 | b010 | b011 | b100 | b101 | b110 | b111 |
bytes in transfers | 1 | 2 | 4 | 8 | 16 | 32 | 64 | 128 |
AXI 协议定义了三种突发式读写的类型:固定式的突发读写、增值式突发读写、包装式突发读写。用信号 ARBURST 或 AWBURST 来选择突发式读写的类型。
- 固定式突发读写是指地址是固定的,每一次传输的地址都不变。这样的突发式读写是重复的对一个相同的位置进行存取。例如 FIFO。
- 增值式突发读写是指每一次读写的地址都比上一次的地址增加一个固定的值。
- 包装式突发读写跟增值式突发读写类似。包装式突发读写有两个限制:1 起始地址必须以传输的 size 对齐。2 突发式读写的长度必须是 2、4、8 或者 16。
ARBURST[1:0] AWBURST[1:0] | 突发类型 | 描述 | 适用的存储类型 |
b00 | FIXED(固定式) | 固定地址的突发读写 | FIFO类型 |
b01 | INCR(增量式) | 地址自增的突发读写 | 通常的内存 |
b10 | WRAP(包装式) | 地址自增的突发读写,封装到较低地址的边界处 | 缓存 |
b11 | RESERVED(保留) |
关于一些地址的计算
Start_Address 主机发送的起始地址
Number_Bytes 每一次数据传输所能传输的数据 byte 的最大数量
Data_Bus_Bytes 数据总线上面 byte lanes 的数量
Aligned_Address 对齐版本的起始地址
Burst_Length 一次突发式读写所传输的数据的个数
Address_N 每一次突发式读写所传输的地址数量,范围是 2-16
Wrap_Boundary 包装式突发读写的最低地址
Lower_Byte_Lane 传输的最低地址的 byte lane
Upper_Byte_Lane 传输的最高地址的 byte lane
INT(x) 对 x 进行向下取整
公式
Start_Address = ADDR
Number_Bytes = 2^SIZE
Burst_Length = LEN + 1
Aligned_Address = (INT(Start_Address / Number_Bytes) ) x Number_Bytes
Address_1 = Start_Address
Address_N = Aligned_Address + (N – 1) x Number_Bytes
Wrap_Boundary = (INT(Start_Address / (Number_Bytes x Burst_Length)))x (Number_Bytes x Burst_Length)
如果有 Address_N = Wrap_Boundary + (Number_Bytes x Burst_Length),则后面的公式成立 Address_N = Wrap_Boundary。
第一次突发式读写:
Lower_Byte_Lane = Start_Address - (INT(Start_Address / Data_Bus_Bytes))x Data_Bus_Bytes
Upper_Byte_Lane = Aligned_Address + (Number_Bytes - 1) -(INT(Start_Address / Data_Bus_Bytes)) x Data_Bus_Bytes
除了第一次读写之后的读写:
Lower_Byte_Lane = Address_N – (INT(Address_N / Data_Bus_Bytes))x Data_Bus_Bytes
Upper_Byte_Lane = Lower_Byte_Lane + Number_Bytes – 1
DATA[(8 x Upper_Byte_Lane) + 7 : (8 x Lower_Byte_Lane)]