3、FPGA内存控制器基础:内存控制器核心功能、SDRAM/DDR时序基础、FPGA内部Block RAM与外部DRAM对比
各位同学,今天我们聊聊内存控制器。说实话,这是FPGA设计里最容易出bug的地方之一。我见过太多工程师在仿真里跑得欢,一上板子就死机,最后发现是内存时序没配好。嗯,咱们今天就把这块硬骨头啃下来。
3.1 内存控制器的核心功能
内存控制器说白了就是个翻译官。它把FPGA内部乱七八糟的读写请求,翻译成SDRAM或DDR芯片能听懂的命令。我个人习惯把它的功能拆成三块:
- 命令调度:决定什么时候发ACT、什么时候发READ/WRITE、什么时候发PRECHARGE
- 地址映射:把逻辑地址转换成行地址+列地址+Bank地址
- 数据通路:处理读写数据的对齐、缓冲和校验
你想想看,如果这三个环节任何一个出问题,内存就罢工了。我在项目中遇到过最坑的一次,就是地址映射算错了Bank位,结果连续读写时总是莫名其妙丢数据。查了三天,最后发现是地址线接反了两位。
核心要点:内存控制器的本质是状态机。它必须严格遵守SDRAM/DDR芯片的时序规范,不能快也不能慢。
3.2 SDRAM/DDR时序基础
SDRAM的时序,说白了就是一堆延迟参数。我刚开始学的时候也被这些参数搞晕过,什么tRCD、tRP、tRAS,记都记不住。后来我总结了一个方法:你只要记住三个关键动作就行。
3.2.1 三个关键时序参数
| 参数 | 全称 | 含义 | 典型值(DDR3-1600) |
|---|---|---|---|
| tRCD | RAS to CAS Delay | 行激活后到列选通的时间 | 13.75ns(11个时钟周期) |
| tRP | Row Precharge Time | 预充电时间,关闭当前行 | 13.75ns(11个时钟周期) |
| tRAS | Row Active Time | 行必须保持激活的最短时间 | 35ns(28个时钟周期) |
为什么会这样?因为DRAM内部是电容存储,读一次数据就会破坏电荷,必须刷新。你想想看,如果tRCD设得太短,行还没激活你就去读,读出来的数据肯定是错的。我曾经在调试一块DDR3板子时,把tRCD设成了10个周期,结果读写测试通过率只有60%。后来改成11个周期,立马100%通过。
个人经验:实际项目中,我建议把时序参数设得比数据手册推荐值略大一点。比如手册说tRCD最小11个周期,你就设12个。多一个周期不会影响性能,但能大大提升稳定性。
3.2.2 DDR与SDRAM的区别
DDR和普通SDRAM最大的区别,就是DDR在时钟的上升沿和下降沿都传输数据。说白了,同样的时钟频率,DDR的带宽翻倍。但代价是什么?时序更复杂了。
- DQS信号:DDR引入了数据选通信号DQS,用来对齐数据。SDRAM没有这个
- 写均衡:DDR3以上需要写均衡训练,补偿PCB走线延迟差异
- ODT:片上端接电阻,减少信号反射。SDRAM不需要
我记得第一次调DDR3的时候,DQS和DQ的相位关系搞反了,结果数据全是乱的。后来用示波器一看,DQS的边沿正好在DQ数据的中间才对。嗯,这个坑我替你们踩过了。
3.3 FPGA内部Block RAM与外部DRAM对比
很多初学者会问:FPGA内部不是有Block RAM吗?为什么还要用外部DRAM?这个问题问得好。咱们来做个对比。
3.3.1 容量与速度
| 特性 | Block RAM | 外部DRAM |
|---|---|---|
| 典型容量 | 几Mb到几十Mb | 几百Mb到几十Gb |
| 访问速度 | 几百MHz,固定延迟 | 取决于时序,延迟不确定 |
| 带宽 | 高,每个时钟都能读写 | 高,但有刷新开销 |
| 功耗 | 低 | 高 |
你想想看,如果你的设计只需要存几万个数据,Block RAM完全够用。但如果你要做视频缓存、网络数据包缓冲,那必须上外部DRAM。我做过一个4K视频处理的项目,一帧图像就要几十Mb,Block RAM根本塞不下。
3.3.2 使用场景选择
我个人习惯这样选:
- 用Block RAM的场景:FIFO、小容量查找表、寄存器文件、配置参数存储
- 用外部DRAM的场景:大容量数据缓冲、图像帧缓存、网络包缓存、操作系统内存
避坑指南:千万不要在Block RAM里存大量连续数据。我曾经有个项目,用Block RAM做了个256K深度的FIFO,结果一个芯片的BRAM全用光了,逻辑资源反而空着。后来改成外部DRAM,成本降了一半。
3.3.3 延迟对比
Block RAM的延迟是确定的,一般1-2个时钟周期就能读出数据。外部DRAM呢?从发出读命令到数据回来,最少也要十几个周期。如果遇到行冲突,还要先预充电再激活,延迟可能到几十个周期。
为什么会这样?因为DRAM内部是二维阵列,每次读写都要先激活行,再选通列。如果连续访问同一行,延迟就小;如果随机访问不同行,延迟就大。Block RAM是SRAM结构,没有这个限制。
嗯,这里要注意:如果你的设计对延迟敏感,比如CPU的缓存,那必须用Block RAM。如果只是做数据缓冲,延迟大一点没关系,用外部DRAM更划算。
3.4 本章知识体系
下面这张图总结了本章的核心内容。我习惯用这种结构图来理清思路,你们也可以试试。
这张图把本章的三个核心内容串起来了。左边是内存控制器的功能,中间是时序参数,右边是BRAM和DRAM的对比。底部是我总结的四条设计要点,你们做项目时可以对照着检查。
个人建议:刚开始学内存控制器时,别急着上DDR4。先拿SDRAM练手,把tRCD、tRP这些参数调明白了,再上DDR。我当年就是从SDRAM起步的,踩的坑少很多。
好了,这一章的内容就到这里。内存控制器这块,说白了就是时序和状态机。你只要把时序图画清楚,状态机写严谨,基本不会出大问题。下一章咱们会深入讲DDR控制器的具体实现,到时候我会带你们手写一个简单的DDR控制器。
公众号:蓝海资料掘金营,微信deep3321