前几天帮一位同事分析了下write data在AXI write data channel上排布,想想还是记录一下,方便日后复习。我们先来看一张wdata排布图,灰色单元表示该Byte没有被传输。
第一次看这张图的时候,是否有感觉疑惑:
- address为0x07的data为什么要放在②的位置,而不是放在①的位置?
- 为什么第3笔传输(3rd transfer)的4B data要放在data bus的后半部分,而不是前半部分?
其实上述两个问题不难,大家只需要把AXI A3.4.1和A3.4.2章节的Pseudocode代码好好研读下就有答案了。我们先来讲几个前提变量:
- Start_Address:表示的是一笔transaction的起始地址,它等于AxADDR。
- Number_Bytes:表示1个transaction中每笔data transfer的最大byte数,它等于2 ^ AxSIZE。
- Data_Bus_Bytes:表示data bus的byte宽度,也就是在实现中定义好的物理最大宽度了,比如我说某个AXI master的data bus宽度是8Byte,这个8Byte就是Data_Bus_Bytes。
- Aligned_Address:它是Start_Address根据Number_Bytes做对齐之后的值,也就是Aligned_Address = (INT(Start_Address / Number_Bytes)) × Number_Bytes。
- Burst_Length:它表示在transaction中会burst传输多少笔data transfer,它等于Burst_Length = AxLEN + 1。
- Address_N:它表示在一次burst传输第几笔transfer的地址,比如N=1,那么表示burst传输中的第1笔transfer。对于第1笔transfer,Address_1等于Start_address。INCR burst之后的Address_N计算公式为:Address_N = Aligned_Address + (N – 1) × Number_Bytes。
- Wrap_Boundary:表示WRAP burst传输的最低address,它等于Wrap_Boundary = (INT(Start_Address / (Number_Bytes × Burst_Length)))× (Number_Bytes × Burst_Length)。
- Lower_Byte_Lane:表示1笔transfer最低address的Byte通道。
- Upper_Byte_Lane:表示1笔transfer最高address的Byte通道。
- INT(x):表示x的向下取整数值。
1. INCR的write data排布
有了以上几个概念之后,我们来分析下上述的data传输图,它图中可以看出它是起始地址为0x7,AxSize=0b10(4Byte),AxLen=b11(burst长度为4)的INCR burst传输,并且Data_Bus_Bytes为8Byte。因此我们可以先求解出:
- Start_Address=0x07,Number_Bytes=4Byte,Data_Bus_Bytes=8Byte,Aligned_Address=0x4,Burst_Length=0x4
- Address_1=0x07,Address_2=0x08,Address_3=0x0C,Address_4=0x10
Lower_Byte_Lane和Upper_Byte_Lane的计算公式为:
如果是第1笔transfer,那么:
- Lower_Byte_Lane = Start_Address – (INT(Start_Address / Data_Bus_Bytes)) × Data_Bus_Bytes
- Upper_Byte_Lane = Aligned_Address + (Number_Bytes – 1) – (INT(Start_Address / Data_Bus_Bytes)) × Data_Bus_Bytes
如果不是第1笔transfer,那么
- Lower_Byte_Lane = Address_N – (INT(Address_N / Data_Bus_Bytes)) × Data_Bus_Bytes
- Upper_Byte_Lane = Lower_Byte_Lane + Number_Bytes – 1
所以结合以上公式,我们可以算出4笔transfer的Upper_Byte_Lane和Upper_Byte_Lane为:
- 第1笔transfer:Upper_Byte_Lane = 7,Lower_Byte_Lane = 7;
- 第2笔transfer:Upper_Byte_Lane = 3,Lower_Byte_Lane = 0;
- 第3笔transfer:Upper_Byte_Lane = 7,Lower_Byte_Lane = 4;
- 第4笔transfer:Upper_Byte_Lane = 3,Lower_Byte_Lane = 0;
Upper_Byte_Lane和Lower_Byte_Lane的数值代表在data channel占据的第几字节,比如Lower_Byte_Lane=0,表示最低的0字节。因为每1笔data transfer的data只能在data channel的DATA((8 × Upper_Byte_Lane) + 7: (8 × Lower_Byte_Lane))之间传输,所以这也就解答了最开始的两个疑问了。
2. 扩展到WRAP burst
扩展到WRAP burst的话,其实也类似的,只是WRAP的Address_N计算起来和INCR有点不一样,它涉及到卷绕address回去。我们再以一张Wrap burst传输图为例顺便说下,灰色单元表示该Byte没有被传输。
从图中可以看出它是起始地址为0x4(Wrap必须是aligned的传输),AxSize=0b10(4Byte),AxLen=b11(burst长度为4)的Wrap burst传输,并且Data_Bus_Bytes为8Byte。因此我们可以先求解出:
- Start_Address=0x04,Number_Bytes=4Byte,Data_Bus_Bytes=8Byte,Aligned_Address=0x4,Burst_Length=0x4。
根据AXI spec,Wrap传输的Address_N计算公式定义为:如果WRAP传输刚开始,还没有到达边界,Address_N=Aligned_Address + (N – 1) × Number_Bytes。如果WRAP传输的Address_N等于Wrap_Boundary + (Number_Bytes × Burst_Length),那么当前transfer的Address_N会用Wrap_Boundary传输,之后transfer的Address_N为Start_Address + ((N – 1) × Number_Bytes) – (Number_Bytes × Burst_Length)。所以这个WRAP burst的Address_N为:
- Address_1=0x04,Address_2=0x08,Address_3=0x0C,Address_4=0x0
虽然Address_N的计算公式和INCR burst不一样,但是Upper_Byte_Lane和Upper_Byte_Lane的计算公式是一样的。我们可以算出4笔transfer的Upper_Byte_Lane和Upper_Byte_Lane为:
- 第1笔transfer:Upper_Byte_Lane = 7,Lower_Byte_Lane = 4;
- 第2笔transfer:Upper_Byte_Lane = 3,Lower_Byte_Lane = 0;
- 第3笔transfer:Upper_Byte_Lane = 7,Lower_Byte_Lane = 4;
- 第4笔transfer:Upper_Byte_Lane = 3,Lower_Byte_Lane = 0;
3. 结论
不管是WRAP传输,还是INCR传输,其实Upper_Byte_Lane和Lower_Byte_Lane的计算公式是一样的,我们在平时可以不用套用这么多公式去计算,太麻烦了。我们其实根据Data_Bus_Bytes,Number_Bytes和Start_Address就可以大致心算出write data在data bus上是如何排布的了。是这样的:
- 先用Data_Bus_Bytes去把address空间划分为很多子空间,每段子空间大小为Data_Bus_Bytes。
- Number_Bytes把address空间划分为很多更小的子空间,每段子空间大小为Number_Bytes。每段子空间的最大值称为Number_Bytes的最大边界,每段子空间的最小值称为Number_Bytes的最小边界。
- Start_Address%Data_Bus_Bytes的结果(余数)就是第1笔transfer的Lower_Byte_Lane,Upper_Byte_Lane的取值肯定在达到第一个Start_Address落在的Number_Bytes子空间的最大边界处。
- 之后的transfer就以此类推下,其实就是以Number_Bytes大小的窗口在address上平移。