3、AXI互连结构:拓扑结构、地址映射与路由机制

大家好,我是老李。今天咱们聊聊AXI Interconnect,这个在SoC设计里绕不开的“交通枢纽”。

说实话,我刚入行那会儿,觉得AXI总线就是一堆信号线,连上就完事了。直到有一次,我负责一个多主多从的系统,CPU、DMA、GPU三个主设备抢着访问DDR和SRAM,结果系统跑起来各种超时、死锁。嗯,从那以后我才真正开始研究Interconnect的内部机制。

说白了,AXI Interconnect就是一个智能路由器。它负责把多个Master的请求,正确地转发到对应的Slave,同时保证数据不乱、不丢、不冲突。

3.1 拓扑结构:你选哪种“路网”?

拓扑结构,就是Interconnect内部怎么连线。我见过不少新手一上来就选“全连接”,结果资源消耗大得吓人。其实,选哪种结构,完全取决于你的应用场景。

3.1.1 共享总线(Shared Bus)

这是最古老、最简单的结构。所有Master和Slave挂在同一条总线上,谁用谁申请。

  • 优点:面积小,实现简单。
  • 缺点:带宽有限,一次只能一个Master访问总线。多个Master同时请求时,得排队。

我在一个低功耗IoT芯片里用过这种结构。主设备就一个CPU和一个简单的DMA,从设备也就Flash和少量SRAM。共享总线完全够用,而且省面积。

3.1.2 交叉开关(Crossbar)

这是目前最常用的结构。它像一个矩阵,每个Master都可以通过独立的通道访问任意一个Slave。

  • 优点:支持多个Master同时访问不同的Slave,带宽高。
  • 缺点:面积大,布线复杂。Master数量多了,面积会爆炸。

我建议,如果你的系统有3个以上的Master,或者对带宽要求高,Crossbar是首选。比如我做过的一个AI加速器,有4个DMA引擎同时搬运数据,Crossbar才能撑住。

3.1.3 多层AXI(Multi-Layer AXI)

这是ARM公司提出的一种改进结构。它把总线分成多个层,每个层可以独立工作。

  • 优点:兼顾了共享总线的面积优势和Crossbar的带宽优势。
  • 缺点:设计复杂度高,需要仔细规划层与层之间的交互。

我个人习惯,在中等规模的SoC里用多层AXI。比如一个带GPU、VPU、DSP的系统,我会把高带宽的Master(GPU、VPU)放在一层,低带宽的Master(DSP、CPU)放在另一层,这样既隔离了带宽,又避免了Crossbar的庞大面积。

3.1.4 网络片上网(NoC)

这个比较新,适合超大规模系统(比如16个Master以上)。它用路由器和链路组成网络,数据包在节点间传输。

  • 优点:可扩展性极强,带宽高。
  • 缺点:延迟大,设计复杂,工具链支持不成熟。

嗯,这个我目前只在和高端服务器芯片里见过,咱们做嵌入式SoC的,暂时还用不上。

核心建议:

  • Master ≤ 2个:用共享总线
  • Master 3~8个:用Crossbar或多层AXI
  • Master > 8个:考虑NoC

3.2 地址映射:给每个Slave发“身份证”

地址映射,说白了就是给每个Slave分配一段地址空间。Master发一个地址,Interconnect就知道该去找谁。

我记得有一次,一个同事把两个Slave的地址范围设重叠了,结果数据写进去就丢了,查了三天才找到原因。所以,地址映射一定要仔细。

3.2.1 地址解码原理

Interconnect内部有一个地址解码器。它根据Master发来的地址,判断属于哪个Slave的地址范围。

// 伪代码示例:地址解码逻辑
if (addr >= 0x0000_0000 && addr <= 0x0FFF_FFFF) {
    slave = SRAM;
} else if (addr >= 0x1000_0000 && addr <= 0x1FFF_FFFF) {
    slave = DDR;
} else if (addr >= 0x2000_0000 && addr <= 0x2FFF_FFFF) {
    slave = UART;
} else {
    slave = DEFAULT; // 未映射区域,返回错误
}

3.2.2 地址对齐与粒度

地址映射时,要注意对齐。通常,每个Slave的基地址必须是其地址空间大小的整数倍。

  • 粒度:最小映射单位。比如4KB、64KB、1MB。粒度越小,地址空间利用率越高,但解码逻辑越复杂。
  • 对齐:基地址必须能被粒度整除。比如粒度是4KB,基地址必须是0x1000、0x2000这样的。

避坑指南:我曾经在项目里把DDR的地址范围设成了0x8000_0000 ~ 0x8FFF_FFFF,但基地址0x8000_0000没有对齐到256MB边界。结果综合工具报了一堆地址解码错误。后来我改成0x8000_0000 ~ 0x8FFF_FFFF,基地址对齐到256MB,问题就解决了。

3.2.3 默认从设备(Default Slave)

每个Interconnect都应该有一个默认从设备。当Master访问的地址不在任何Slave的映射范围内时,请求会被路由到默认从设备。

默认从设备通常返回一个错误响应(SLVERR或DECERR)。这样,软件就能知道访问了非法地址。

3.3 路由机制:数据包怎么走?

路由机制,就是Interconnect内部怎么把请求从Master送到Slave,再把响应送回来。

3.3.1 基于地址的路由

这是最基础的路由方式。Interconnect根据地址解码结果,把请求转发到对应的Slave端口。

  • 读事务:Master发读地址 → Interconnect解码 → 转发给Slave → Slave返回读数据 → Interconnect转发给Master。
  • 写事务:Master发写地址和写数据 → Interconnect解码 → 转发给Slave → Slave返回写响应 → Interconnect转发给Master。

3.3.2 事务ID与乱序传输

AXI支持乱序传输。Master可以发多个事务,每个事务带一个ID。Interconnect根据ID来区分不同的事务,并保证同一个ID的事务按顺序返回。

你想想看,如果Master发了两个读请求,一个去DDR(延迟大),一个去SRAM(延迟小)。如果Interconnect不处理ID,SRAM的数据先回来,Master就乱套了。

所以,Interconnect内部会维护一个ID映射表。它把Master的ID转换成内部ID,等Slave返回数据时,再根据内部ID还原成Master的ID。

3.3.3 仲裁机制

当多个Master同时访问同一个Slave时,Interconnect需要仲裁,决定谁先访问。

常见的仲裁算法有:

  • 固定优先级:优先级高的Master永远先访问。简单,但可能导致低优先级Master饿死。
  • 轮询(Round Robin):每个Master轮流访问。公平,但延迟不确定。
  • 加权轮询:给高带宽Master更多机会。我常用这个,比如给GPU分配3个时间片,给CPU分配1个。

注意:仲裁只发生在多个Master同时请求同一个Slave时。如果它们请求不同的Slave,Interconnect可以并行处理,不需要仲裁。

3.4 实战:一个简单的AXI Interconnect设计

下面我画一个简单的AXI Interconnect结构图,帮助大家理解。

AXI Interconnect 结构示意图 Master 1 (CPU) Master 2 (DMA) Master 3 (GPU) AXI Interconnect 地址解码器 路由逻辑 仲裁器 ID管理器 默认从设备 Slave 1 (SRAM) 0x0000_0000 ~ 0x0FFF_FFFF Slave 2 (DDR) 0x1000_0000 ~ 0x1FFF_FFFF Slave 3 (UART) 0x2000_0000 ~ 0x2FFF_FFFF 图例: Master(主设备) Interconnect(互连) Slave(从设备) 请求路径 响应路径

从图上可以看到,三个Master通过Interconnect连接到三个Slave。Interconnect内部有地址解码器、路由逻辑、仲裁器和ID管理器。当Master 1访问0x1000_0000时,Interconnect解码后知道是Slave 2(DDR),就把请求转发过去。如果此时Master 2也访问DDR,仲裁器就会决定谁先谁后。

3.5 总结与避坑

好了,这一章的内容就这些。我最后再唠叨几句:

  • 拓扑结构:别盲目选Crossbar,根据Master数量来定。
  • 地址映射:一定要对齐,别重叠。我建议用脚本自动生成地址映射表,避免手写错误。
  • 路由机制:注意ID管理,乱序传输虽然能提高性能,但处理不好会出大问题。
  • 仲裁:别让低优先级Master饿死。我曾经在一个项目里,DMA一直抢不到总线,导致视频数据丢帧。后来改成加权轮询,问题就解决了。

下一章,我们会深入AXI的握手协议和时序。到时候再聊!

可可精品资料库