SDRAM地址已经送对, 为什么数据还不出来? 你可能漏了ACTIVE这一步

FPGA · SDRAM · 命令状态机

SDRAM地址已经送对,为什么数据还不出来?你可能漏了ACTIVE这一步

SDRAM控制器管理的是Bank与行状态,不是一根地址总线

SDRAM 内部按 Bank、行和列组织,行地址与列地址分时复用。一次访问通常要先激活目标行,再按器件规定时序发出列读写命令;若同一 Bank 已打开其他行,还要先预充电关闭。地址正确但状态错误,数据仍不会正确出现。

FPGA 端把地址和读使能都送了出去,逻辑分析仪上看不到明显毛刺,SDRAM 却不返回预期数据。很多初学者会继续查数据线,却忽略了器件内部当前打开的是哪一个 Bank、哪一行。

SDRAM 不是给出完整地址就能立即访问的异步 RAM。它把地址分成 Bank、行与列,并通过 ACTIVE、READ、WRITE、PRECHARGE 等命令驱动内部状态机。

一、为什么SDRAM要把地址拆成行和列

大容量存储阵列以二维方式组织,先选择一行,再在这行中选择列。为了减少外部引脚,许多 SDRAM 让同一组地址线在不同命令阶段分别承载行地址和列地址。

图 1 SDRAM 先激活目标行,再在已打开行中选择列(原理示意,非实测结果)

Bank 地址则选择哪一个相对独立的存储块。控制器每个周期不仅要给地址,还要让命令组合告诉器件“这是行地址、列地址,还是其他操作”。

二、ACTIVE做的不是“开始读”,而是打开一行

ACTIVE 命令锁存 Bank 与行地址,把目标行打开到该 Bank 的内部行缓冲。之后的 READ 或 WRITE 才能用列地址访问这一行中的数据。

ACTIVE 之后不能立即随意发列命令,需要满足器件规定的行到列等待时间。具体周期数与模式寄存器、时钟和器件规格有关,必须以目标数据手册为准。

三、目标Bank里已经开了别的行怎么办

同一 Bank 在某一时刻只能保持特定行状态。如果目标行已经打开,可以直接发列访问;如果 Bank 空闲,需要先 ACTIVE;如果打开的是另一行,就要先 PRECHARGE 关闭旧行,再激活新行。

图 2 PRECHARGE、ACTIVE 与列访问的基本命令顺序(原理示意,非实测结果)

这也是“地址都对却读不到”的常见原因:地址信号本身正确,但当前 Bank 状态不允许这条命令。

四、页命中与页冲突,本质是状态不同

图 3 空闲、目标行已打开、其他行已打开三种 Bank 状态(原理示意,非实测结果)

  • Bank空闲:需要先激活目标行,再等待规定间隔后访问列。
  • 目标行已打开:可在满足命令与数据时序的前提下直接访问目标列。
  • 其他行已打开:先预充电关闭旧行,再激活新行,访问路径更长。

Bank 交错可以在一个 Bank 传输数据时准备另一个 Bank,用状态重叠隐藏部分等待;但这要求控制器准确跟踪每个 Bank 的状态。

五、调试时不要只盯DQ

图 4 SDRAM 控制器调试的四组观察点(原理示意,非实测结果)

  1. 解码每个周期的命令组合,确认 ACTIVE、READ、WRITE、PRECHARGE 和 NOP 是否按状态出现。
  2. 分别标出 Bank、行地址和列地址在哪个周期被锁存。
  3. 核对命令之间的等待周期,并使用目标器件与当前模式寄存器的时序参数。
  4. 对齐数据方向、读延迟、写数据、DQM 与总线三态切换,避免读写争用。
  5. 从单 Bank、单地址、低频测试开始,再扩展到突发、交错与满速。

六、3个常见误区

  • 地址正确就一定能读:SDRAM 还需要正确命令和 Bank 状态。
  • 把等待周期写死就能复用:频率、模式与器件变化后必须重新按数据手册约束。
  • 仿真能读就代表硬件没问题:板级时序、信号完整性、上电初始化与模型准确性仍需验证。

工程判断:SDRAM 控制器的核心是按器件时序维护每个 Bank 的行状态。READ 只是列访问命令;没有正确 ACTIVE、等待和必要的 PRECHARGE,地址再正确也不会得到正确数据。

写在最后

SDRAM 调试最有效的转变,是从“这条地址线对不对”升级为“这个 Bank 现在处于什么状态”。

把命令、Bank、行、列和等待周期画成一条时间线,很多看似随机的读错会变成明确的状态机错误。