第1章:内存子系统架构概览

各位同学,欢迎来到《服务器SoC内存互连架构师研修班》。我是你们的老朋友,在芯片互连领域摸爬滚打了十几年。今天咱们聊聊内存子系统,这是整个SoC里最绕不开的“硬骨头”。

你想想看,CPU算力再强,如果内存喂不饱数据,那就是“茶壶里煮饺子——倒不出来”。我当年做第一颗服务器芯片时,就吃过这个亏。CPU跑得飞快,但内存延迟一高,整体性能直接腰斩。从那以后,我养成了一个习惯:先看内存架构,再看CPU核心。

核心观点:内存子系统是SoC性能的“咽喉”。带宽、延迟、效率,三者缺一不可。

1.1 DDR / LPDDR / HBM 内存协议对比

先说协议。市面上主流的内存协议就三种:DDR、LPDDR、HBM。很多人觉得它们只是功耗和带宽不同,其实没那么简单。

特性 DDR (如DDR5) LPDDR (如LPDDR5) HBM (如HBM2E)
典型带宽 ~32 GB/s per channel ~25 GB/s per channel ~460 GB/s per stack
工作电压 1.1V 0.5V - 0.9V 1.2V
功耗
延迟 中等 较低
封装方式 DIMM插槽 板载焊接 2.5D/3D堆叠
典型应用 服务器、台式机 手机、笔记本 AI加速器、HPC

我个人习惯,选型时先看功耗预算。如果功耗不是瓶颈,DDR5是性价比之王。但如果你做的是AI训练芯片,HBM几乎是唯一选择。为什么?因为带宽差距太大了。HBM2E单颗就能提供近500GB/s的带宽,而DDR5需要十几条通道才能拼得过。

避坑指南:我曾经在一个项目中,为了省成本选了LPDDR5做服务器主存。结果发现,LPDDR5的刷新周期和DDR不同,导致在高负载下出现周期性“卡顿”。后来不得不加了一级SRAM缓存才解决。所以,选协议时一定要看你的负载模型。

1.2 内存控制器架构(MC)

内存控制器,说白了就是CPU和DRAM之间的“翻译官”。它负责把CPU的访存请求,转成DRAM能懂的时序命令。

一个典型的内存控制器,内部包含这几个模块:

  • 请求队列(Request Queue):缓存来自CPU的读写请求。我建议至少做到32深度,否则容易丢请求。
  • 调度器(Scheduler):决定下一个执行哪个请求。这是整个MC的大脑。
  • 命令生成器(Command Generator):把调度好的请求,转成DRAM的ACT、READ、WRITE、PRE等命令。
  • 时序引擎(Timing Engine):负责检查DRAM的时序约束,比如tRCD、tCL、tRP等。嗯,这里要注意,时序引擎如果写不好,芯片直接跑飞。
  • 数据通路(Data Path):负责读写数据的传输和ECC校验。

我见过很多新手,一上来就堆队列深度,觉得越大越好。其实不然。队列深了,调度延迟反而会变高。我一般控制在32-64之间,具体看你的DRAM频率。

关键设计点:内存控制器的核心是“乱序执行”。CPU发来的请求顺序,和DRAM实际执行的顺序,往往是不同的。调度器要做的就是“重排序”,让DRAM的利用率最大化。

1.3 内存通道与Rank设计

通道(Channel)和Rank,这两个概念容易混淆。我简单解释一下:

  • 通道:一条独立的数据总线。每个通道有自己的DQ、DQS、命令/地址总线。通道之间完全独立。
  • Rank:同一个通道上的一组DRAM芯片,共享命令/地址总线,但数据总线是独立的(通过片选信号CS#区分)。

举个例子:一个DDR5通道,可以挂2个Rank。每个Rank是64bit数据位宽。如果你用x8的DRAM颗粒,一个Rank就需要8颗芯片(64/8=8)。

我在项目中遇到过一个问题:为了追求容量,在一个通道上挂了4个Rank。结果发现,由于CS#信号的负载太重,信号完整性出了问题,频率上不去。后来我学乖了,服务器SoC一般每个通道最多2个Rank,再多就加通道。

警告:Rank数量增加,虽然容量大了,但会导致以下问题:

  1. 命令/地址总线的负载增加,信号质量下降。
  2. 片选信号的时序更难收敛。
  3. 刷新开销增大(每个Rank需要独立刷新)。

所以,我建议:优先增加通道数,而不是Rank数

1.4 内存调度算法(FR-FCFS / Par-BS)

调度算法,是内存控制器的灵魂。这里我重点讲两个经典算法:FR-FCFS和Par-BS。

FR-FCFS(First Ready - First Come First Served)

这个算法的核心思想是:先服务那些“准备好”的请求。什么叫“准备好”?就是DRAM的行已经打开(Row Active),可以直接读写。

具体流程:

  1. 检查所有请求,看哪些请求对应的行已经打开。
  2. 在已打开行的请求中,按FCFS顺序服务。
  3. 如果没有已打开行的请求,则选一个行未打开的请求,先发ACT命令打开行,再服务。

这个算法很简单,但效果很好。我当年在第一个项目中就用了FR-FCFS,性能比纯FCFS提升了30%以上。为什么?因为DRAM的行激活(ACT)开销很大,能避免就避免。

FR-FCFS的缺点:它容易导致“饥饿”。如果一个请求的行一直没打开,它可能永远排不上队。所以,实际工程中,我会加一个“老化计数器”,超过一定时间的请求,强制提升优先级。

Par-BS(Parallel Bank Scheduling)

这个算法更高级。它利用了DRAM的Bank并行性。DRAM内部有多个Bank,每个Bank可以独立工作。Par-BS的核心是:尽量让请求分散到不同的Bank,让多个Bank同时工作

举个例子:

  • 请求A:Bank 0,行0x100
  • 请求B:Bank 1,行0x200
  • 请求C:Bank 0,行0x300

Par-BS会优先服务A和B,因为它们在不同Bank,可以并行。C虽然和A在同一Bank,但行不同,需要先关闭A的行(PRE),再打开C的行(ACT),开销很大。

我建议,如果你的SoC有4个以上内存通道,Par-BS的效果会非常明显。但要注意,这个算法的硬件实现复杂度较高,需要维护每个Bank的状态机。

实战经验:我曾经在一个8通道的AI芯片上,把调度算法从FR-FCFS换成Par-BS,带宽利用率从65%提升到了82%。代价是MC的面积增加了15%。但为了性能,值了。

知识体系总览

下面这张图,是我自己总结的内存子系统知识框架。你可以把它当作本章的“地图”。

内存子系统架构知识体系 内存协议对比 DDR5 LPDDR5 HBM2E/3 带宽/功耗/延迟 内存控制器架构 (MC) 请求队列 调度器 命令生成器 时序引擎 数据通路 通道与Rank设计 Channel 0 Channel 1 Rank 0 Rank 1 调度算法:FR-FCFS → Par-BS

这张图从下往上看,就是内存子系统的设计流程:先定协议,再搭MC架构,然后规划通道和Rank,最后调调度算法。每一步都环环相扣。

本章小结

好了,第一章的内容就到这里。我带你过了一遍内存子系统的四大块:协议、控制器、通道Rank、调度算法。这些都是基础中的基础,后面的章节会逐一深入。

最后送大家一句话:内存架构设计,没有银弹。每个项目都有自己的约束,你要学会在带宽、延迟、功耗、面积之间做权衡。这个能力,不是看书能看出来的,得靠项目“喂”出来。

课后思考:如果你现在要设计一颗面向AI推理的SoC,你会选DDR5还是HBM?为什么?欢迎在群里讨论。

专注资料整理