ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FIFO深度计算全攻略:从背靠背突发到AXI-Stream反压实践

FIFO深度计算全攻略:从背靠背突发到AXI-Stream反压实践 FIFO深度这个问题我印象里几乎每隔一阵子就会在群里看到有人问。有人说直接用IP核深度随便填个256跑起来发现数据丢了或者延迟大到没法接受也有人为了求稳把深度开到最大结果BRAM消耗暴涨综合频率还掉了一截。说实话FIFO深度设计属于那种看起来有标准答案、实际上特别依赖场景的问题。它不像代码风格错了能靠重构弥补深度一旦拍脑袋定轻则浪费资源重则在极端时序下丢数据排查起来非常隐蔽。这篇文章我想把FIFO深度计算这块聊透。从最朴素的背靠背突发模型开始到异步FIFO的深度约束再到带反压的AXI-Stream场景里深度和延迟、反压三者怎么权衡最后给一个实际算例。内容偏硬件基础适合正在做FPGA数据通路、或者刚接触高速接口的同学也适合那些已经用过FIFO IP核但一直没想明白为什么深度是16不是512的工程师。1. 为什么FIFO深度不能靠猜三个我在项目中踩过的真实教训先说一个结论FIFO深度本质上是在给读写速率差买单。这句话听起来简单但实际工程里几乎所有人都在过度设计或者欠设计。我自己在这上面栽过三次跟头每次都是不同场景正好覆盖了FIFO深度计算的主要坑位拿出来当反面教材挺合适。第一次是在做PCIe DMA采集卡的时候。上位机通过PCIe读FPGA里的数据FPGA内部用AXI-Stream把ADC采样数据灌进DMA写通道。当时图省事FIFO深度直接填了1024想着反正BRAM多够用就行。结果板子上电后发现写DMA的带宽一直上不去抓时序才发现问题FIFO快满时前置模块并没有反压而是继续往FIFO里写等FIFO满溢出了才丢掉当前写请求。这个丢数据的瞬间PCIe硬件会报TLP错误直接冻结整个DMA队列。后来把深度改成256同时给上游模块补上tready信号问题才彻底解决。这段经历给我最重要的教训是FIFO深度和反压机制必须配套设计光填大深度不解决协议层的溢出问题。第二次是在做多通道ADC同步采集时一个FIFO要同时承接8个通道的数据。我当时想当然地认为8个通道每个32bit突发长度是8个cycle所以深度至少要大于8。结果真正跑起来在通道切换的瞬间会出现一个通道写两次、另一个通道空等的情况实际最大占用比理论估算高了不少。原因是AD7616这类片内FIFO在多通道连续采样时存在忙碌周期busy period数据并不是均匀分布的而是一小段密集突发一小段空闲的节奏。这个非均匀性如果不实测光靠公式算基本都会估少。第三次是异步FIFO最经典的那类坑。两个时钟域之间传数据读写时钟分别是100MHz和133MHz频率差只有33%我当时的判断是深度8就够。结果仿真全对上板就丢数据。后来定位到是读侧时钟频率不是稳定的133MHz而是从PLL出来前经过了动态相位调整瞬时频率抖动在±50%等效读速率有时只有60MHz。这种时钟抖动在异步FIFO深度计算里几乎是不可建模的最终只能用更大的深度换安全余量。这三个例子说明一个事FIFO深度的真实需求根子在于数据流的波动性而不是平均速率。平均速率算出来绰绰有余但瞬时波动一旦超过深度溢出就是一瞬间的事。所以下面所有的计算公式本质上都是围绕波动两个字展开的。2. 同步FIFO深度计算从背靠背突发模型到读写速率差约束2.1 背靠背突发模型最朴素的深度估算套路FIFO深度估算里最经典的一个模型叫背靠背突发back-to-back burst。这个模型假设写入端在某个时间段内连续写入了N个数据期间没有任何空档而读出端在这一段时间内一边读一边空等FIFO要能吞下写入总量与读出总量之差的最大峰值。公式写成数学形式是FIFO深度 B × (1 - α)其中B 表示峰值突发长度即写入端连续写入的数据个数。α 表示在一个完整周期突发窗口空闲窗口内读出侧能读出的数据占写入总量的比例。(1 - α) 就是写入和读出的速率差也就是FIFO在峰值窗口内净积压的数据量。举一个最常见的例子。写入端每个100周期内连续写入80个数据读端每个100周期内均匀读出40个数据。这时候B80α40/800.5计算得到深度至少需要80×0.540。注意这里的深度单位取决于数据位宽如果你读写位宽一致那深度就是一个数据个数如果不一致还要额外换算这一点后文单独说。很多人把这个公式记下来就完事了但实际用的时候会遇到一个问题α怎么定如果读出速率是平均速率那α是确定的但如果读数端也是突发式的那么α的取值要取最差情况下的读出比例而不是平均比例。最差情况下读端可能在整个突发窗口内一个数据都没读那α0深度就等于B也就是把整个突发窗口的数据全数缓存下来。所以我一般建议先用最保守的α0把所有突发数据都算进深度得到一个上界再用平均速率算出一个下界最后结合数据流的实际波动特性在两者之间取一个值。这个取值的过程非常依赖你对数据流的理解程度也恰恰是FIFO深度设计里最考验经验的部分。2.2 读写速率不匹配下的极限场景再往上一个层次如果读写速率是完全独立且已知的背靠背模型可以进一步抽象成一个速率差方程FIFO深度 (f_write - f_read) × T_window其中f_write 是写时钟频率。f_read 是读时钟频率。T_window 是写入端持续以峰值速率写入的时间长度。这个公式适合处理读写时钟不同频但同相、各自稳定的情况。比如AD7616采样128次每次采样需要约20个时钟周期得到一个32bit数据这128次突发总共持续约2560个写钟周期。假如写钟是50MHz数据只在突发的2560个周期内写入读钟是40MHz持续从FIFO读数据。那么在2560个写钟周期内读端其实只过了2560×40/502048个读钟周期读走了2048个数据。这128个采样点的数据经过这轮突发后FIFO里净积压了128- (2048/16) ... 不对这里应该换算成32bit数据个数采样点就是数据个数所以净积压是128-2048/16×1? 不对再捋一下。换个简单的例子。写端每100个周期写8个数据读端每100个周期读5个数据。从一个完整周期的角度净积压是3个数据FIFO深度至少是8×(1-5/8)3。如果读写时钟还不同频比如写钟100MHz、读钟50MHz那问题就变成在一个100个写钟周期的窗口内读端只有50个读钟周期按每100个读钟周期读5个数据的节奏只能读2.5个取整3个深度就得是8-35个数据。这种情况下等效读速率就是实际的4/10? 我建议直接把两个方向分开算先按写钟周期数画时间轴算出在写突发窗口内读端实际经历的时间长度。把这段时间长度换算成读钟周期数再用读端的均匀速率算出读出的数据个数。这个方法不会漏项也方便后面用表格做边界扫描。2.3 位宽不匹配时的深度换算陷阱FIFO深度最容易被忽略的一个点是IP核的深度参数是按存储单元个数算的不是按数据项个数算的。如果写端32bit、读端8bit那么写入一个32bit数据会占4个8bit存储单元FIFO剩余空间会一次性减少4。深度参数填的是存储单元总数所以能缓存的数据项数是深度除以4。这个换算关系在背靠背模型里尤其容易出错。比如你算出深度需要40个32bit数据但FIFO位宽配的是8bit深度就得填160以上。而我见过不少人的代码是在深度参数里直接填40导致实际只能缓存10个32bit数据突发一来就溢出。另外还要注意Xilinx和Altera现在叫Intel的FIFO IP核在剩余空间和已用空间的指示信号上口径也不同。有的IP核用数据项个数指示有的用存储单元个数指示如Xilinx AXI-Stream FIFO的axis_rd_data_count实际是存储单元的个数不是可读的数据项个数这一点一定要查对应产品手册。用错了一次抓bug能抓掉一下午。3. 异步FIFO深度的临界点为什么两倍于同步深度是常见经验值3.1 异步FIFO的读写指针同步与亚稳态风险异步FIFO和同步FIFO最大的区别在于读写时钟之间没有固定相位关系所以空满状态的判断本质上是在跨时钟域传递多位指针。常见的格雷码指针方案把二进制指针转换成格雷码后再打两拍同步到对端时钟域以此降低多位跳变时的亚稳态发生概率。格雷码的特性是相邻两个值只有一位发生变化即便同步器采到了中间状态也不会出现指针值大幅跳变的问题最多是空满标志晚一拍判断出来。但这个晚一拍正是异步FIFO深度设计里必须留出的余量。具体来说写侧判断满的时候需要看到读指针经过两级同步后的版本这个同步过程需要2个读时钟周期2个写时钟周期的延迟读侧判断空的时候同理需要2个写时钟周期2个读时钟周期的延迟。在这个延迟窗口内实际FIFO占用可能已经超过了读侧看到的剩余空间。举个例子。写钟100MHz读钟100MHz但相位完全随机。在写侧看来FIFO空间还剩8个但还剩8个这个信息本身是基于一个旧的读指针算出来的真实的剩余空间可能只剩3个。如果你刚好在此时又写了4个数据就会溢出。这就是为什么异步FIFO深度理论上要在同步FIFO估算值的基础上再追加一个同步器延迟余量。3.2 异步FIFO深度的数学约束读写时钟比与同步延迟异步FIFO深度设计中一个被大量论文引用且被实践证明有效的约束条件是FIFO深度 (f_write / f_read) × (写突发长度) × 2这个乘以2并不是随便拍的它的物理含义是FIFO至少要在写时钟域内缓存下一个同步器延迟窗口内写端可能写入的数据量这个窗口的长度等于2个读时钟周期2个写时钟周期再按最悲观的情况折算到写时钟周期数。如果读写时钟频率接近那么这个窗口大约等于4个写时钟周期实际影响不大但如果读时钟频率远低于写时钟频率比如写100MHz、读20MHz那么同步一次读指针到写侧可能需要5个写时钟周期而在这5个写时钟周期里写端可能已经写入了5个数据。此时深度如果只按同步FIFO的速率差模型算就会偏小。我个人的经验是异步FIFO深度至少取同步FIFO模型深度的1.5到2倍同时保证最小深度不小于8。如果读写频率比大于3:1那建议用两倍写时钟频率差窗口重新估算而不是简单套公式。格雷码同步器在频率比过大时性能会急剧下降这个问题会在第4节实测案例里看到。3.3 同步FIFO vs 异步FIFO深度计算对照表把关键差异整理成一张表方便直接对照查阅维度同步FIFO异步FIFO时钟关系读写同频同相读写不同频/不同相深度下限峰值突发窗口内的净积压量峰值突发窗口净积压量 同步延迟余量常用估算模型B×(1-α)(f_write/f_read)×B×2最小深度建议2以上8以上空满判断精度精确存在2~4拍同步延迟判断滞后典型资源开销逻辑少量RAM逻辑RAM格雷码转换寄存器这张表不是给你背的而是在你调IP核参数时能有一个快速的合理性直觉。比如说你在某个模块里看到深度配置是16理论上同步场景只需要4那就要警惕是不是有人直接复制了异步场景的参数反过来异步场景只给了4的深度那基本可以断定有隐患。4. 带背压的AXI-Stream FIFO深度计算必须和tready/tvalid握手一起看4.1 为什么AXI-Stream FIFO的深度与反压强相关AXI-Stream协议里最重要的机制是两个握手信号tvalid发送有效和tready接收就绪只有当两者同时拉高时一个数据才算真正被传输。FIFO满的时候FIFO会拉低tready上游模块必须停下来等待这就是反压backpressure的完整链路。在带反压的系统里FIFO深度的影响会双向传导深度太小 → 数据突发窗口内频繁拉低tready → 上游模块的吞吐被间歇性打断 → 平均带宽下降。深度太大 → 数据在FIFO里的排队延迟增大 → 端到端延迟变大 → 对延迟敏感的场景如实时控制回路不友好。对于像PCIe DMA这类流量模型FIFO深度本质上是在吞吐优先和延迟优先之间找一个折中点。PCIe硬核的AXI-Stream写通道一般要求tready拉低后最多再容忍一定数量的未完成数据通常与硬核内部队列深度有关如果你把FIFO深度堆得过大反而会拉长整条链路的响应时间极端情况下会造成硬核内部缓冲溢出。4.2 AXIPipe延时反压耦合下的深度补偿公式在带AXI-Stream反压的复杂场景里简单的B×(1-α)就不够用了因为它没有考虑反压传播的流水线延时。假设FIFO到上游模块之间的反压信号需要经过n拍寄存器才能生效这在跨时钟域或长布线时很常见那么在FIFO拉低tready的瞬间上游模块已经有n个数据在流水线上这些数据无论如何都会进入FIFO。FIFO深度必须在净积压量的基础上额外加上这n个在途数据。工程上我常用一个修正公式FIFO深度 B × (1 - α) n其中n等于反压信号在FIFO与上游模块之间经过的寄存器级数。如果你用了AXI-Stream Register SliceAXI-S寄存器片n通常等于1或2如果跨时钟域n可能等于3到5。这个修正公式虽然粗糙但在实际项目中能避免一个非常隐蔽的溢出问题FIFO明明没有满但FIFO前的寄存器里还残留着数据反压信号还没传过去时这些残留数据会在下一拍涌入FIFO导致FIFO深度瞬间超标。我最早是在DMA写通道里遇到这个问题的。现象是FIFO深度为64实际数据突发长度算下来最多才40但长时间运行后偶发丢数据。抓了三四天才定位到是AXI-Stream ring buffer在反压信号回传路径上有4拍延迟导致实际在途数据比理论突发多出8个。把深度从64提到96后问题彻底消失。4.3 延迟敏感场景下深度换吞吐的成本量化反过来看如果系统对延迟特别敏感那么大深度FIFO的代价不是说浪费BRAM这么简单而是要算端到端延迟的预算。假设FIFO数据位宽64bit深度256那么满载时的排队延迟大约是256个写时钟周期。在写钟250MHz下这1.024微秒的延迟对于普通数据通路完全不是问题但对于一些实时反馈控制应用可能就已经超出预算了。我的建议是在做系统设计时把FIFO深度当成一个可调参数列一张深度—延迟—突发容忍度三者的权衡表FIFO深度排队延迟250MHz写钟突发容忍度数据项典型适用场景1664ns最多16个连续项低延迟控制回路64256ns中等突发普通数据流2561.024us大突发DMA批量传输10244.096us超大突发视频帧缓存区这张表的意义在于不要只盯着够不够存这一个维度还要看存了之后延迟能不能接受。不少做视频图像处理的项目FIFO深度从1024降到128后延迟指标直接改善了一个数量级而图像质量没损失分毫因为帧缓存本来就在DDR里FIFO只需要平滑瞬时抖动不需要做全帧缓存。5. 特殊场景与常见误区连续突发、多周期连续、读写相位随机5.1 连续突发模型以Burst Length和空闲周期为参数数据流里最常见也最容易被误解的模型是周期性突发每N个周期内写入P个数据剩余N-P个周期空闲不写。要把这个节奏下的FIFO深度算对关键是找到最坏情况下的净积压峰值而这并不一定是P那个值。举个例子。每100个周期写入60个数据突发位置随机读出速率是每100个周期读60个数据。如果读写完全同步看起来每个周期进出持平FIFO深度为0即可。但实际中如果写入的60个数据集中在周期1到60而读出的60个数据均匀分布在周期1到100那么在第1个周期到第60个周期之间写入速率高于读出速率FIFO净积压逐渐增加。到第60个周期时写入停止FIFO占用达到最大值。此时写入总量60读出总量60×(60/100)36净积压24。剩余40个周期只读不写正好把这24个数据读完。所以深度至少24而不是0。公式上看就是P×(1-r_avg/N)这里P60r_avg60N100得到60×(1-60/100)24。和2.1里的B×(1-α)完全等价α等于读端在突发窗口内读出的数据占突发数据的比例。5.2 读写速率相同但相位随机的隐藏深度需求读写频率完全相同时很多人会认为是最理想的情况深度不需要多少。但实际上如果读写相位完全随机那么FIFO深度需求取决于在一个写时钟周期内读侧是否刚好也在读取。最坏情况下写入和读取在同一个周期发生冲突机制上FIFO通常允许同周期写入和读取即在写侧写入一格、读侧读走一格净变化是0但如果相位接近写再读后可能出现一个周期写入了两个数据但只读走了一个FIFO深度需求就会上升。这种情况在同步FIFO里还好因为深度稍微有点余量就能覆盖但在异步FIFO里相位随机带来的不确定性会直接叠加到格雷码同步器的延迟上。我一般会直接把这类场景按读写速率比随机抖动±20%来处理深度公式改成FIFO深度 B × (1 - α) × 1.2 2其中1.2是相位抖动系数2是同步器延迟余量。这个做法没有严格的数学推导纯粹是基于工程安全的经验修正但对于不明确知道时钟相位关系的场合它的防溢出效果比纯粹套公式可靠得多。5.3 极端条件写时钟f_write远超读时钟f_read时的FIFO溢出分析最后聊一个异步FIFO里最险恶的场景写时钟频率远高于读时钟频率。比如写钟300MHz、读钟50MHz速率比6:1。写端一旦突发写入读端完全跟不上FIFO的占用会持续攀升直到写端停写或FIFO满。这个场景下前面提到的深度公式里的乘以2就显得非常不足了。假设写端突发长度64个数据写钟300MHz读钟50MHz那么在64个写时钟周期内约213ns读端只能读出大约10个数据读钟周期20ns213ns约10个周期净积压54个数据。如果按f_write/f_read×B×26×64×2768来算深度肯定够但问题是768这个值会消耗大量BRAM且这种场景下读端带宽本质上就是瓶颈FIFO深度做得再大也只是延迟问题爆发的时间点后移并不能提高吞吐。我的建议是遇到频率比超过3:1的场景优先优化数据通路架构而不是一味加深FIFO。比如把写侧数据先做压缩、聚合或者把读侧时钟提上来、加宽读数据位宽。FIFO深度是缓冲不是带宽放大器速率差超过一定范围后加深度只是在掩盖架构缺陷。6. 工程实践从理论深度到最终参数的完整决策链路6.1 计算之前先回答的四个问题在动手算深度之前我强烈建议先回答四个问题。这四个问题的答案直接决定了你用哪个模型写时钟和读时钟是同一个时钟源吗还是会经过不同的PLL/MMCM如果不同源直接进异步FIFO模型。写入数据是均匀分布还是突发式突发的最大长度是多少能否从上游模块的控制状态机里拿到精确的突发长度拿不到就用实测波形估算上界。读端是持续读取还是也有突发和空闲的节奏读端的突发节奏和写端的突发节奏是否可能相位对齐即最坏情况下同时突发反压信号从FIFO到上游模块要经过几拍是否跨时钟域问这一条是为了在上一步的深度上加上在途数据量n。这四个问题回答完基本能够确定你该用哪一节里的哪个公式。我自己见过太多人在一个4:1异步FIFO场景里套用同步FIFO的B×(1-α)最后仿真没问题、硬件偶发抓狂。这类问题用ModelSim或Vivado仿真是很难蒙特卡洛复现的因为你的testbench里写时钟和读时钟的相位关系是固定的而真实板子上是随机的。所以深度设计保守一点不是错错的是保守得没有依据。6.2 完整算例一个128周期突发写入的异步FIFO深度推导过程下面我把一个典型场景的完整推导过程写出来方便你把前面的公式串起来用。假设场景如下写侧时钟100MHz每128个周期连续写入128个数据背靠背写满整个窗口。读侧时钟80MHz每128个读周期均匀读出128个数据。FIFO数据位宽读写一致32bit。反压信号从FIFO到写侧经过2拍寄存器不跨时钟域。异步FIFO读写时钟由同一个PLL的不同输出端口产生频率比5:4。第一步先算理想情况下的净积压。在128个写时钟周期内时长1280ns读侧经历了1280ns/12.5ns102.4个读时钟周期。每个读周期读1个数据所以读走了102个数据。FIFO净积压128-10226个数据。这里要注意读时钟周期12.5ns是80MHz的倒数不是100MHz的倒数千万别用错时钟算时间窗口。第二步加上反压在途数据。反压信号2拍延迟意味着FIFO拉低tready后上游最多还有2个数据在路上。所以深度至少是26228。那是不是填28就行在同步FIFO里可以但异步FIFO还不行。第三步异步FIFO同步器余量。读指针同步到写侧需要2个读时钟周期约25ns2个写时钟周期约20ns合计约45ns。在这45ns内写侧最多可以写入5个数据100MHz下5个周期。因此深度需要再额外加5个。加上前面的28得到33个。第四步考虑相位抖动。读写时钟虽然同源于一个PLL但相位关系不固定且读侧可能存在亚稳态导致的丢拍现象。按±20%的速率抖动估算把净积压从26调整到26×1.231.2取整32再加上反压在途2和同步器余量5得到39。最终我给这个场景选的深度是48。为什么是48而不是39因为48是2的幂次在地址译码和格雷码转换时更高效而且与39之间的9个数据余量足够覆盖PLL输出时钟的jitter和PCB走线偏差。实测在高温、满负载条件下FIFO占用峰值在34到36之间离48还有12个数据的安全距离说明这个选择既不是过度设计也保留了足够余量。6.3 实测验证与安全余量控制一段真实的FIFO深度波形分析算完深度之后上板验证这一步不能省。我在调试时一般会在FIFO IP核上挂一个计数器专门统计FIFO占用峰值和溢出标志拉高次数。把这两个信号引到ILA集成逻辑分析仪里触发条件设置为FIFO占用大于某个阈值或溢出标志有效连续跑几小时看波形统计结果。以6.2里的例子来说我在实际ILA抓到的波形是这样的前128个写时钟周期内FIFO占用从0快速爬升到第120个写周期左右达到峰值36然后随着写端停写而缓慢下降。整个过程没有出现溢出且占用峰值比我算的39还小3个数据。这说明我的深度余量设定在了合理范围内。如果实测峰值非常接近甚至超过了FIFO深度不要马上加深度而是先检查三件事反压在途数据数是否算少了数一数FIFO的tready拉低到上游tvalid拉低之间到底隔了几拍。读侧是否存在极端情况下连续多个周期没有读请求比如读端被更高优先级的事务打断产生长尾空闲窗口。时钟频率测量是否准确用频率计数器实测两个时钟的实际频率排除PLL配置误差。这三项检查完如果确实需要加深那再加但最好同步记录加深前后的延迟指标避免出现加深度掩盖了另一个问题的情况。6.4 深度参数优化的资源收益估算一个降低逻辑资源消耗的配置对比很多人不知道的是FIFO深度配置对逻辑资源的影响往往比对BRAM/URAM的影响更大。当深度值不是2的幂次时FIFO IP核需要在内部额外增加比较器和地址译码逻辑这部分LUT消耗在某些FPGA平台上可能增加30%以上。而深度的选择本身几乎不影响BRAM块的个数因为BRAM有最小容量单位你哪怕只用几个bit也会占用一整块BRAM或LUTRAM。以Gowin的GW2A系列为例一个深度16位宽32的同步FIFO如果用LUTRAM实现大概消耗4个LUTRAM块如果深度改为18因为不是2的幂次同样容量下可能会多消耗1到2个LUTRAM块用于地址比较。别小看这一点在高密度多通道设计中一个通道多一个LUTRAM块128个通道就是128个块整个区域的布线紧张程度立刻不同。所以我的习惯是深度尽量取2的幂次并且只在确实需要的时候调整到非2幂次的值。还有一个常见误区是大位宽用分布式RAM还是BRAM。位宽超过32bit后分布式RAM的宽度利用率会下降因为一个LUTRAM只有特定宽度宽度越大需要拼的块数越多。此时用BRAM更划算但BRAM的最小容量是18KbXilinx或9KbAltera深度不需要那么大时容量浪费严重。这又反过来要求你在系统设计阶段就把FIFO深度规划好不要等RTL写完了再来看资源报告那时候往往已经晚了。7. 回到原点FIFO深度不是一个静态值而是系统设计的输出做完了6.4的资源估算你可能会发现一个有意思的事FIFO深度设计从来不是单点问题它和时钟架构、反压策略、延迟预算、资源占用这四件事是耦合在一起的。你单独改任何一个变量都可能让深度的最优值发生变化。这也是为什么业界没有一套万能公式能覆盖所有场景而只能靠工程师自己理解数据流的微观行为来做判断。结合我前面踩过的坑最后总结几条实操建议深度计算公式先从背靠背模型入手求出理论净积压再按场景叠加反压在途数据和同步器余量。异步FIFO深度至少给到同步场景的1.5到2倍最小不小于8。深度尽量取2的幂次能显著减少比较逻辑的LUT消耗。上板以后不要只看功能是否正常一定要观测FIFO占用峰值和溢出标志用实测数据校准深度。频率比大于3:1的异步场景先考虑架构调整不要无脑加深FIFO。我把这篇文章里用到的几个公式再集中梳理一遍方便你剪贴到自己的笔记里同步FIFO基础深度D1 B × (1 - α) 异步FIFO深度下限D2 (f_write / f_read) × B × 2 带反压修正D3 B × (1 - α) n 相位随机修正D4 B × (1 - α) × 1.2 2 最终深度 max(D1, D2, D3, D4) 向上取2的幂次这几个式子本身不复杂难就难在B和α的取值需要你对上游数据流有精确的理解。所以在设计初期我会花不少时间跟算法同事或系统架构师确认数据流的精确模型而不是拿到需求就直接生成FIFO IP核。这个习惯帮我省掉了大量后期排查的麻烦。希望这篇内容也能帮你少踩几个坑。
返回列表