异步 FIFO 最小深度计算方法及原理分析

计算 FIFO 深度是设计 FIFO 中常遇到的问题。常识告诉我们,当读速率慢于写速率时(瞬时速率),FIFO 便可被用作系统中的缓冲元件或队列。FIFO 的大小取决于读写数据的速率,系统的数据速率取决于系统的负载能力,因此为了保证系统性能,我们需要考虑 FIFO 传输的最坏情况。所谓最坏的情况就是使得写速率最大,读速率最小的时候考虑突发传输;


异步 FIFO 最小深度计算原理

IFO 用于缓冲块数据流,一般用在写快读慢突发传输的情况,遵循的规则如下: 

即是确保对FIFO写数据时不存在 Overflow 。

例1: 
A/D 采样率50MHz,DSP 读 A/D 的速率40MHz,要不丢失地将10万个采样数据送入 DSP,在 A/D 在和 DSP 之间至少设置多大容量的FIFO才行? 
100,000/50MHz=1/500s=2ms100,000/50MHz=1/500s=2ms 
(50MHz−40MHz)∗1/500=20k(50MHz−40MHz)∗1/500=20k,即是 FIFO 深度;


异步 FIFO 最小深度常用计算公式

这里假设读写 FIFO 是可以同时进行的, 
写时钟频率 w_clk, 
读时钟频率 r_clk, 
写时钟周期里,每 B 个时钟周期会有 A 个数据写入 FIFO, 
读时钟周期里,每 Y 个时钟周期会有 X 个数据读出 FIFO, 
则 FIFO 的最小深度的计算公式如下:

 

此公式可从上面原理推导而来;其中写入速率为w_clk,读出速率为(X/Y)*r_clk

例2: 
如果100个写时钟周期可以写入80个数据,10个读时钟可以读出8个数据。令w_clk=r_clk ,考虑背靠背 (20个clk不发数据+80clk发数据+80clk发数据+20个clk不发数据的200个clk) ,代入公式可计算 FIFO 的深度, 
fifo_depth = 160-160*80% = 160 - 128 = 32
如果令w_clk=200MHz,改为100个w_clk里写入40个,r_clk=100MHz,10个r_clk里读出8个,那么 FIFO 深度为48。计算如下, 
fifo_depth = 80 - 80 * 80% * (100/200) = 80 - 32 = 48

 注: 
 
两者相除自然就是这段时间读出的数据量。显然burst_length表示这段时间写入的数据量,两者的差为 FIFO 中残留的数据,这个也就是理论上的 FIFO 的最小深度;


读写 FIFO 不是同时进行的情况下

假如读写 FIFO 不是同时进行的,FIFO 深度就是写数据最大突发个数;


异步 FIFO 最小深度计算实例 

例3: 
如两个异步时钟域数据接口,假如读写是同时进行的,一般设置 FIFO 的深度就要对应两个时钟以及对应写最大的突发数据。假设写时钟频率是40MHz,读时钟为25MHz,在写端最大突发写数据个数为100个数据。对应深度计算:100(1-25/40)=37.5,对应深度设置至少为38;

假如读写不是同时的,这就需要设置深度为写数据最大突发个数,如上例中,对应最大突发个数为100个,则深度设置为100;

例4: 
一个8bit宽的异步 FIFO,输入时钟为100MHz,输出时钟为95MHz,设一个 frame 为4Kbit,且两个 frame 之间的发送间距足够大。求FIFO的最小深度? 
burst_length = 4K/8 = 4*1024/8 = 4096/8 = 512。 
因为X和Y的值没有给出,所以默认为1。 
fifo_depth = 512 - 512*(95/100) = 25.6 ,所以fifo_depth最小取值是26;


系统设计的问题——流量平衡

为了保证输入数据(负载)全部通过,输出吞吐量要大于输入吞吐量;但也不要太大,以免设计过剩。 
所以有, 
(r_clk∗X/Y)=(w_clk∗A/B)
(r_clk∗X/Y)=(w_clk∗A/B)

等式左边是系统设计吞吐量,右边是负载流量。
例5: 
两个异步时钟域数据接口,写时钟频率是19MHz,读时钟为20MHz,读写是同时进行的,输入数据不间断。求FIFO的最小深度? 
显然有, 
( r_clk * X/Y ) > ( w_clk * A/B ) 
故理论上FIFO的最小深度是1; 

### 异步FIFO最小深度计算 对于异步FIFO的设计而言,确保其能够无损传输数据至关重要。为了防止因读写速度差异而导致的数据丢失现象,在设计阶段需精确计算FIFO最小深度。 #### 基本原则 当异步FIFO两端的工作频率不同——具体表现为一端持续向另一端输入或提取信息时,则可能出现溢出或下溢的情况。为了避免这种情况发生,应使FIFO具备足够的存储空间来容纳可能产生的最大瞬态差额[^2]。 #### 计算公式推导 基于上述需求,可以得出用于估算所需缓冲区大小的一般表达式: \[ \frac{\text{FIFO Depth}}{(Write\ Rate - Read\ Rate)} > \frac{\text{Data Packet Size}}{\text{Write Rate}} \] 这里,“Packet Size”指的是待转移的数据总量;而右侧分母中的“Write Rate”,则表示单位时间内可完成的有效写入次数。左侧分子代表的是目标FIFO的实际容量,分母部分反映了净增长速率(即每秒新增加多少未处理的信息)。因此整个不等式的含义在于:即使是在最坏情况下,也应当让FIFO完全充满所需要的时间大于等于一次完整的数据包传递过程所耗用的时间长度[^3]。 #### 实际案例解析 假设存在如下条件: - 写入侧工作于100MHz频率; - 并非每次脉冲都会触发实际写动作,而是每隔五个周期中有四个会发生有效事件; - 对面接收方运行在80MHz上,并且几乎不会错过任何机会去尝试获取新到达的消息。 此时可以根据之前提到的原则来进行具体数值上的考量。由于并非每一个写请求都能成功执行,所以平均下来相当于有\( 100 MHz * (80/100)=80 Mbps\) 的真实流量进入队列等待被消费掉。考虑到对方同样维持着相同的带宽消耗水平,这意味着两者间并不存在明显的相对优势或者说差距为零。然而这并不意味着不需要额外的空间支持了,因为即便如此仍然存在着同步误差带来的潜在风险以及初始化瞬间可能会有的短暂失衡状态。为此建议保留一定比例的安全裕度作为预防措施的一部分[^5]。 综上所述,针对该特定场景下的最优解应该设置成能承载至少一个完整周期内所有可能发生的变化范围内的全部元素数量加上适当冗余量级即可满足稳定运作的要求。 ```python write_rate_effective = 100e6 * (80 / 100) # Effective write rate considering not all cycles are used for writing. read_rate = 80e6 # Full read rate as every cycle is utilized. # Since the effective rates match, we consider transient conditions and initial fill state. safety_margin = 1.2 # Adding a safety margin of 20% to account for synchronization issues or startup transients. initial_depth_for_one_cycle = int((write_rate_effective - read_rate) / write_rate_effective * safety_margin) print(f"The minimum depth should be at least {initial_depth_for_one_cycle} elements.") ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值