4. FPGA存储层次与缓存基础

星载FPGA的数据通路性能,往往不取决于逻辑资源有多少,而取决于“数据能不能在正确的时间出现在正确的位置”。这就引出了存储层次问题:越靠近计算单元、访问越快的存储,容量越小、单位成本越高;越远离计算单元、容量越大的存储,访问延迟越长、带宽越受限。理解片上RAM/ROM、寄存器、UltraRAM、外部SRAM/DRAM/Flash各自的位置与角色,是后续做缓存与带宽优化的前提。

一、从寄存器到外部存储:一条完整的存储谱系

在Xilinx 7系列及UltraScale/UltraScale+器件中,典型的存储资源可以按“速度—容量—灵活性”排成一条谱系:

  • 寄存器(Flip-Flop/Latch):位于CLB内部,单周期可达,容量以“位”计,适合存放流水线中间结果、状态机状态、少量控制字。它是最快的存储,但数量有限,不能用来缓存大块数据。
  • 分布式RAM(Distributed RAM):用LUT拼成的小容量RAM,深度通常几十到几百,适合小FIFO、查找表、系数表。它灵活但容量小,占用LUT会挤占逻辑资源。
  • 块RAM(Block RAM,BRAM):专用双端口存储块,7系列每块36Kb,UltraScale每块36Kb并可配置为两个18Kb。BRAM是星载FPGA最常用的片上缓存,适合行缓存、乒乓缓冲、跨时钟域FIFO。
  • UltraRAM(URAM):UltraScale+器件特有,每块288Kb,容量远大于BRAM,但端口和配置灵活性略低,适合大容量、规则访问的缓存,如整帧图像缓存、大块矩阵暂存。
  • 外部SRAM/DRAM/Flash:片外存储。SRAM接口简单、随机访问快,但容量小、成本高;DRAM容量大、单位成本低,但需要刷新和时序控制,访问延迟高;Flash非易失,适合存放配置比特流、程序代码和标定参数,写入慢、擦除按块。

这条谱系的核心规律是:越靠近计算,越快越小;越远离计算,越慢越大。缓存设计的目标,就是让高频访问的数据尽量停留在靠近计算的一侧,而把低频、大块的数据放到远端。

FPGA存储层次:速度—容量—距离关系 访问速度 / 单位成本 容量 / 访问延迟 寄存器 / Latch CLB内部 · 单周期 · 位级容量 · 流水线中间值、状态机状态 最快 分布式RAM(LUT RAM) LUT拼装 · 小容量 · 小FIFO、系数表、查找表 快 块RAM(BRAM) 36Kb/块 · 双端口 · 行缓存、乒乓缓冲、跨时钟域FIFO 中 UltraRAM(URAM) 288Kb/块 · UltraScale+ · 整帧图像、大块矩阵暂存 较大 外部存储:SRAM / DRAM / Flash SRAM:接口简单、随机访问快、容量小、成本高 DRAM:容量大、单位成本低、需刷新、延迟高 Flash:非易失、存比特流/代码/标定参数、写慢擦除按块 最大 计算 单元 高频数据向计算侧靠拢,低频大块数据向远端下沉

二、缓存命中与缺失:为什么“放对位置”比“放得多”更重要

缓存的基本假设是局部性原理:程序在一段时间内倾向于重复访问同一批数据(时间局部性),也倾向于访问相邻地址的数据(空间局部性)。当计算单元请求的数据已经在快速存储中,称为命中(Hit);不在,则称为缺失(Miss)。缺失时,必须从更慢的下一级存储把数据搬上来,这个搬运过程会带来额外延迟,甚至阻塞流水线。

在星载FPGA中,缓存命中率直接决定有效带宽。举例来说,假设某图像处理模块需要按行读取一帧4096×4096、16bit的图像,若每行都从外部DRAM读取,则每行需要一次突发传输,行间切换带来行激活与预充电开销;若在片内用BRAM做行缓存,把当前行和下一行暂存,则连续像素访问几乎全部命中BRAM,外部DRAM只在换行时访问一次。两种方式的平均访问延迟可能相差数倍。

衡量缓存效果常用三个指标:命中率(命中次数/总访问次数)、缺失代价(一次缺失需要多少周期补齐)、平均访问时间。平均访问时间可近似写成:

平均访问时间 = 命中时间 + 缺失率 × 缺失代价

示例(假设值):
  命中时间   = 2 周期(BRAM)
  缺失代价   = 40 周期(外部DRAM突发+同步)
  命中率     = 95%
  缺失率     = 5%
  平均访问时间 = 2 + 0.05 × 40 = 4 周期

若命中率降到 80%:
  平均访问时间 = 2 + 0.20 × 40 = 10 周期

可以看到,命中率从95%降到80%,平均访问时间从4周期涨到10周期,有效带宽下降超过一半。这说明缓存优化的重点不是“把容量做大”,而是“把高频访问的数据留在快侧”。

三、星载场景下的实际取舍

星载环境对存储选择有额外约束:辐射总剂量、单粒子翻转(SEU)、功耗与散热、体积与重量。BRAM和URAM是片内资源,抗辐照设计主要依赖三模冗余、EDAC和擦洗;外部DRAM容量大,但需要关注SEU导致的位翻转,通常配合ECC使用;Flash用于配置和参数存储,需考虑擦写寿命与坏块管理。

一个典型的工程取舍是:用BRAM做行缓存和FIFO,用URAM做大块图像或矩阵暂存,用外部DRAM做整帧或长时间序列存储,用Flash存配置与标定表。寄存器只承担流水线和控制,不承担数据缓存。这样分层之后,每一级存储都只做自己最擅长的事,整体带宽和延迟才能同时满足。

判断缓存是否合理的三个问题:
  • 高频访问的数据是否已经放在BRAM/URAM中,而不是每次都去外部DRAM?
  • 缺失发生时,补齐路径是否足够短,是否会和其它访问争抢同一端口或同一总线?
  • 缓存容量是否与数据块大小匹配,是否出现“缓存太小导致频繁换入换出”的抖动?

理解存储层次与缓存命中/缺失,是后续做带宽预算、乒乓缓冲设计、跨时钟域FIFO深度计算的基础。只有先看清数据“住在哪里、走哪条路、要等多久”,才能谈优化。