FPGA存储三剑客:手把手教你玩转RAM、ROM和FIFO(附完整工程代码)
刚接触FPGA那会儿,我最头疼的就是存储资源。看着别人写的代码里,RAM、ROM、FIFO用得行云流水,自己却总在地址溢出、数据错位这些坑里打转。后来才明白,FPGA里的存储单元就像工具箱里的不同扳手,你得知道什么时候该用哪一把,用错了不仅费劲,还可能把活儿干砸了。
这篇文章,我想和你聊聊FPGA里最核心的三种存储结构:RAM、ROM和FIFO。我不会只给你讲枯燥的理论,而是会结合我实际项目里踩过的坑,用完整的工程代码,带你从零搭建一个能跑起来的存储系统。你会发现,一旦理解了它们各自的设计哲学和使用场景,很多复杂的时序和数据流问题,其实都有清晰的解决路径。
1. 理解核心:RAM、ROM与FIFO的本质区别
在开始写代码之前,我们必须先搞清楚这三者最根本的区别。很多初学者混淆它们,往往是因为只记住了“都是存数据的”,却忽略了它们访问数据的方式,而这恰恰决定了它们的应用场景。
简单来说,你可以把RAM想象成一个带编号的储物柜阵列。你知道每个柜子的编号(地址),可以随时往任何一个柜子里存东西(写),也可以随时从任何一个柜子里取东西(读)。存取哪个柜子,完全由你说了算,这就是“随机存取”。它非常适合存储那些需要频繁更新、且访问模式不固定的中间数据,比如图像处理中的像素缓存、通信协议中的状态变量。
ROM则更像一个已经印好的手册。里面的内容在“出厂”(综合实现)时就已经固定了,你只能读取,不能修改。它没有“写”这个操作。ROM通常用来存储系统启动代码、固定的系数表(比如滤波器的抽头系数)、或者字符点阵数据。在FPGA里,ROM通常由块RAM(Block RAM)资源初始化而成,或者用查找表(LUT)来实现小容量的分布式ROM。
FIFO(First In, First Out)是一种特殊的数据结构,它的行为模式是“排队”。数据从一端(写端口)依次进入,从另一端(读端口)按照进入的先后顺序依次离开。你不知道也不关心某个数据具体存放在哪个物理位置,你只关心队列的头和尾。FIFO天生就是为了解决数据缓冲和跨时钟域问题而生的。当生产数据的速度和消费数据的速度不一致时,FIFO就像一个蓄水池,平滑数据流。
为了让你更直观地看到区别,我整理了一个对比表格:
| 特性 | RAM (随机存取存储器) | ROM (只读存储器) | FIFO (先进先出队列) |
|---|---|---|---|
| 核心访问方式 | 随机存取(通过地址) | 随机读取(通过地址) | 顺序存取(无地址) |
| 写入能力 | 可读可写 | 只读,内容需预先初始化 | 顺序写入 |
| 关键控制信号 | 地址线(addr)、写使能(we)、读使能(re) |
地址线(addr)、读使能(re) |
写使能(wr_en)、读使能(rd_en)、空(empty)、满(full)标志 |
| 典型应用场景 | 数据缓存、查找表、状态机寄存器堆 | 存储固定系数、程序代码、字库 | 数据流缓冲、异步时钟域数据传递 |

642

被折叠的 条评论
为什么被折叠?



