3、系统集成基础:SoC架构中的存储器子系统、存储器控制器与总线协议

各位同学,今天我们来聊聊系统集成的基础。说白了,就是把存储器这个“仓库”装进SoC这个“城市”里,还得让它跟CPU、DMA这些“居民”顺畅地打交道。

我刚开始做芯片验证那会儿,总觉得存储器不就是个存数据的地方嘛,有啥好讲的?后来踩的坑多了才明白——存储器子系统是整个SoC的命脉。你CPU算得再快,数据喂不进去,全是白搭。

3.1 SoC架构中的存储器子系统

一个典型的SoC里,存储器不是单一存在的。它是个分层结构,像个金字塔。

核心要点:存储器子系统的设计目标,是在性能容量成本之间找到平衡点。

从上往下看,大概是这么个结构:

  • 寄存器(Registers):在CPU核内,速度最快,容量最小。我习惯叫它“手边的工具台”。
  • Cache(缓存):L1/L2/L3,离CPU越近越快。L1 Cache的访问延迟通常只有1-2个时钟周期。
  • SRAM(静态随机存取存储器):片上内存,速度快,但面积大。常用于做TCM(紧耦合内存)或FIFO。
  • DRAM(动态随机存取存储器):片外内存,容量大,但速度慢。DDR4/DDR5/LPDDR都属于这类。
  • Flash/ROM:非易失性存储,存代码和固件。启动时用的就是它。

你想想看,如果CPU每次读写都去访问片外的DDR,那延迟得几百个时钟周期,性能直接崩了。所以Cache的作用就是“预取”和“缓存”,把常用的数据留在身边。

我的经验:有一次做AI芯片验证,发现DDR带宽利用率只有30%。查了半天,原来是Cache的替换策略没配好,频繁的Cache Miss导致数据一直在DDR和Cache之间来回倒腾。后来把预取深度调大了一倍,带宽利用率直接飙到85%。

3.2 存储器控制器(Memory Controller)的功能

存储器控制器,你可以把它理解成“仓库管理员”。CPU说“我要读地址0x1000的数据”,控制器就得去DDR里把数据找出来,再送回来。

它的核心功能有这几个:

  1. 地址映射:把CPU发来的逻辑地址,转换成DDR芯片的物理地址(行、列、Bank)。
  2. 命令调度:DDR的读写有严格的时序要求(比如tRCD、tCL、tRP)。控制器得按规矩来,不能乱发命令。
  3. 数据缓冲:写数据时先存到缓冲区,等DDR准备好了再发出去。读数据时也一样,先缓存再返回。
  4. 刷新控制:DRAM需要定期刷新,否则数据会丢。控制器得在后台偷偷做这件事,不能影响正常读写。
  5. ECC校验:高端场景下,控制器会做纠错码校验,保证数据不出错。

注意:我曾经遇到过一个bug,DDR的刷新请求和读请求冲突了,控制器没处理好优先级,导致读数据延迟了十几个周期。结果整个系统的帧率直接掉了一半。嗯,这里要提醒大家——控制器的调度算法,一定要在验证阶段覆盖各种冲突场景。

下面这张图,是我画的一个简化版存储器控制器内部结构:

存储器控制器内部结构(简化版) 总线接口 地址映射 命令调度 数据缓冲 刷新控制 ECC校验 DDR接口 总线协议(AXI/AHB/APB)→ 存储器控制器 → DDR芯片

3.3 总线协议与存储器接口

总线协议,就是SoC里各个模块之间通信的“交通规则”。ARM公司搞了三套主流协议:AXI、AHB、APB。它们各有各的适用场景。

3.3.1 AXI(高级可扩展接口)

AXI是高性能总线,支持乱序传输、突发传输、多通道并行。说白了,就是“高速公路”。

它的特点:

  • 独立通道:读地址、读数据、写地址、写数据、写响应,五个通道各走各的。
  • 乱序传输:可以同时发多个请求,返回的顺序可以跟请求顺序不一样。
  • 突发传输:一次发一个起始地址,后面连续传多个数据,效率极高。

关键点:AXI的握手协议是VALID/READY机制。发送方拉高VALID,接收方拉高READY,一拍握手成功。如果有一方没准备好,就等一拍。

我举个例子,AXI读传输的时序大概是这样:

// AXI读事务示例
// 1. 发送读地址:ARVALID拉高,ARADDR=0x1000,ARREADY拉高
// 2. 等待数据返回:RVALID拉高,RDATA=0xABCD,RREADY拉高
// 3. 最后一个数据:RLAST拉高,表示传输结束

always @(posedge clk) begin
  if (arvalid & arready) begin
    // 地址被接收
    addr_sent <= 1'b1;
  end
  if (rvalid & rready & rlast) begin
    // 传输完成
    trans_done <= 1'b1;
  end
end

我的建议:验证AXI接口时,一定要覆盖VALID/READY的各种组合。比如VALID一直拉高但READY时高时低,或者READY一直拉高但VALID断断续续。我见过太多验证环境只测了“一拍握手”的理想情况,结果流片回来发现总线卡死了。

3.3.2 AHB(高级高性能总线)

AHB是ARM的“中端”总线。它比AXI简单,但比APB复杂。支持流水线操作和突发传输,但不支持乱序。

它的特点:

  • 流水线:地址阶段和数据阶段可以重叠,提高吞吐量。
  • 单一主控:同一时刻只能有一个主设备占用总线。
  • 分时复用:地址和数据共用一组总线,通过控制信号区分。

AHB的传输分两个阶段:地址阶段(Address Phase)和数据阶段(Data Phase)。地址阶段发HADDR和HWRITE,数据阶段发HWDATA或HRDATA。

避坑指南:我曾经在AHB验证中踩过一个坑——从设备返回的HREADY信号在最后一个数据时拉低了,导致总线死锁。原因是从设备内部FIFO满了,但没处理好反压。所以验证AHB时,一定要测HREADY随机拉低的场景。

3.3.3 APB(高级外设总线)

APB是“低速小路”,专门用来接那些不要求高性能的外设,比如UART、GPIO、I2C。它简单到几乎没有握手信号。

它的特点:

  • 两状态机:IDLE状态和SETUP状态。写操作时,先进入SETUP,再进入ACCESS。
  • 无流水线:每个传输至少需要两个时钟周期。
  • 无突发:一次只能传一个数据。

APB的写操作时序:

// APB写传输
// 1. IDLE状态:PSEL=0,PENABLE=0
// 2. SETUP状态:PSEL=1,PENABLE=0,PADDR和PWDATA有效
// 3. ACCESS状态:PSEL=1,PENABLE=1,数据被采样
// 4. 回到IDLE或下一个SETUP

3.4 三种总线的对比

我把它们放在一起对比一下,方便你理解:

特性 AXI AHB APB
性能 高(乱序、突发) 中(流水线、突发) 低(无流水线)
复杂度 高(5个通道) 中(2个阶段) 低(2个状态)
适用场景 DDR控制器、DMA、高性能加速器 SRAM、内部总线矩阵 低速外设(UART、GPIO)
握手方式 VALID/READY HREADY PSEL/PENABLE
典型频率 500MHz+ 200-400MHz 50-100MHz

在实际的SoC中,这三种总线是共存的。CPU和DDR之间走AXI,内部SRAM走AHB,低速外设走APB。中间通过总线桥(Bus Bridge)来转换协议。

总结一下:存储器子系统是SoC的“血管”,存储器控制器是“心脏”,总线协议是“血管壁”。三者配合好了,数据才能顺畅流动。验证的时候,一定要把这三者作为一个整体来测,别拆开测。

好了,这一章的内容就到这里。记住我上面说的那些坑,你以后做存储器验证时会少走很多弯路。


专注资料整理