DDR物理层基础:这些信号你摸过没?

说实话,每次我带新人调DDR,第一件事就是让他们把手伸到示波器探头上去摸CK、DQS这几个信号。不是真摸,是感受一下那个波形——抖不抖、干不干净、有没有回勾。物理层搞不明白,后面训练序列再怎么写都是白搭。

这一章我把DDR物理层最核心的几个信号类型、ODT和驱动强度串起来讲。你不用背手册,跟着我过一遍实战中踩过的坑就行。

2.1 信号类型:谁在发,谁在收?

DDR总线上的信号可以分成三大类:时钟CK、数据相关信号DQ/DQS、以及命令地址CMD/ADDR。每类信号在训练序列里的作用完全不同。我习惯画个表格帮自己理清思路——

信号 方向 训练中的作用
CK Controller → DRAM 所有信号的参考时钟,训练的先决条件
DQS 双向 读/写数据选通,训练对齐的核心
DQ 双向 数据总线,读/写训练的目标
CMD/ADDR Controller → DRAM 命令和地址,训练时的控制基础

你看,CK是老大,CK不稳,什么都别谈。CMD/ADDR是传令兵,DQ/DQS是主力部队。

CK(差分时钟)

CK和CK#是差分对。差分的好处是什么?抗共模干扰,摆幅小、速率高。DDR4的CK跑在1.6GHz以上,你想想看,这个频率下信号很容易被串扰吃掉。我在一个4层板项目上吃过亏——CK走线太长还没包地,结果DQS锁不住,训练死活过不去。

注意:CK到每个DRAM颗粒的等长必须做到 ±10ps 以内。我一个同事把CK绕得乱七八糟,结果写训练哪怕用了最强驱动都救不回来。

DQS(数据选通)

DQS是DQ的“伴侣”。写数据时Controller发DQS,读数据时DRAM发DQS。DQS不像CK那样连续跑,它是Burst式的。训练序列里最重要的事情就是让DQS的边缘对准DQ的眼图中心。

说白了,DQS就是一个“什么时候该采样”的脉冲。

DQ(数据总线)

DQ就是数据本身。每8位DQ配一对DQS(x8颗粒),或者每16位配一对(x16颗粒)。训练时Controller会发固定的数据Pattern,然后调整DQS的延迟,找到最佳的采样点。

我教新人一个小技巧:调试时先看DQ和DQS的相位关系,如果DQS边沿正好在DQ数据的切换区,那训练一定失败。这时候就该调DQS的延迟了。

CMD/ADDR(命令与地址)

这个信号组是单端的,不像CK和DQS那样用差分。CMD/ADDR需要CK的边沿来采样。所以CK的抖动直接会反应到CMD/ADDR的采样窗口上。我觉得新手最容易忽略的就是CMD/ADDR上的信号完整性——因为跑得比DQ慢多了,但别小看它,一旦时序崩了,芯片连初始化的读命令都收不到。

2.2 片上终端 ODT:为啥要终结?

ODT的全称是On-Die Termination,片上终端电阻。DDR信号跑太快,信号反射很严重。我在一个DDR4调测项目里见过不加ODT的波形——那振铃简直像心电图。ODT其实就是把电阻放在芯片内部,帮我把反射能量吸收掉。

ODT的典型值有:40Ω、60Ω、120Ω,还有关闭(Disable)状态。什么时候用哪个值?看拓扑。我列一下我常用的配置:

  • 单颗粒/双颗粒:ODT 40Ω~60Ω 就够了
  • 多颗粒(DIMM):ODT 60Ω~120Ω,因为负载重,得用更大的阻抗来匹配
  • 写操作:ODT在DRAM端启用
  • 读操作:ODT在Controller端启用

嗯,这里要注意:ODT不是越大越好。你想想看,120Ω的ODT对信号吸收能力弱,反射压不住;而40Ω虽然吸收好,但功耗大、信号幅度被拉得太低。我一般从60Ω起调,然后看眼图。

我的实战习惯:写训练时盯着DRAM端ODT,读训练时盯着Controller端ODT。调这个值的时候必须一边看示波器一边改MRx寄存器,别信仿真仿出来的最优值——板子上的寄生参数谁都说不准。

2.3 驱动强度:信号能推多远?

驱动强度是指输出buffer能提供多大的电流能力。对DDR来说,DQ和DQS的驱动强度直接影响信号的眼高、上升时间、以及反射。我见过有人开过强驱动——信号像打了鸡血一样陡峭,结果反射把别的信号都串成筛子了。

DDR4的驱动强度一般可以配置为34Ω、40Ω、48Ω、60Ω几种。选择的原则是:在满足时序的前提下,尽量用弱驱动以减少EMI和过冲。

配置 适用场景 效果
34Ω 短距离、少负载 上升时间快但EMI大
40Ω 大多数DDR4系统 平衡功耗和信号质量
48Ω 长距离、多负载 反射小但信号幅度偏低
60Ω 低功耗优先 EMI最小,但信号边沿慢
// 一个用于初始ODT和驱动强度的伪代码示例
// 上电初始化部分
void ddr_phy_init(void){
    // 先配置ODT: 从60Ω开始
    mr1_odt_set(60);
    // 配置DQ驱动强度: 40Ω
    mr2_drive_strength_set(40);
    // 然后做ZQ校准
    zq_calibration();
    // 再开始训练
    ddr_training_start();
}

千万记住:ODT和驱动强度需要配合调整,不能独立优化。比如用40Ω驱动的同时ODT用120Ω,那个不匹配会造成严重的过冲。我曾经在DDR3上把这个组合当成了最优解,结果ZQ校准跑完直接报错……后来发现是终端阻抗没匹配好。

2.4 DDR物理层信号互联结构图

下面这张图是我自己画的DDR物理层信号互联结构。它把CK、DQS、DQ、CMD/ADDR与ODT、驱动强度的关系串在了一起。你调试的时候可以参考这张图去追信号流向。

DDR物理层信号互联结构图 DDR物理层信号互联与配置关系 Controller ODT端: 读启用 驱动强度: 34~60Ω DRAM ODT端: 写启用 驱动强度: 34~60Ω CK 差分时钟 DQS 数据选通 DQ 数据总线 CMD/ADDR ODT 配置原则 写操作: DRAM端启用ODT 读操作: Controller端启用ODT 配合ZQ校准使用,从60Ω起调 驱动强度配置原则 轻负载: 34Ω 强驱动 重负载: 48~60Ω 弱驱动 DDR4: 默认从40Ω开始调 图2.1 DDR物理层信号互联与配置结构

这张图其实就是我训练DDR之前必须确认好的四个要素:ODT左右各配、驱动强度上下匹配、信号类型方向清楚、CK时钟干净。缺一个,训练序列就等着报错吧。

2.5 避坑指南

说了这么多,最后给你几个我亲手踩过的坑:

避坑1: 我曾经把ODT和驱动强度都设成了同一个值,比如都是40Ω,以为肯定匹配。结果因为PCB走线的特性阻抗是50Ω,反而失配了。实际上ODT和驱动强度没必要相等,两个参数要独立看,但匹配的目标都是和传输线阻抗(50Ω或40Ω)对齐。

避坑2: 有一次调试DDR4,写训练一直失败,眼图惨不忍睹。我查了半天,原因居然是CK和DQS之间的偏差太大了——CK从Controller到所有DRAM的链路长度多走了2cm。物理层不对,训练序列再怎么优化都没用。所以,训练调试之前先拿示波器测一下CK到各个DRAM的延迟差。

避坑3: 驱动强度不是越大越好。我记得在某个项目中,新人把DQ驱动开到了最高,结果上升沿太陡,串扰到旁边的DQS上,DQS的眼图直接被污染了。后来换回40Ω,配合60Ω的ODT,一切正常。

好了,物理层这些概念搞明白了,下一步你就能看懂训练序列那些步骤为什么要那样调了。记住:物理层是地基,地基稳了,楼才能盖高。