FIFO最小深度的计算
数据突发长度(burst length)
在讲解如何去计算FIFO深度之前,我们来理解一个术语burst length。要理解数据的突发长度,首先我们来考虑一种场景,假如模块A不间断的往FIFO中写数据,模块B同样不间断的从FIFO中读数据,不同的是模块A写数据的时钟频率要大于模块B读数据的时钟频率,那么在一段时间内总是有一些数据没来得及被读走,如果系统一直在工作,那么那些没有被读走的数据会越累积越多,那么FIFO的深度需要是无穷大的,因此只有在突发数据传输过程中讨论FIFO深度才是有意义的。也就是说我们一次传递一包数据完成后再去传递下一包数据,我们把一段时间内传递的数据个数称为burst length。
我们知道burst length过后,通过上述讨论我们大概就知道FIFO的最小深度与burst rate, burst size, read and write frequency等因素有关。要确定FIFO的深度,关键在于计算出在突发读写这段时间内有多少个数据没有被读走。也就是说FIFO的最小深度就等于没有被读走的数据个数。
何为FIFO深度
其实很惭愧,在这之前用FIFO都是直接用IP,因为应用场景很简单,因此FIFO深度的选择也比较随意,并没想很多。今天在网上看到一个异步FIFO深度计算的题目,发现对于这块并不熟悉,因此注意了下,下面写写自己的一些理解吧。提前说明下,因为我实际中并没有碰到需要去计算FIFO深度的场景,因此可能有些理解是错误的,希望各位大侠能批评指正。
首先,一定要理解清楚FIFO的应用场景,这个会直接关系到FIFO深度的计算,如果是面试官抛出的问题,那么有不清楚的地方,就应该进行询问。如果是笔试或者工程中需要计算FIFO深度的话,那么就需要自己考虑清楚。
其次,异步FIFO,读写时钟不同频,那么FIFO主要用于数据缓存,我们选择的FIFO深度应该能够保证在最极端的情况下,仍然不会溢出。因此考虑的前提一般都是写时钟频率大于读时钟频率,但是若写操作是连续的数据流,那么再大的FIFO都无法保证数据不溢出。因此可以认为这种情况下写数据的传输是“突发Burst”的,即写操作并不连续,设计者需要根据满标志控制或者自己来控制写操作的起止。
宏观地,从整个时间域上看,“写数据=读数据”,这个条件必须要满足,如果这个大条件不满足的话,用FIFO是没有效果的。但是在发送方"突发"发送数据的时间T内,是很有可能写数据>读数据的,因此FIFO的深度要能够保证,在这段时间T内,如果接收方未能将发送方发送的数据接收完毕的话,剩下的数据都是可以存储在FIFO内部而且不会溢出的,那么在发送方停止发送数据的"空闲时隙"内,接收方可以从容地接收剩下来的数据。
上面一段就是个人认为在FIFO深度计算中,最重要的部分了。接着来看一个例子,这是我看一个网友写时,是他当时遇到的一道笔试题。
一个8bit宽的AFIFO,输入时钟为100MHz,输出时钟为95MHz,设一个package为4Kbit,且两个package之间的发送间距足够大。问AFIFO的深度。
因为这位网友可能只是简述,因此信息并不完整,我的个人理解是这样的场景,一个异步FIFO,读写频率不同,读写位宽相同。发送发一次Burst突发的数据量为4Kbit,即500bytes,在两次Burst突发之间有足够的时间,因此我们只用考虑在发送方Burst发送数据的时间T内,如果接受方没法将数据全部接受,其余数据均可存在FIFO内且不溢出,那么在发送方停止Burst发送数据的时间段内,接收方就可以从容的从FIFO内读取数据。首先发送方Burst发送数据的时间段为 T = 500/100MHz,发送的数据量为 B_send = 500bytes,而在T这段时间内,接收方能够接受的数据量为B_rec = T*95MHz = 500 * 95 / 100 bytes = 475bytes,因此 B_remain = B_send - B_rec = 500 - 475 = 25 。那么FIFO的深度至少要大于等于25才行。
再看另外一个例子,还是从网上找到的,
写时钟频率w_clk,
读时钟频率r_clk,
写时钟周期里,每B个时钟周期会有A个数据写入FIFO
读时钟周期里,每Y个时钟周期会有X个数据读出FIFO
则,FIFO的最小深度是?
首先,我们可以认为写操作是Burst突发的。
其次,写操作的效率并不是100%的,而是A/B的,因此我们可以认为实际的F_wr = (A/B)*w_clk,同理,实际中F_rd = (X/Y)*r_clk。
另外,和第一个例子不同的是,这个题目里面并没有约束Burst突发的场景,在正常情况下,应该是这样的
空闲—Burst突发—空闲—Burst突发—空闲—Burst突发。但是我们在计算中,需要考虑最极端的情况,即
空闲—Burst突发—Burst突发—空闲—Burst突发—空闲。即传输过程中,可能会出现"背靠背"的情况,那么我们设计的FIFO深度必须能够保正,在"背靠背"的时间段内,如果接收方没法接受所有数据,那么剩余的数据可以被存储在FIFO内部且不会溢出。那么就可以开始计算了。假设"背靠背"时发送的数据 = BL,那么"背靠背"的时间 = BL / w_clk ,注意,这段时间内 F_wr = w_clk 而不是之前提到的
(A/B)*w_clk。在这段时间内,接收方可以接受的数据 = (BL / w_clk) * (X/Y)*r_clk ,
剩下的数据量 = BL - ( BL / w_clk ) * (X/Y)*r_clk,那么FIFO的深度至少就要为
" depth = BL - ( BL / w_clk ) * (X/Y)*r_clk "这样的深度了。
将上述公式变换下,得到 depth = BL - BL * (X/Y) * (r_clk/w_clk) 。这个公式就是网上流传的计算FIFO深度的公式,我想应该就是这个推理过程吧。
上述的讨论的一个前提就是FIFO的读写位宽一致,如果这个条件不满足的话,那么FIFO的深度的计算就更加复杂一些,但是我们还是可以把FIFO的读写位宽也折合成一定的因子,带入 实际的F_wr = (A/B)*w_clk 和 F_rd = (X/Y)*r_clk 中去,应该是是可以解决的。
FIFO深度计算
如果数据流连续不断则FIFO深度无论多少,只要读写时钟不同源同频则都会丢数;
FIFO用于缓冲块数据流,一般用在写快读慢时,
FIFO深度 / (写入速率 - 读出速率) = FIFO被填满时间 应大于 数据包传送时间= 数据量 / 写入速率
例:A/D采样率50MHz,dsp读A/D读的速率40MHz,要不丢失地将10万个采样数据送入DSP,在A/D在和DSP之间至少加多大容量(深度)的FIFO才行?
正解:
100,000 / 50MHz = 1/ 500 s = 2ms
(50MHz - 40MHz) * 1/500 = 20k既是FIFO深度。
一种错误的算法(我也犯了同样的错误):
100,000/40MHZ= 1/400s = 2.50ms
(50M - 400M)1/400 =25K.那么这样进去的数据就不是100K了,而是100K+50M(0.0025-0.002)=125,000bit,错误在时间的计算
异步FIFO设计注意事项
异步FIFO的设计与同步FIFO的设计具有很大差距;设计的时候需要考虑跨时钟域处理带来的问题;
1、FIFO的设计必须解决empty和full控制问题;
2、异步FIFO可以考虑把写Addr在写时钟域转换成gray码,然后通过读时钟来寄存器,转换到读时钟域中,解决empty标记信号;
3、异步FIFO可以考虑把读Addr在读时钟域转换成gray码,然后通过写时钟来寄存器,转换到写时钟域中,解决full标记信号;
4、使用gray码的原因在gray码可以把Addr值连续变化的规例(但是Addr的会有多个bit跳变)转换成gray码中只有1个bit跳变,这样在跨时钟域传输中不会出现异步采取出现很大差异(异步时钟采样会出现亚稳态现象),最多是原始Addr值加1或者减1,这样不会使得FIFO状态出现错误;
当fifo的尺寸很大时候。用gray code 变得不太合算。
因为要从binary变成gray,再变回来。
这个时候,要用异步handshake来把地址转到另一个
时钟域里面。简单的说用 request 和 ack。
但是在工程设计中还存在这样一种情形,只给出数据在一段时间内的读写速率,怎么读写完全随机,这种情况我们需要考虑最坏的一种情况避免数据丢失。在最坏的情形中,读写的速率应该相差最大,也就是说需要找出最大的写速率和最小的读速率。
假设:
写数据时钟频率fa=80MHz
读数据时钟频率fb=50MHz
在写时钟周期内,每100个周期就有40个数据写入FIFO
在读时钟周期内,每10个周期可以有8个数据读出FIFO
那么:
首先这里没有给出数据的突发长度,从假设中可以得出每100个周期就有40个数据写入FIFO,这里可能就有人会说突发长度就是40个数据,其实不是这样的,因为数据是随机写入FIFO的,我们需要考虑做坏的情形,即写速率最大的情形,只有如下图背靠背的情形才是写速率最高的情形,burst length为80
注意:这里需要验证一下是否有解,即写入burst数据时间必须大于等于读出burst数据时间,不然数据就会越累积越多,使得FIFO的深度必须为无穷大。首先写入80个数据需要的时间 = 1/80MHz * (80 * 100/40)=2500ns,读出80个数据需要的时间 = 1/50MHz * (80 * 10/8)=2000ns,由于写入burst数据时间大于对出burst数据时间,因此有解。
下面来计算FIFO最小深度,连续写入80个数据最快所需要时间 = 1/80MHz * 80 = 1000ns
从FIFO中读出一个数据至少所需时间 = (1/50MHz) * (10/8) = 25ns
那么在1000ns内能够读出的数据 = 1000ns/25ns = 40
在1000ns内没有读出的数据 = 80 - 40 = 40
因此FIFO的最小深度为40
总结
从上面分析来看,求FIFO的最小深度主要有以下要点:
在求解之前需要验证一下在允许的最大时间长度内写入的数据量是否等于读出的数据量,保证有解;
求FIFO深度需要考虑最坏的情形,读写的速率应该相差最大,也就是说需要找出最大的写速率和最小的读速率;
不管什么场景,要确定FIFO的深度,关键在于计算出在突发读写这段时间内有多少个数据没有被读走;
由于FIFO空满标志位的判断延迟,在实际应用中需要预留一些余量。
下面我们来推导一下FIFO深度的求解公式,假设:
写时钟频率为fwr
读时钟频率为frd
在写时钟周期内,每m个周期内就有n个数据写入FIFO
在读时钟周期内,每x个周期内可以有y个数据读出FIFO
那么:
首先必须满足(1/fwr) * (m/n) ≥ (1/frd) * (x/y)
背靠背的情形下是FIFO读写的最坏情形,burst长度 B = 2 * n
写完burst长度数据最快所需时间 T = (1/fwr) * B
从FIFO中读出一个数据至少需要时间 t= (1/frd) * (x/y)
在T时间内能够从都走的数据个数 = T/t = B * (frd/fwr) * (y/x)
在T时间内还没有读走的数据个数 = B-B * (frd/fwr) * (y/x)
因此FIFO的最小深度为 B-B * (frd/fwr)* (y/x)
注意保留一些余量
如果读时钟频率大于或等于写时钟频率,并且数据是连续传送的,即读数据比写数据要快,因此FIFO只起到过时钟域的作用,FIFO的最小深度为1即可。
————————————————
版权声明:本文为CSDN博主「崽象肚里能撑船」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44502896/article/details/106456724