AXI burst地址计算
突发传输有3种类型:FIXED,INCR,WRAP
FIXED每次传输的地址固定为master指定的地址,所以不需要更新地址
INCR传输的起始地址是master指定的AxADDR,起始地址之后的传输地址需要和每次传输的最大字节数对齐,这个最大字节数记为number_bytes,计算方法是number_bytes=2 ^ AxSIZE,例如AxSIZE=2代表每次最多传输4个字节。INCR传输的起始地址是可以不对齐的,例如在AxSIZE=2时,起始地址可以指定为0x3,但是之后的地址需要和number_bytes对齐,也就是起始地址之后的地址依次为0x4,0x8,计算的方法为
align_addr = (INT(start_addr/number_bytes))*number_bytes;
addr_1 = start_addr = AxADDR;
addr_N = align_addr + (N-1)*number_bytes;//N>1
align_addr是起始地址对number_bytes对齐后的地址,例如上面的例子中align_addr=(INT(0x3/0x4))*0x4=0x0,地址按上述规则递增,一共传输AxLEN+1次,这就是INCR传输的过程
WRAP也类似与INCR传输,只不过WRAP传输的范围被限制在一个窗口中,当传输的地址到达窗口的上边界时就要卷绕的窗口的下边界。INCR要求除起始地址外的传输的地址都要和number_bytes对齐,WRAP要求包括起始地址在内的传输地址都要和number_bytes对齐,整个WRAP传输的窗口还要和本次传输的总字节数对齐。以AxSIZE=2,AxLEN=3为例,每次传输4字节,一共传输4次,也就是本次WRAP传输一共会传输16个字节,那么WRAP传输的窗口就是16字节对齐的,也就是第一个窗口的地址范围是0x0-0xf,第二个窗口的范围是0x10-0x1f,虽然起始地址有对齐要求,但是起始地址不一定要在窗口的下界,例如上面的例子中可以将起始地址指定为0x8,这样本次WRAP传输的窗口就是0x0-0xf,第一次传输的地址同样是master指定的地址
addr_1 = start_addr = AxADDR
计算后续地址之前先计算窗口的范围,下边界wrap_boundary就是起始地址和传输总长度对齐,上边界wrap_max就是下边界加起始地址
wrap_boundary = (int(start_addr/(number_bytes*burst_len))) * (number_bytes*burst_len);
wrap_max = wrap_boundary + (number_bytes*burst_len);
在到达上边界之前,WRAP传输地址生成方式和INCR模式一样,当到达边界之后,即addr_N = wrap_max时,本次传输的地址改为wrap_boundary,后续的地址为
addr_N = start_addr + ((N-1)*number_bytes) - (number_bytes*burst_len);
相当于到达上边界之后就回到wrap_boundary重新开始递增。一次WRAP传输会覆盖一个窗口,窗口大小为number_bytes*burst_len且该窗口起始位置和这个大小是对齐的

到现在为止解决的都是计算地址的问题,还需要解决每次传输要占用axi的哪个通道的问题,还是从对齐的角度来理解就可以,当确定了axi的带宽后,每个地址的数据走哪个通道就已经固定了,现以INCR为例,让起始地址是非对齐的

先计算第一次传输的通道使用情况,其实就是和通道宽度对齐
low_lane = start_addr - (int(start_addr/bus_width)) * bus_width
high_lane = align_addr + (number_bytes-1) - (int(start_addr/bus_width)) * bus_width;
后续的其实也是一样的
low_lane = addr_N - (int(addr_n/bus_width)) * bus_width;
high_lane = low_lane + number_bytes - 1;

浙公网安备 33010602011771号