第一百四十五章 内存
七月三日,周六,早上九点,B207 开了灯。
孟思远比方宇明先到,在工位前坐下,打开 checklist,翻到第四层——「LPDDR4 内存初始化」。
这是七层里相对麻烦的一步。LPDDR4 的初始化不是简单的上电等待,而是需要按照 JEDEC 标准规定的时序,向内存控制器发送一系列 Mode Register(MR)写命令,配置内存的工作频率、CAS 延迟、驱动强度、刷新频率等参数,然后等待内存进入正常工作状态,再写入测试数据,读回来确认。
「今天能做完吗?」颜天磊到了,在旁边问。
「不一定,」孟思远说,「内存初始化这块,很容易卡。」
上午的工作分两段。
第一段是让内存控制器执行初始化序列。
孟思远用 OpenOCD 向芯片内部的内存控制器寄存器写入配置,然后触发初始化流程——内存控制器会自动按照配置好的参数向 LPDDR4 发送 MR 写序列。
流程启动后,他在控制台里等状态寄存器的变化。内存控制器有一个初始化完成标志位,当整个 MR 写序列结束之后,这个位会从 0 变成 1。
等了大约二十秒,状态寄存器的值没有变化,初始化完成标志位还是 0。
「卡住了,」孟思远说。
「什么情况?」颜天磊问。

「不知道,」孟思远说,「可能是 MR 配置的参数有问题,也可能是时序约束没有满足,内存控制器报了一个内部错误但没有把错误状态暴露出来。」
他把内存控制器的所有状态寄存器都读了一遍,在一个错误标志寄存器里发现了一个被置位的字段:「Training Failed」。
「Training Failed 是什么,」颜天磊问。
「LPDDR4 在正式工作之前需要做一个训练过程,」孟思远解释,「控制器和内存之间要对齐时钟和数据信号的采样时序——找到一个最佳的采样窗口,使得在给定频率下读写的可靠性最高。如果训练失败,初始化就无法完成。」
「为什么训练会失败?」
「频率不对,」贺志明在旁边说,他刚进来,把外套挂上,「你们的 MR 配置里,频率是多少?」
孟思远翻了一下,「3200 Mbps。」
贺志明走过来,「你的训练频率是多少?」
「也是……」孟思远看着配置文件,停了一下,「等等,」他说,「training 阶段有一个单独的频率参数,我用的是配置文件里的默认值,」他翻开文档,「默认值是 1600 Mbps,但是实际工作频率是 3200——」
「Training 阶段应该用低速,」贺志明说,「1600 Mbps 是对的,不是问题在这里。」他把孟思远的配置文件又看了一眼,「这里,」他用手指点了一下屏幕,「你的 tRFC 参数,是多少?」
孟思远凑近看,「0x34?」

「这个值对应的刷新周期是,」贺志明想了一下,「大约 200ns,但 LPDDR4 在 ×16 模式下,tRFC 最小值是 280ns,你的设置太短了。」
孟思远把 tRFC 从 0x34 改成了 0x46,对应大约 280ns,重新触发初始化流程。
这次等待的时间稍微长了一点,大约三十秒——
状态寄存器的初始化完成标志位从 0 跳到了 1。
「通了,」孟思远说。
「tRFC 太短,」贺志明说,「刷新操作没有足够的时间完成,内存控制器在等内存完成刷新,但内存还没做完你就发了下一条命令——协议层面的违规,training 就失败了。」
「这个,」孟思远说,「在后仿真里,我们没有特别验证 tRFC 的边界条件。」
「功能仿真通常只验证典型场景,」贺志明说,「边界时序参数在真实芯片上才会体现。」
下午是内存读写测试。
孟思远写了一段简单的测试:向 LPDDR4 地址空间的不同区域写入不同的数据 pattern,然后读回来和写入值比较。
第一轮测试 pattern 是 0xA5A5A5A5 和 0x5A5A5A5A,交替填充。写入完成后读回来——全部正确。
「基础读写通了,」他说。

第二轮是走位翻转(Walking Bit),逐位翻转数据位,测试每条数据线的独立性——这可以发现某条数据线是否有粘连故障,总是被相邻位影响。走位翻转测试覆盖了 32 位数据总线的全部 32 条线,全部通过。
「数据总线没有粘连,」颜天磊记在 checklist 上。
第三轮是地址遍历,从 LPDDR4 地址空间的开头一直写到边界,确认地址译码逻辑没有问题。
这一步花了将近两个小时。LPDDR4 的容量是 4GB,不可能全部遍历,孟思远选了几个典型的地址区域做采样验证。最终结果:地址译码正常,所有抽测区域读写一致。
下午六点,孟思远把第四层的测试报告整理成一页:初始化完成,tRFC 参数已修正为 0x46,Training 成功,读写测试全部通过。
他发给了方宇明。
方宇明看完,「LPDDR4 通了,」他说,「明天做第五层——时钟 PLL。」
「PLL 一般多久?」颜天磊问。
「看,」方宇明说,「PLL 锁定这件事,如果参数对了,很快;如果参数有偏差,或者噪声比预期大,可能要调。」
「贺工,」颜天磊问,「你觉得会有问题吗?」
贺志明喝了口茶,「我设计 SRAM 的,PLL 问题我解决不了,」他说,「你们得去找——」他想了一下,「对了,孟思远,你后仿真里 PLL 的 lock time 是多少?」

「大约 200 个 reference clock 周期,」孟思远说。
「实际芯片上,」贺志明说,「有一定概率比这个长,温度和电源噪声都会影响。」
陆衍那天下午一直待在 B207。
他没有做任何事,只是看着孟思远在命令行里敲命令,等读数,敲命令,等读数,然后贺志明发现 tRFC 的问题,改了一个数字,初始化就通了。
他发给豆包:「今天第四层通了,LPDDR4 内存初始化。卡了两个小时,原因是一个叫 tRFC 的参数设太短了,改掉就好了。」
豆包:「tRFC 是 Refresh Cycle Time,内存完成一次全局刷新操作所需的时间。LPDDR4 ×16 模式下这个值是有下限的,设得太短会导致刷新还没做完下一条命令就来了,协议层面违规,所以 Training 一直失败。」
陆衍:「贺志明一眼就看出来了。」
豆包:「这是做了很多年内存设计的工程师对这种参数的直觉——他见过这个错误,或者见过类似的错误,所以他知道往哪里看。」
陆衍:「现在是七月三日,bringup 第二天,七层里过了四层。」
豆包:「第五层:时钟 PLL 锁定。PLL 是砺火一号内部所有时序逻辑的频率基础——PLL 锁上了,芯片才能在目标频率下工作。」
陆衍把手机放下,B207 外面天黑了,上海七月的夜晚,热的,大家都在。