第10课 · 存储器

SRAMROM读写初始化

📌 学习目标:实现 SRAM(同步读写存储器)和 ROM(只读存储器),掌握 Verilog 存储器建模方法,通过 Verilator 验证读写和初始化功能。

一、存储器概述

存储器是计算机中用于存储数据和程序的部件。根据读写特性分为:

类型挥发性用途
SRAM易失Cache、寄存器文件
DRAM易失主存
ROM非易失固件、启动代码
Flash✅(慢)非易失SSD、BIOS

二、SRAM 原理

SRAM(Static Random-Access Memory)使用 6 个晶体管构成的双稳态触发器存储 1 位数据。

2.1 SRAM 特点

2.2 SRAM 读写时序

操作cswe地址数据
10有效dout ← mem[addr]
11有效mem[addr] ← din
未选0XXdout 高阻

三、ROM 原理

ROM(Read-Only Memory)在制造时写入数据,运行时只读。在 FPGA 中用初始化文件或 case 语句实现。

四、Verilog 实现

// memory.v — SRAM + ROM // 16x8 SRAM(同步写、异步读) module sram #(parameter DEPTH=16, WIDTH=8) ( input clk, input we, input [$clog2(DEPTH)-1:0] addr, input [WIDTH-1:0] din, output [WIDTH-1:0] dout ); reg [WIDTH-1:0] mem [0:DEPTH-1]; assign dout = mem[addr]; always @(posedge clk) begin if (we) mem[addr] <= din; end endmodule // 16x8 ROM(只读,初始化内容) module rom #(parameter DEPTH=16, WIDTH=8) ( input [$clog2(DEPTH)-1:0] addr, output [WIDTH-1:0] dout ); reg [WIDTH-1:0] mem [0:DEPTH-1]; initial begin // 初始化 ROM 内容:地址 * 17(斐波那契风格) mem[0] = 8'h00; mem[1] = 8'h11; mem[2] = 8'h22; mem[3] = 8'h33; mem[4] = 8'h44; mem[5] = 8'h55; mem[6] = 8'h66; mem[7] = 8'h77; mem[8] = 8'h88; mem[9] = 8'h99; mem[10] = 8'hAA; mem[11] = 8'hBB; mem[12] = 8'hCC; mem[13] = 8'hDD; mem[14] = 8'hEE; mem[15] = 8'hFF; end assign dout = mem[addr]; endmodule

4.1 测试台

// tb_memory.v module tb_memory; reg clk, we; reg [3:0] addr; reg [7:0] din; wire [7:0] sram_dout, rom_dout; sram #(.DEPTH(16), .WIDTH(8)) u_sram ( .clk(clk), .we(we), .addr(addr), .din(din), .dout(sram_dout) ); rom #(.DEPTH(16), .WIDTH(8)) u_rom ( .addr(addr), .dout(rom_dout) ); integer pass = 0, fail = 0; always #5 clk = ~clk; initial begin clk = 0; we = 0; addr = 0; din = 0; // ROM 初始化验证 #1; for (integer i = 0; i < 16; i = i + 1) begin addr = i; #1; if (rom_dout !== (i * 8'h11)) begin $display("FAIL ROM[%0d]: got %h exp %h", i, rom_dout, i*8'h11); fail = fail + 1; end else pass = pass + 1; end // SRAM 写入测试 we = 1; for (integer i = 0; i < 16; i = i + 1) begin addr = i; din = i + 8'hA0; #10; end // SRAM 读回验证 we = 0; for (integer i = 0; i < 16; i = i + 1) begin addr = i; #1; if (sram_dout !== (i + 8'hA0)) begin $display("FAIL SRAM read[%0d]: got %h", i, sram_dout); fail = fail + 1; end else pass = pass + 1; end // SRAM 覆盖写入测试 we = 1; addr = 5; din = 8'hFF; #10; we = 0; addr = 5; #1; if (sram_dout !== 8'hFF) begin $display("FAIL SRAM overwrite: got %h", sram_dout); fail=fail+1; end else pass=pass+1; $display("========================================"); $display("存储器测试: PASS=%0d FAIL=%0d", pass, fail); if (fail == 0) $display("✅ SRAM读写+ROM初始化验证通过!"); else $display("❌ 存在失败!"); $display("========================================"); $finish; end endmodule

五、Verilator 编译命令

verilator --cc memory.v --exe tb_memory.v \ --build --top-module tb_memory ./obj_dir/Vtb_memory

六、存储器层次结构

┌─────────────────────────┐
│    CPU 寄存器 (x0-x31)   │  ← 最快 (~0.3ns, ~1KB)
├─────────────────────────┤
│    L1 Cache (SRAM)      │  ← 快 (~1ns, 32-64KB)
├─────────────────────────┤
│    L2 Cache (SRAM)      │  ← 中等 (~5ns, 256KB-1MB)
├─────────────────────────┤
│    L3 Cache (SRAM)      │  ← 较慢 (~10ns, 4-32MB)
├─────────────────────────┤
│    主存 (DRAM)           │  ← 慢 (~50ns, GB级)
├─────────────────────────┤
│    SSD (Flash)          │  ← 很慢 (~100μs)
├─────────────────────────┤
│    HDD (磁盘)            │  ← 最慢 (~10ms)
└─────────────────────────┘

locality principle:程序倾向于访问最近访问过的数据及其附近的数据。

🤔 思考题:为什么 SRAM 用 6 个晶体管而 DRAM 只用 1 个晶体管+1 个电容?SRAM 为什么不需要刷新?

💡 提示:SRAM 是正反馈双稳态电路(自保持),DRAM 是电容存储(会漏电需刷新)

🏆 成就解锁:存储器架构师

✅ Verilator 仿真验证通过

✅ SRAM 同步写、异步读验证正确

✅ ROM 初始化数据读取验证正确

✅ SRAM 覆盖写入验证正确

🎯 下一目标:RISC-V 指令集 → 第11课:RV32I 基础