4. 内存控制器详解:调度策略、命令仲裁与数据总线利用率

内存控制器,说白了就是CPU和DRAM之间的那个“交通警察”。

我做了这么多年芯片,发现很多工程师把精力都放在计算单元上,觉得内存控制器嘛,买IP就行了。嗯,这话对也不对。IP确实能跑,但能不能跑出你想要的带宽,差别大了去了。今天我就把内存控制器里最关键的几个点掰开揉碎了讲清楚。

4.1 调度策略:FR-FCFS 与银行分组

先问个问题:内存请求来了,先服务谁?

最简单的做法是FIFO,谁先来谁先走。但DRAM有个特性——行缓冲。如果连续访问同一行,速度极快;如果频繁换行,那就要花时间预充电和激活。

FR-FCFS(First-Ready First-Come First-Serve) 就是针对这个问题的优化。它的核心思想是:先服务那些“准备好”的请求

FR-FCFS 调度规则:

  • 如果某个请求的行缓冲已经打开(行命中),优先服务它
  • 如果多个请求都行命中,按到达时间排序
  • 如果所有请求都行未命中,才按FCFS处理

我在一个ADAS项目中遇到过这种情况:摄像头数据流是连续的,但CPU偶尔会插入一些随机地址的访问。如果不做FR-FCFS,CPU的随机访问会把行缓冲冲掉,导致摄像头数据流的带宽直接腰斩。加了FR-FCFS之后,摄像头流的行命中率从40%提升到了85%。

但FR-FCFS有个副作用——饥饿问题。如果一直有行命中的请求插队,那些行未命中的请求可能永远得不到服务。所以实际工程中,我们通常会加一个“老化计数器”,超过一定时间没被服务的请求,优先级强制提升。

银行分组(Bank Grouping)

DDR4和DDR5引入了Bank Group的概念。每个Bank Group内部有独立的命令总线,这意味着你可以同时给不同Bank Group发命令。

我个人的习惯是:把关键数据流分散到不同的Bank Group中。比如显示控制器放在Group A,神经网络加速器放在Group B,CPU放在Group C。这样三个数据流可以并行访问,互不干扰。

避坑指南:

我曾经在一个项目中,把所有数据都塞到了同一个Bank Group里。结果发现带宽利用率只有理论值的60%。后来用Bank Group交错映射,利用率直接飙到92%。

记住:Bank Group不是越多越好,但如果你有多个独立的数据流,一定要把它们分开。

4.2 命令仲裁:谁先上总线?

内存控制器内部有多个命令队列:读队列、写队列、刷新队列、ZQ校准队列。仲裁器要从这些队列里选一个命令发出去。

常见的仲裁策略有:

  • 严格优先级:读优先于写,刷新优先于一切。简单但容易导致写请求堆积。
  • 轮询(Round-Robin):每个队列轮流来。公平但可能错过关键请求。
  • 加权轮询:给读队列更高的权重。这是最常用的方案。

你想想看,为什么读优先级通常高于写?因为CPU是读敏感的——读不到数据,流水线就 stall 了。写操作可以缓冲,晚几个周期问题不大。

但这里有个陷阱:写请求堆积过多,会导致读请求也变慢。因为DRAM的读操作需要先关闭写状态。所以实际工程中,我们会设置一个“写阈值”——当写队列超过某个深度时,强制切换到写模式。

注意:

刷新命令的优先级最高,但刷新期间不能做任何读写操作。如果刷新太频繁,会吃掉大量带宽。DDR5的刷新机制做了改进,支持“刷新管理”,可以合并多个刷新请求。我建议你务必开启这个功能。

4.3 数据总线利用率:从60%到95%的秘诀

数据总线利用率,是衡量内存控制器好坏的核心指标。公式很简单:

利用率 = 有效数据传输周期 / 总周期数

但想做到高利用率,没那么容易。我总结了几条实战经验:

  1. 减少命令间隔:连续两个读命令之间,最少要间隔几个周期(取决于时序参数)。好的调度器能把间隔压到最小。
  2. 利用写合并:多个小写请求合并成一个大的写请求,减少命令开销。
  3. 预取与突发长度匹配:DDR的突发长度通常是8或16。如果你的数据粒度是32字节,刚好匹配;如果是64字节,那就浪费了。我建议你根据DDR的突发长度来设计缓存行大小。
  4. 避免总线冲突:读和写不能同时占用数据总线。好的调度器会提前切换方向,减少“读-写-读”切换带来的空闲周期。

我记得有一次调试一个4K视频处理芯片,内存带宽利用率只有68%。查了半天,发现是写合并没做好——每个像素更新都单独发一个写命令。改成按行合并后,利用率直接到了91%。

4.4 知识体系总览

下面这张图,是我画的内存控制器核心逻辑。你看一眼,就能把今天讲的内容串起来。

内存控制器核心逻辑 CPU/GPU 请求 请求队列 调度器 FR-FCFS + 银行分组 命令仲裁器 读/写/刷新 优先级 DRAM 控制器 数据总线 利用率监控 反馈控制 核心:调度策略决定命令顺序,仲裁决定谁先上总线,最终影响数据总线利用率

从这张图你能看到,请求从CPU/GPU进来,先排队,然后调度器决定顺序,仲裁器决定谁先发,最后通过数据总线送到DRAM。每一步都影响最终的带宽利用率。

4.5 实战建议

最后,我给大家几个可以直接用的建议:

场景 推荐策略 预期效果
视频流处理 FR-FCFS + Bank Group隔离 带宽利用率提升20-30%
随机小数据访问 写合并 + 老化机制 减少写延迟50%
高并发多数据流 加权轮询 + Bank Group交错 避免饥饿,公平性提升
低延迟敏感应用 读优先 + 紧急通道 读延迟降低40%

嗯,内存控制器这块内容,说深也深,说浅也浅。关键是你得理解DRAM的物理特性,然后针对你的应用场景做取舍。没有银弹,只有最适合的方案。


专注资料整理