目录
一、问题背景
FIFO(先入先出队列)是硬件设计时很常用功能单元,但是RTL bug也经常由它引起。
由FIFO引起bug的原因有多种,主要原因还是没有搞懂为什么需要使用FIFO,本篇主要从根本出发讲解FIFO的作用。
二、FIFO用于消除电路不确定性(推荐)
一般而言,硬件设计出的电路都是确定的电路,但是一些特殊的情况下存在不确定性。例如下面的电路:
电路包含从DDR中读取数据,经过N级pipeline处理后写回到DDR。很明显,其中N级pipeline是确定的电路,但是从DDR读写是不确定的(一般latency可以在100~2000 cycle内浮动)。因此一旦DDR读写出现停滞,整个处理流水线将同步停滞,处理性能剧烈降低。
因此在DDR读写之间加入FIFO电路,FIFO中可以预存一些数据,使得DDR读写抖动时,内部pipeline依然可以工作。
三、FIFO用于斩断pipeline,调节时序(推荐)
上面的电路中,每级pipeline中都可以存储一个数据,每级pipeline往后传递必须保证后面的每一级pipeline均可以向后传递,例如pipelineN写后级的FIFO时受阻,这个受阻信号将层层传递至pipeline0,在N比较大时timing很难收敛。
因此可以在N级pipeline中添加FIFO,每级pipeline只需要保证其后到FIFO的链路畅通即可。
因为FIFO的afull/full信号是FIFO内部cunter产生,不会受FIFO后面的电路影响,达到了斩断流水线的效果。
四、FIFO用于简化pipeline反压设计(不推荐)
从二、三的图中可以看出,每级pipeline都可以反压前级,pipeline传递数据通过valid+ready进行,是一种非常稳定的交互方式。工程上为了开发方便,利用FIFO可以缓存数据的特性,采用单valid传递pipeline数据,认为后级ready一定为1,这种假设建立在后级FIFO缓存能力较大的基础上。一旦后级FIFO深度预留不够出现溢出,就会产生严重bug。
下图是例子展示,可以看出后级FIFO直接反压前级FIFO,中间的pipeline一定向后传递。如果后级FIFO反压前级时预留深度<N,N级pipeline中的数据因无法停止前进可能使后级FIFO溢出。
五、总结
FIFO是一种功能强大的电路,能够帮助我们解决许多问题。但是为了偷懒而利用FIFO的缓存特性往往导致隐藏bug,我们设计时还是应该对电路的行为有精确控制。