很多人觉得寄存器实现FIFO很简单,确实如此。用组合逻辑同时处理wr和rd信号,写和读可以在同一个时钟周期内完成,这是寄存器的天然优势。不存在访问冲突,因为每个数据位都有独立的触发器。
但这种方便是有代价的。当FIFO深度达到256、位宽32bit时,需要的寄存器资源是8192个触发器。在FPGA或者ASIC里这会吃掉大量逻辑资源,综合出来的布线延迟也会变长。所以寄存器方案只适合小规模场景,比如深度16以内、位宽不超过32的情况。
SRAM带来的麻烦
当容量需求上来了,就得考虑SRAM。这时候问题就来了:SRAM的读写是互斥的。
什么意思?假设上位机正在写数据,下位机同时发起读请求,硬件层面只能执行一个操作。这就是访问冲突。你必须设计一个仲裁机制,判断优先处理谁。
always @(*) begin if (wr_req && rd_req) begin // 冲突检测 case (arbitration_mode) WRITE_FIRST: grant = wr_req; READ_FIRST: grant = rd_req; endcase end end优先写还是优先读?这个决策直接影响系统性能。如果是视频流处理,读优先能保证显示连续性;如果是数据采集,写优先能避免数据丢失。没有绝对正确的答案,完全取决于你的应用场景。
仲裁带来的另一个问题是延迟不确定性。当冲突发生时,被仲裁掉的一方需要等待。
什么时候该上DDR
深度超过几千、位宽到64bit以上时,SRAM的片上资源已经不够用了。这时候只能选片外DDR。
DDR控制器的复杂度是另一个量级。你需要处理刷新周期、突发传输、地址映射这些问题。延迟从纳秒级变成了几十到上百纳秒。但没办法,容量需求摆在那里,技术选型就得服从现实。
实际项目中见过有人用DDR做视频缓存,结果带宽规划没做好,读写冲突导致画面撕裂。最后加了双buffer机制才解决。
回到开头的问题,选哪个?答案藏在你的需求里:
数据量小、速度要求高 → 寄存器,别犹豫
中等规模、能接受仲裁开销 → SRAM,记得做好冲突处理
大容量、延迟不敏感 → DDR,准备好啃控制器
芯片设计就是这样,没有完美方案,只有合适的取舍。技术选型看起来是工程问题,实际考验的是你对系统本质的理解深度。