架构蓝图:SoC顶层架构设计,总线与互联(AMBA/AXI/CHI)

好,咱们今天聊聊SoC的骨架——顶层架构和总线互联。说白了,就是决定各个IP核怎么“说话”、怎么“串门”。

我刚开始做SoC的时候,总觉得把功能模块拼起来就行了。结果呢?第一次流片回来,CPU读DDR的数据,延迟大得离谱,整个系统跑起来像老牛拉车。后来才明白,架构设计没做好,后面流片就是烧钱

一、SoC顶层架构的“三要素”

我个人习惯,拿到一个SoC需求,先画三个圈:

  • 计算域:CPU、GPU、NPU、DSP,负责“干活”
  • 存储域:DDR控制器、SRAM、Cache,负责“存东西”
  • 互联域:总线、NoC、桥接器,负责“传话”

这三个域怎么摆,直接决定了芯片的性能上限。你想想看,如果CPU和DDR之间隔了七八个桥接器,延迟能低吗?

核心原则:高带宽、低延迟的路径,必须直连。别绕弯子。

二、AMBA总线家族:从APB到CHI

ARM的AMBA协议,几乎是行业标准。我这些年做过的项目,从低功耗IoT到高性能计算,全离不开它。

协议 典型用途 带宽 复杂度
APB 低速外设(UART、GPIO、I2C) 极简
AHB 中速模块(内部SRAM、DMA) 中等
AXI 高性能主设备(CPU、GPU、DDRC) 较高
CHI 多核一致性互联(服务器、AI芯片) 极高 极高

嗯,这里要注意:别在APB上挂高速设备。我曾经见过一个项目,把USB控制器挂在了APB上,结果USB传输时CPU占用率飙升到90%。为什么?APB不支持burst传输,每传一个字都要握手一次,效率极低。

三、AXI协议:高性能互联的基石

AXI是我用得最多的协议。它有几个关键特性,我简单说说:

  • 独立地址/数据通道:读写可以并行,不像AHB那样串行
  • outstanding传输:可以连续发多个请求,不用等每个都完成
  • 乱序完成:后面的请求可以先返回,只要ID匹配就行

举个例子,CPU要读DDR里的数据。如果用AHB,发一个读请求,等数据回来,再发下一个。用AXI呢?可以一口气发8个读请求,DDR控制器按最优顺序返回数据。这性能差距,你想想看。

实战技巧:AXI的ID位宽别省。ID位宽决定了outstanding深度。我一般给CPU留4位ID,支持16笔outstanding。给DMA留3位,8笔就够了。

四、CHI协议:多核一致性的“终极方案”

CHI是ARM最新的互联协议,专门解决多核Cache一致性。说白了,就是多个CPU核同时读写同一块内存,怎么保证数据不错乱。

我记得做一颗16核服务器芯片时,用了CHI协议。刚开始觉得不就是个总线嘛,能有多复杂?结果光CHI的snop(监听)机制就研究了两个月。

CHI的核心思想是“去中心化”。每个节点(CPU、DDRC)都是对等的,通过一个叫“Home Node”的模块来协调。数据请求不再需要经过中央总线仲裁,而是直接点对点通信。

// CHI协议中一个典型的读请求流程
1. Requester (CPU0) 发送 ReadOnce 请求到 Home Node
2. Home Node 检查 snoop filter,发现数据在 CPU1 的 Cache 中
3. Home Node 发送 Snop 请求到 CPU1
4. CPU1 返回数据,并标记 Cache Line 为无效
5. Home Node 将数据转发给 CPU0
6. CPU0 收到数据,完成读操作

这个流程看起来简单,但实际硬件实现极其复杂。尤其是snoop filter的设计,既要快又要准。我踩过一个坑:snoop filter的entry数量设少了,导致频繁的snoop miss,性能直接腰斩。

避坑指南:CHI协议对延迟极其敏感。我曾经因为把Home Node和DDRC放在芯片的两端,导致跨die延迟增加了30ns,整个系统的性能下降了15%。后来不得不重新布局,把Home Node放在DDRC旁边。

五、总线互联的“黄金法则”

做了这么多年SoC,我总结了几条总线互联的法则:

  1. 带宽匹配:主设备的总带宽不能超过互联总带宽。比如CPU峰值带宽是128GB/s,那互联至少得支持128GB/s。
  2. 延迟预算:每个路径的延迟要提前算好。我一般给CPU到DDR的延迟预算在50ns以内,超过这个数,性能就会明显下降。
  3. QoS分级:实时性要求高的设备(如显示控制器),要设高优先级。批量传输的设备(如DMA),设低优先级。
  4. 死锁预防:AXI协议本身不会死锁,但多个桥接器串联时,可能因为buffer满导致死锁。解决办法是保证每个路径都有足够的buffer深度。

嗯,说到死锁,我想起一个项目。当时用了三层AXI互联,结果在压力测试时,系统偶尔会卡死。查了三天,发现是某个桥接器的写buffer满了,导致读请求被阻塞,而读请求又占着另一个buffer不放。典型的死锁场景。后来加了一个独立的读通道,问题解决。

六、实战:一个典型的SoC互联架构

我画一个典型的SoC互联架构,你感受一下:

+----------------+     +----------------+     +----------------+
|   CPU Cluster  |     |   GPU          |     |   NPU          |
|   (4核, L3$)   |     |   (16核)       |     |   (8核)        |
+-------+--------+     +-------+--------+     +-------+--------+
        |                      |                      |
        +----------------------+----------------------+
                               |
                    +----------+----------+
                    |   CHI Interconnect  |
                    |   (Home Node)       |
                    +----------+----------+
                               |
          +--------------------+--------------------+
          |                    |                    |
+---------+--------+  +-------+--------+  +--------+-------+
|   DDRC (通道0)   |  |  DDRC (通道1)  |  |   PCIe RC      |
|   (32GB/s)       |  |  (32GB/s)      |  |   (16GT/s)     |
+------------------+  +----------------+  +----------------+
                               |
                    +----------+----------+
                    |   AXI Interconnect  |
                    |   (低延迟桥接)      |
                    +----------+----------+
                               |
          +--------------------+--------------------+
          |                    |                    |
+---------+--------+  +-------+--------+  +--------+-------+
|   USB 3.0        |  |   Ethernet     |  |   UART/GPIO    |
|   (通过AHB桥接)  |  |   (通过AHB桥接) |  |   (APB总线)    |
+------------------+  +----------------+  +----------------+

这个架构里,CPU、GPU、NPU通过CHI互联,直接访问DDRC。PCIe也挂在CHI上,因为它的带宽高。低速外设呢?通过AXI转AHB、再转APB的桥接器挂上去。这样既保证了高性能路径的延迟,又降低了低速模块的复杂度。

个人建议:设计互联架构时,先画数据流图。把每个主设备到每个从设备的路径画出来,标上带宽和延迟要求。然后看哪些路径可以共享,哪些必须独立。这一步做好了,后面布线、验证都会轻松很多。

七、总结

SoC顶层架构设计,说白了就是平衡的艺术。你要在性能、功耗、面积之间找平衡。总线互联呢?就是把这个平衡落到具体的硬件上。

我经常跟团队说:架构设计不是画图,是算账。带宽、延迟、buffer深度、QoS策略,每一项都要算清楚。算不清楚的地方,就是以后流片回来要踩的坑。

好了,这一章就聊到这儿。下一章咱们深入AXI协议的细节,讲讲怎么优化outstanding和乱序传输。到时候我会分享一个我踩过的坑——因为ID分配不当,导致系统性能下降30%。