1.AXI的几个概念
1.1 Transaction/Burst/Transfer/Beat
在手册的术语表中,与 AXI 传输相关的有三个概念,分别是 transfer(beat)、burst、transaction。用一句话串联就是:
在 AXI 传输事务(Transaction)中,数据以突发传输(Burst)的形式组织。一次突发传输中可以包含一至多个数据(Transfer)。每个 transfer 因为使用一个周期,又被称为一拍数据(Beat)。
所以可以这么理解:transaction就是一次数据burst的传输+对应的读/写命令通道交互过程。传输事务包含数据和命令的传输,burst指的是数据传输。
而一次burst传输通常包含一拍到多拍数据,每一拍称为transfer或beat
1.2 Byte lane与strobe
一个AXI的dataBus位宽肯定是Byte的整数倍,设为BusW Byte,其中每一个Byte对应叫做一个Byte lane。Byte lane常与wstrobe联系在一起,有多少byte lane就有多少bit的wstrobe。
1.3 bus位宽和transfer位宽(AxSize)
Bus位宽在1.2节已经提到,标记为BusW。
一个Beat(transfer)的位宽为dataW=DW Byte。dataW是由AxSize来确定的。关系如下:
DW可以小于BusW,当小于BusW时,就是narrow传输。详情参考1.5节。
1.4 起始地址对齐
- 起始地址与axi data width对齐。也就是要求addr_start是DW的整数倍【注意是DW,也就是transfer位宽,而不是BusW】
- 起始地址与burst width对齐。也就是burstW=DW×burstLen Byte
常见的自研DMA中如果出现第一种地址非对齐的传输往往建议master将地址addr_start与DW对齐,为什么这么做可以参考第4章内容。举个例子如下:
首先假设
addr_start=0x3
DW=BusW=4 B
transW=5B----实际需要读取数据量
在读数据时,AXI读的实际情况是
addr_start_align=0x0
burstLen=2
此时读回的是0-7地址的8byte数据,实际需要的是3-7地址的数据,所以其他数据被master丢掉
在写数据时,AXI写的实际情况是
addr_start_align=0x0
burstLen=2
第一拍wstrb=0'b1000,第二拍wstrb=0'b1111
这里就出现了strobe写。
对于第二种对齐并不是AXI总线本身的强制要求,但是一旦满足该种对齐,此时无论是wrapBurst还是INC burst,AXI的行为是一致的,下文会详细解释。
2.Burst Type介绍
AXI总线中,读写地址通道AR/AW的AxBURST[1:0]信号用于定义该transaction的burst type。
AxBURST[1:0] | Burst Type |
---|---|
2’b00 | FIXED |
2’b01 | INCR |
2’b10 | WRAP |
2’b11 | Reserved |
在这里需要突出说明的是Burst Type只和当前Burst有关,Burst之间不会互相影响。举个例子,对于wrap类型,前后两个trans如果都是wrap类型,那么每个trans都有addr_start,每个trans只在本trans的addr_low_bound和addr_up_bound之间wrap,和其他trans没有关系。INCR和FIXED也是一样的,每一个trans都有自己的addr_start,只是常用的INCR多个trans的addr_start是连续的,给人的感觉地址在两个trans之间incr,实际这种incr是master计算的和AXI总线本身没有关系。
下面一段摘自AXI总线的Burst Type以及地址计算 | WRAP到底是怎么一回事?_axi wrap-CSDN博客
这一段的总结很好,就直接搬过来【实际是AXI协议的翻译】
FIXED
- 同一个burst内每个transfer的地址保持一致。
- 同一个burst内的每一个beats的byte lanes数目保持一致,但可以通过WSTRB选择每个beat的哪些byteLane是有效bytes。
常用于对同一位置的重复访问,例如读或清空FIFO。为什么举例是FIFO而不是mem呢?因为虽然FIFO有多个存储单元,但挂在AXI上时只分配了一个地址,假设FIFO深度为Fifo_D,位宽和AXI的transfer的有效位宽一致,那么用一个Fifo_D长度的burst去读或写FIFO,就可以读完或写满该FIFO。当然如果挂在AXI上的mem也只分配一个地址,也可以支持FIXED操作。
INCR
- 同一个burst内地址随transfer递增。
- 地址递增量为一个transfer的大小。
- 常用于对normal sequential memory的访问。
WRAP
- start address需按照transfer的大小即DW进行对齐
- burst length只能从2,4,8,16中取值。
- 地址递增达到upper boundary时回卷到lower boundary
设burstW=DW×BurstLen,则lower_boundary=Floor(start_addr/burstW) × burstW;upper_boundary=Floor(start_addr/burstW) × burstW + burstW
显然如果start address是和burstW对齐,那么最大地址只会达到upper_boundary-1,不会发生wrap,此时的行为就和INCR一致。
Wrap通常用于从memory中读取cache line
因为master对cache的访问通常是cache line中的某些bytes,但当发生cache miss时,从memory读回来的是整个cache line。而此时master发送的地址却不一定是cache line的起始地址,而可能位于中间,因此递增到upper boundary时需要回卷到lower boundary,才能将该cache line读完。
3. narrow transfer & strobe & unaligned transfer
这一节之所以把narrow transfer和写strobe以及地址非对齐放在一起有两个原因:
- narrow transfer和unaligned transfer(地址非对齐)传输都会使用write strobe
- narrow transfer和unaligned transfer都需要考虑每个transfer的地址和用哪些byteLane来传输有效数据
在这里先说一个结论:
narrow transfer和非narrow的transfer都可以使用wstrb
unaligned transfer和aligned transfer也都可以使用wstrb
也就是说:
wstrb既不是narrow也不是unaligned的同义词
3.1 write strobe
WSTRB[n:0] 信号为高电平时,表明了哪些ByteLane上的写数据是有效的。写数据总线的每 8 位有 1 个wstrobe,因此 WSTRB[n] 对应WDATA[(8n)+7:(8n)]。
协议并没有规定wstrb信号是连续的,也就是说ByteLane上有效数据可以不连续。如下图所示:
但是实际系统中是否支持不连续的wstrb还要取决于Slave是否支持。
可以看出上面的wstrb只是告诉slave,哪些写byte是有效的,和具体的transfer类型无关。
上面的例子对于singleBurst和burstSize=4的incr trans是否都是支持的?上面的截图是从知乎截过来的,协议里面是否帧的支持?
3.2 narrow transfer
narrow transfer在协议中的定义就是DW < BusW。
【需要说明的是DW一定是BusW的1/(2^n),而不能是随便小于BusW的数。因为DW和BusW都是2的幂次】
根据定义,narrow transfer和write strobe是没有直接关系的。
当master发送narrow transfer时,地址和控制信息决定传输使用哪些字节通道:
- 在INCR和WRAP突发中,突发的每个transfer(beat)使用不同的byteLane
- 在FIXED突发中,每个transfer都使用相同的byteLane。
如下图是一个INCR的narrow传输实例,其中BusW=4B,DW=1B,burstLen=5,start_addr=0
下图给出了另一个INCR传输实例,其中start_addr=4,BusW=8B,DW=4B,burstLen=3.
由上图可以看出此trans虽然是对齐传输(start_addr域DW对齐),但是第一个transfer的有效byteLane却是从第4个开始[从0计数]。那么byteLane到底是怎么使用的呢?特别是当narrow和非对齐同时出现时是怎么的呢?在第5章会给出答案。
3.3 unaligned transfer
在这里介绍一下非对齐传输&INCR&non-narrow的trans,怎么计算有效byte lane的位置,其中Floor表示向下取整。
设一个trans的每一个transfer的地址为Addr_N,Addr_0=addr_start,Addr_align=Floor((addr_start/DW)*DW),则:
Addr_N=Addr_align + N×DW
则进一步得到:
low_byte_lane_0 = addr_start - Floor(addr_start/DW)*DW
up_byte_lane_0 =DW-1
low_byte_lane_N=0
up_byte_lane_N =DW-1
带入1.4节的数据
low_byte_lane_0=3-Floor(3/4)*4=3
up_byte_lane_0 =4-1=3
low_byte_lane_1=0
up_byte_lane_1 =4-1=3
和1.4节结果一致
这里采用非对齐地址在AXI上传输,和1.4节master将非对齐转为对齐地址传输的唯一差别就是非对齐传输的Axaddr[n:0] !=0 【具体到上面例子就是n=1】
4. 非对齐的axaddr是否可以直接传输
对于地址非对齐的访问,AXI Axaddr可以直接传输不对齐地址吗?
地址非对齐在读和写有什么不同的处理?写可以有strobe,但是读没有,全靠约定吗?
AXI协议规定 slave本身不需要为地址非对齐做任何不要的处理【当然也可以做特殊处理】,也就是说Axaddr的不对齐地址可以传输。
虽然地址非对齐,但是无论读数据还是写数据,都会按照对齐的格式来传输,只不过这些data transfer会有无效数据。
对于写:AXI要求按协议规定的ByteLane发数据之后,对有效数据的wstrb赋1,无效数据的wstrb赋0。此时如果master把地址对齐,利用wstrb也可以正确的写,这样还不需要slave来处理不对齐的地址
对于读:协议规定对齐和非对齐的ByteLane摆放是一样的,如果直接发非对齐的trans,到了slave端,还是要判断地址对齐的情况,而且数据返回后,由于没有strb,master要自己选择哪些数据要被丢弃。所以还不如master先把地址处理成对齐的,然后将多读的数据丢弃。
所以有两个结论:
- 如果axi传输了非对齐的地址,那么就需要slave来支持非对齐传输;如果slave不支持非对齐传输,那么就需要master来把起始地址对齐。当然slave和master可以同时都做处理
- 同样需求的非对齐传输和mst把地址对齐的传输,它们的唯一区别就是AXI上是否传输非对齐的Axaddr,其他的比如Axsize,AxLen,和有效byteLane都是一致的。
根据上面的描述 我建议能在master端把这些非对齐的trans处理掉最好。自研DMA基本都能在master处理掉,对于CPU来说可能是有些不好在master处理的地方。
5.地址与byteLane计算
5.1 地址与byteLane计算公式
先给出数据量定义,前文已经出现的保持一致的含义,这里在重申一次。
DW:每个transfer的数据位宽。
BusW:AXI的传输bus位宽
BurstLen:一次burst传输的transfer(beat)数,BurstLen=Axlen+1
BurstW:一次burst传输的数据总量,BurstW=DW×BurstLen
addr_start:一次burst传输的起始地址,addr_start=Axaddr
addr_align:addr_start对齐到DW的地址
addr_N:第N比transfer的地址,其中N从0开始计数【AXI spec中是从1开始,所以下面的公式和spec略有区别】
wrap_boundary(lower_boundary):wrap类型的burst中的最小地址,或者说地址下边界
up_byte_lane_N:第N笔【N从0开始】transfer中最大地址所对应的byteLane位置
low_byte_lane_N:第N笔【N从0开始】transfer中最小地址所对应的byteLane位置
floor(x):对x向下取整
则:
wrap_boundary=floor(addr_start/BurstW) × BurstW (也即对齐到BurstW的地址)
addr_align=floor(addr_start/DW)×DW (也即对齐到DW的地址)
addr_0=addr_start
对于INCR和还未发生wrapped的WRAP burst:
addr_N=addr_align + N×DW
对于WRAP,如果Addr_N=wrap_boundary + BurstW,则从该transfer开始进行地址wrap,设此时为第N0比transfer,此时地址发生wrap,也即此时:
addr_N=addr_N0=wrap_boundary
发生wrap之后接下来的transfer地址为:
addr_N=addr_start + N×DW - BurstW = wrap_broundary + (N-N0)×DW
low_byte_lane_0= addr_start - floor(addr_start/BusW)×BusW (也即对齐到BusW的地址)
up_byte_lane_0 = addr_align + DW - 1 - floor(addr_start/BusW)×BusW
low_byte_lane_N= addr_N - floor(addr_N/BusW)×BusW (N > 0)
up_byte_lane_N = low_byte_lane_N + DW - 1
注意up_byte_lane_N和up_byte_lane_0的差别。
那么根据上面的公式,我们得出以下结论:
- byteLane计算中的对齐是对齐到BusW(AXI的数据位宽)
- Addr_N的对齐是对齐到DW(实际的数据位宽)
- wrap_boundary的对齐是对齐到BurstW(实际传输数据量)
5.2 地址计算实例
需要补充narrow和地址非对齐+wrap的情况来一个实例说明
对于FIXED和INCR类型的Burst,其地址计算就不在这里展开,比较简单。本节只介绍Wrap Burst的地址计算。
addr_low_bound=Floor(addr_start/BurstW)*BurstW
addr_up_bound = addr_low_bound + BurstW
可以看到虽然有wrap,但是BurstW是不变的。另外addr_low_bound就是trans的burstW向下对齐的地址,所以如果addr_start=addr_low_bound,该trans的最后一个beat地址肯定是addr_low_bound+BurstW-1,所以永远达不到addr_up_bound,就不存在wrap,此trans的处理过程和INCR完全一致。下面举个例子来说明:
wrap trans只支持起始地址DW对齐
addr_start=0x4,AxLEN = 3, AxSIZE = 2, AxBURST = 3
DW=4
transW=DW×(AxLEN+1)=16
则
addr_low_bound=Floor(0x4/16)*16=0
addr_up_bound=0+transW=16
所以4个beat的地址分别为:
beat0:0x4
beat1:0x8
beat2:0xc
beat3:0x0(0x10到达上界,所以wrap到0)
6.疑问
下面这种busW=DW=32bit的single burst传输wtrb为4'b0101是否满足axi协议?
地址 | 3 | 2 | 1 | 0 |
wtrb | 0 | 1 | 0 | 1 |
D[31:24] | D[23:16] | D[15:8] | D[7:0] |
上面这一点和3.1节的write strobe给出的例子相似,就是说在既没有非对齐,又没有narrow传输的情况下,wtrob非连续的使用是否是允许的。
wtrb | 0 | 0 | 1 | 1 |
beat0 | D[31:24] | D[23:16] | D[15:8] | D[7:0] |
beat1 | D[31:24] | D[23:16] | D[15:8] | D[7:0] |
上面的trans,burstSize=2,要求第一个beat的[15:0]bit更新到地址1和0,第二个beat的[15:0]更新到地址5和4,其他bit位不更新。这个要求是否符合axi协议的wstrob的要求?