DRAM/SDRAM

存储密度更大的随机存储器

1. 引言

在 ysyxSoC 项目中,我们先后引入了 SRAM(8KB)PSRAM(4MB),但前者容量太小,后者访问带宽有限。为了运行大型程序(如 RT-Thread、microbench)并满足 CPU 对高带宽主存的需求,我们最终引入了 SDRAM(同步动态随机存取存储器)

本总结将系统性地阐述 DRAM/SDRAM 的存储原理、颗粒结构、控制器设计、扩展方式及其在 ysyxSoC 中的工程实践,并提供完整的 Verilog 代码示例。


2. DRAM 基本单元与操作原理

2.1 存储单元(1T1C)

  • 结构:1 个晶体管(开关) + 1 个电容(电荷存储)。
  • 逻辑:电容充电(高电平)表示逻辑“1”,放电(低电平)表示逻辑“0”。
  • 漏电问题:电容会自然放电,数据在数毫秒内丢失,因此必须周期性刷新(Refresh)
  • 刷新要求:每个存储单元必须在 64ms 内被刷新一次(标准),否则数据丢失。

2.2 读出放大器(Sense Amplifier)与行缓冲

  • 读出放大器:用于检测电容上的微小电压差,并将其放大为稳定的逻辑电平。多个读出放大器组成行缓冲(Row Buffer)
  • 操作流程
    1. PRECHARGE:预充电位线,使两端电压相等(VDD/2)。
    2. ACTIVATE(激活行):将目标行的字线拉高,连接存储单元到位线,电荷共享产生微小电压差。
    3. 读出放大器使能,检测并放大该电压差,将整行数据锁存到行缓冲中。
    4. READ/WRITE:对行缓冲中的列进行读写操作。
    5. PRECHARGE(再次):关闭行,将行缓冲数据写回存储单元,并重新预充电位线。

2.3 行缓冲命中与冲突

  • 行命中(Row Hit):待访问地址的行已处于激活状态(在行缓冲中),可直接进行读写,延迟低(~10–15ns)。
  • 行冲突(Row Conflict):待访问地址的行不同于当前激活行,必须先 PRECHARGE 关闭当前行,再 ACTIVATE 新行,延迟高(~60–80ns)。

2.4 刷新

  • 控制器必须定期向每个 Bank 发送 AUTO REFRESH 命令。
  • 刷新操作会占用总线带宽,但可分散在时间上以减少对性能的影响。

3. SDRAM 颗粒结构(以 MT48LC16M16A2 为例)

3.1 逻辑组织

  • 4 个 Bank(存储体),每个 Bank 是一个行列矩阵。
  • 行数:8192 行,列数:512 列。
  • 颗粒字长:16 位(DQ[15:0])。
  • 总容量:4 × 8192 × 512 × 16 bit = 256 Mbit = 32 MB。

3.2 引脚定义

信号组 名称 位宽 说明
时钟 CLK, CKE 1+1 主时钟和时钟使能
命令 CS#, RAS#, CAS#, WE# 4 组合解码出命令
地址 A[12:0] 13 行/列复用地址
Bank 地址 BA[1:0] 2 选择 4 个 Bank 之一
数据 DQ[15:0] 16 双向数据总线
掩码 DQM[1:0] 2 每个字节的写掩码(低有效)

3.3 命令解码

命令由 {CS#, RAS#, CAS#, WE#} 组合生成,常用命令如下:

命令 CS# RAS# CAS# WE# 功能
ACTIVE 0 0 1 1 激活指定 Bank 的一行
READ 0 1 0 1 从已激活行读出数据(突发)
WRITE 0 1 0 0 向已激活行写入数据(突发)
PRECHARGE 0 0 1 0 关闭当前行,预充电
AUTO REFRESH 0 0 0 1 自动刷新一行(内部计数器)
LOAD MODE REG 0 0 0 0 设置模式寄存器(CAS 延迟等)
NOP 0 1 1 1 无操作

3.4 突发传输(Burst)与 CAS 延迟

  • 突发传输:一次 READ/WRITE 命令后,可连续传输多个数据(Burst Length = 1, 2, 4, 8 或全页)。
  • CAS 延迟(CL):从 READ 命令发出到第一个数据出现在 DQ 引脚上的时钟周期数(如 CL=2)。
  • 效率:突发传输避免了每个节拍重新发送列地址,显著提升连续访问带宽。
  • 示例:若突发长度=4,CL=2,则总周期 = 1(命令)+ 2(CL)+ 3(后续节拍)= 6 周期;而若分四次发送 READ,则需 12 周期。

3.5 模式寄存器

  • 通过 LOAD MODE REGISTER 命令配置:
    • CAS 延迟(CAS Latency):a[6:4]。
    • 突发长度(Burst Length):a[2:0](1,2,4,8 或全页)。
    • 其他字段(突发类型、写模式等可忽略)。

4. SDRAM 控制器(ysyxSoC 集成)

4.1 核心功能

  • 将 AXI/APB 总线请求转换为 SDRAM 命令序列。
  • 管理行缓冲状态,实现行命中优化(FR-FCFS 调度)。
  • 定时发送 AUTO REFRESH(每 7.8μs 刷新一行,保证 64ms 内全部刷新)。
  • 支持突发传输,匹配 AXI 突发长度。

4.2 提供的封装

  • sdram_top_apb:APB 封装,适用于功能调试(速度慢,但握手机制简单)。
  • sdram_top_axi:AXI 封装,用于最终集成(支持突发、乱序、高带宽)。

4.2.1 APB 封装关键代码(sdram_top_apb.v 简化)

wire is_read  = ((in_psel && !in_penable) || (state == ST_WAIT_ACCEPT)) && !in_pwrite;
wire is_write = ((in_psel && !in_penable) || (state == ST_WAIT_ACCEPT)) &&  in_pwrite;

sdram_axi_core #(
  .SDRAM_MHZ(100),
  .SDRAM_ADDR_W(24),
  .SDRAM_COL_W(9),
  .SDRAM_READ_LATENCY(2)
) u_sdram_ctrl(
  .clk_i(clock),
  .rst_i(reset),
  .inport_wr_i(is_write ? in_pstrb : 4'b0),
  .inport_rd_i(is_read),
  .inport_addr_i(in_paddr),
  .inport_write_data_i(in_pwdata),
  .inport_accept_o(req_accept),
  .inport_ack_o(in_pready),
  .inport_error_o(in_pslverr),
  .inport_read_data_o(in_prdata),
  .sdram_* (sdram_*)
);

4.2.2 内部核心 sdram_axi_core 关键参数

  • SDRAM_ADDR_W = 24(行13 + 列9 + Bank2)。
  • SDRAM_READ_LATENCY = 2(CAS 延迟)。
  • 自动计算时序参数:tRCD, tRP, tRFC 基于 SDRAM_MHZ

5. 扩展方式:位扩展与字扩展

5.1 位扩展(Bit-Width Expansion)

目的:增大数据总线宽度,提升单次访存带宽。

方法:将多颗颗粒的数据线并联,但共享地址/命令。例如两颗 16 位颗粒组成 32 位总线。

实现sdram_32mx32.v):

module sdram_32mx32(
  input clk, cke, cs, ras, cas, we,
  input [12:0] a,
  input [1:0] ba,
  input [3:0] dqm,
  inout [31:0] dq
);
  sdram_32mx16 u_low (
    .clk(clk), .cke(cke), .cs(cs), .ras(ras), .cas(cas), .we(we),
    .a(a), .ba(ba), .dqm(dqm[1:0]), .dq(dq[15:0])
  );
  sdram_32mx16 u_high (
    .clk(clk), .cke(cke), .cs(cs), .ras(ras), .cas(cas), .we(we),
    .a(a), .ba(ba), .dqm(dqm[3:2]), .dq(dq[31:16])
  );
endmodule

效果:带宽翻倍,容量不变(仍是 32MB),但 DQ 引脚数翻倍。

5.2 字扩展(Word-Depth Expansion)

目的:增加存储容量。

方法:用高位地址线作为片选,选择不同的颗粒组。每组内部可包含位扩展。

实现sdram.v,实例化两组 sdram_32mx32):

wire [2:0] command = {ras, cas, we};
reg ras_u0, cas_u0, we_u0;
reg ras_u1, cas_u1, we_u1;

always @(*) begin
  case(command)
    3'b000, 3'b111: begin // NOP and LOAD MODE are broadcast
      {ras_u0, cas_u0, we_u0} = command;
      {ras_u1, cas_u1, we_u1} = command;
    end
    default: begin
      {ras_u0, cas_u0, we_u0} = !a[13] ? command : 3'b111;
      {ras_u1, cas_u1, we_u1} =  a[13] ? command : 3'b111;
    end
  endcase
end

sdram_32mx32 grp0 ( ... .ras(ras_u0), .cas(cas_u0), .we(we_u0), .a(a[12:0]), ... .dq(dq) );
sdram_32mx32 grp1 ( ... .ras(ras_u1), .cas(cas_u1), .we(we_u1), .a(a[12:0]), ... .dq(dq) );

效果:容量从 32MB 扩展至 64MB,地址连续(高位 A[13] 区分组),带宽不变。

5.3 组合扩展

  • 最终 ysyxSoC:使用两组 sdram_32mx32(每组位扩展),通过字扩展实现 64MB 容量,32 位数据总线
  • 地址映射:0xa0000000~0xa1ffffff → 组0;0xa2000000~0xa3ffffff → 组1。

6. PSRAM 与 DRAM 对比

特性 PSRAM(伪静态) SDRAM(同步动态)
内部刷新 内置自刷新 需外部控制器定时刷新
接口 SPI/QSPI(串行,引脚少) 并行(地址/数据/命令,引脚多)
带宽 受限(串行) 高(并行 + 突发)
容量 中等(如 4MB) 大(可达数 GB)
易用性 类似 SRAM,控制简单 需复杂时序和状态机
典型应用 嵌入式小系统 通用计算机主存

7. 性能与资源权衡

扩展方式 优点 缺点
位扩展 提升带宽,无需修改地址逻辑 DQ 引脚数增加,PCB 布线复杂
字扩展 提升容量,仅需增加 1 位地址引脚 跨组访问可能增加延迟
组合扩展 同时获得容量与带宽提升 控制器需管理更多片选和时序

在 ysyxSoC 中,我们通过组合扩展,在仿真环境中实现了 64MB、32 位宽 的 SDRAM 子系统,足以运行 RT-Thread 等复杂应用。


8. 实际应用与测试

8.1 测试

  • 使用 mem-test 程序对 SDRAM 空间进行全地址读写校验。
  • APB 封装下,完整测试 64MB 需数小时(受限于 APB 单拍传输)。
  • AXI 封装下,突发传输可显著加速。

8.2 引导加载

  • Bootloader(SSBL)将程序从 Flash 搬运到 SDRAM 起始地址(0xa0000000)。
  • 栈仍放置在 SRAM(8KB)以提升函数调用速度。

8.3 运行大型程序

  • 在 SDRAM 上运行 microbench 和 RT-Thread,性能和容量均满足要求。

9. 总结

  • DRAM/SDRAM 通过 1T1C 单元实现高密度存储,但需刷新和复杂时序控制。
  • SDRAM 控制器 是连接总线与颗粒的关键模块,负责命令生成、时序管理和刷新调度。
  • 位扩展字扩展 是构建大容量、高带宽主存系统的两种基本方式,可灵活组合。
  • ysyxSoC 成功集成了一个 64MB、32 位宽的 SDRAM 子系统,为运行大型软件提供了坚实基础。

通过理解这些原理和实现,你已具备了设计现代 SoC 内存子系统的核心能力。

posted @ 2026-07-24 11:17  mo686  阅读(3)  评论(0)    收藏  举报