1. FIFO基础概念:从零开始理解这个“数据缓冲器”

大家好,我是你们的芯片验证工程师老K。今天咱们聊聊FIFO——这个在SPI控制器里几乎无处不在的东西。

说实话,我刚入行那会儿,觉得FIFO不就是个先进先出的队列嘛,有啥好讲的?直到我在一个高速SPI项目里踩了坑,才发现这东西远没那么简单。嗯,咱们从头说起。

1.1 什么是FIFO?

FIFO,全称First In First Out,翻译过来就是“先进先出”。说白了,它就像一个排队买奶茶的队伍——谁先来,谁就先拿到奶茶。

在数字电路里,FIFO是一种数据缓冲器。它有两个端口:一个写数据进去,一个读数据出来。数据按照写入的顺序,依次被读出。就这么简单。

核心特征:

  • 数据顺序不变:先写进去的,一定先读出来
  • 读写可以不同步:写时钟和读时钟可以不一样
  • 有满/空标志:告诉你现在能不能写、能不能读

我个人习惯把FIFO想象成一个“水桶”。写数据就是往桶里倒水,读数据就是从桶里舀水。桶满了就不能再倒,桶空了就不能再舀。是不是很好理解?

1.2 FIFO在SPI控制器中的作用

你想想看,SPI通信的时候,主设备和从设备的速度可能不一样。主设备发数据很快,但从设备处理得慢,怎么办?

这时候FIFO就派上用场了。它就像一个“缓冲池”,暂时存放那些来不及处理的数据。

具体来说,FIFO在SPI控制器里干三件事:

  1. 速率匹配:CPU写数据到FIFO,SPI模块从FIFO读数据发送。CPU可以一次写很多数据,然后去干别的事,SPI慢慢发。反过来也一样,SPI接收的数据先存到FIFO,CPU有空了再来取。
  2. 减少中断频率:如果没有FIFO,每收发一个字节就要中断CPU一次。有了FIFO,可以攒到半满或快满时才中断一次。我在一个项目中,把中断频率从每字节一次降到了每16字节一次,CPU负载直接降了80%。
  3. 数据整型:SPI的数据位宽可能和CPU总线位宽不一样。比如SPI是8位,CPU是32位,FIFO可以帮你做位宽转换。

我的经验: 选FIFO深度时,别贪大也别太小。深度太大浪费面积,深度太小容易溢出。一般SPI应用,16~32深度就够用。我曾经在一个项目里用了64深度的FIFO,结果综合出来面积大了30%,性能却没提升多少——白费功夫。

1.3 同步FIFO vs 异步FIFO

这是面试常考题,也是实际项目中容易出问题的地方。咱们好好掰扯掰扯。

同步FIFO

同步FIFO,读写用的是同一个时钟。说白了,就是所有操作都在同一个时钟域里完成。

特点:

  • 实现简单:只需要一个时钟,控制逻辑也简单
  • 速度快:没有跨时钟域的延迟
  • 面积小:不需要同步器那些额外电路

适用场景: 当SPI控制器和CPU在同一个时钟域时,用同步FIFO就够了。比如一些低端MCU,CPU和SPI外设都跑同一个时钟。

异步FIFO

异步FIFO,读写可以用不同的时钟。写时钟和读时钟完全独立,各干各的。

特点:

  • 实现复杂:需要处理跨时钟域同步问题
  • 有延迟:因为要同步指针,空满判断会慢一拍
  • 面积大:需要格雷码转换、同步器、双端口RAM

适用场景: 当SPI控制器和CPU在不同时钟域时,必须用异步FIFO。比如SPI工作在100MHz,CPU总线只有50MHz,这时候就需要异步FIFO来桥接。

对比项 同步FIFO 异步FIFO
时钟 单时钟 双时钟(读写独立)
实现复杂度 低 高(需跨时钟域处理)
面积 小 大(约大30%~50%)
空满判断 即时 有延迟(1~2个时钟周期)
适用场景 同时钟域 跨时钟域

避坑指南: 我曾经在一个项目里,把异步FIFO的深度设成了2,结果因为同步延迟,空满标志总是慢半拍,导致数据溢出。后来我把深度改成了4,问题就解决了。记住:异步FIFO的深度至少要大于同步延迟的时钟周期数,否则会出问题。

1.4 一张图看懂FIFO在SPI中的位置

下面这张图,是我自己画的。它展示了FIFO在SPI控制器里的典型位置和作用。

SPI控制器中的FIFO架构 CPU / 总线 写指针 (写时钟域) FIFO 存储体 (双端口RAM) 数据0 数据1 数据2 ... 数据N 读指针 (读时钟域) SPI 接口 (SCK/MOSI/MISO) 写数据 读数据 满标志 / 空标志 数据流向:CPU → 写指针 → FIFO存储体 → 读指针 → SPI接口

从这张图可以看得很清楚:CPU把数据写到FIFO里,SPI接口从FIFO里读数据发出去。写指针和读指针各自独立工作,FIFO的满/空标志告诉两边什么时候该停、什么时候可以继续。

1.5 小结

好了,咱们把这一章的核心内容捋一捋:

  • FIFO 就是个先进先出的数据缓冲器,用来解决速度不匹配的问题
  • 在 SPI控制器 里,FIFO主要做速率匹配、减少中断、数据整型这三件事
  • 同步FIFO 简单、快、面积小,适合同时钟域
  • 异步FIFO 复杂、有延迟、面积大,但能跨时钟域工作

下一章咱们会深入FIFO的设计细节,包括深度怎么选、指针怎么设计、空满判断怎么做。到时候我会拿一个实际项目里的代码来讲解,保证干货满满。


可可精品资料库