异步fifo深度计算

621 阅读6分钟

异步FIFO通常用于在两个时钟域间传输数据,并且通常情况下,写数据的速率是要比读数据的速率快的,因此,就存在FIFO最小深度的一个问题,以防止在数据传输时发生溢出,造成数据的丢失。

在计算FIFO最小深度时,我们一般考虑极端情况,即在一段时间内写速率达到最大,此时由于读数据慢于写数据,因此需要设置一个FIFO的最小深度,来保证数据不丢失。

case1

写时钟频率80mhz,读时钟频率50mhz。 突发长度120 读写之间没有空闲周期,是连续读写一个突发长度。

分析:写一个数据花费时间1/80mhz = 12.5ns . 因此写120需要120x12.5ns。 而读一个数据需要1/50mhz = 50ns。所以在120x12.5ns内,读出120x12.5 /20 75个数据。

最小深度为120-75 = 45个。

计算异步FIFO的最小深度,首先必定是要了解清除应用场景的,这关乎到FIFO的最小深度的计算。FIFO主要是用于数据的缓存,用在读慢写快的场景下。异步FIFO读写不同频,我们选用的FIFO要能够在极端的情况下仍然能够保证数据的不溢出。因此,考虑的前提一般都是读慢写快的情景(写时钟大于读时钟),但需要注意的是,这里的写操作是猝发传输,而不能使连续操作。倘若写快读慢的场景下,写数据流是连续的,那再大的FIFO都会有写满的时候,因此无法避免数据的溢出(下面有一个蓄水的例子)。

所谓最坏情况,就是使得写速率最大,读速率最小;通常是考虑猝发传输。

写时钟:wr_clk;且写时钟周期里,每B个时钟周期会有A个数据写入FIFO;

读时钟:r_clk;且读时钟周期里,每Y个时钟周期里会有X个数据读出FIFO。

读写的Busrt_len: 相同,都为Burst_len。

如果100 个写时钟周期可以写入80个数据,10个时钟周期可以读出8个数据。令wclk =rclk ,考虑背靠背(20个clk不发数据+80clk发数据+80clk发数据+20clk不发数据的共200个clk)代入公式可计算FIFO深度:

160 - 160*0.8 = 32

1、读写都没有空闲周期

假设:
写入时钟 wr_clk = 50MHZ,
读取时钟 rd_clk = 20MHZ,
突发数据长度 Burst length = 100,

写入一个数据需要 1/50MHZ = 20ns;写入100个数据需要 100 * 20ns = 2000ns;

在2000ns内,只能读取 2000/(1/20MHZ) = 40个数据;

所以FIFO_DEPTH(min) = 100 - 40 = 60。

FIFO_DEPTH >= Burst length - ( Burst length * rd_clk / wr_clk)

2、读写有空闲周期

假设:
写入时钟 wr_clk = 50MHZ,
读取时钟 rd_clk = 10MHZ,
写空闲周期 = a,
读空闲周期 = b,
假设 a = 2,b = 1,
突发数据长度 Burst length = 100,

因为读写都有空闲周期,写一个数据,等2个周期再写下一个数据,相当于每3个时钟周期写一个数据;而读一样,读一个数据,等待1个周期再读下一个数据,相当于每2个时钟周期读一个数据;

写入一个数据需要 3*(1/50MHZ) = 60ns,写入100个数据需要 100 * 60 = 6000ns;

在6000ns内可以读取 6000/(2*1/10MHZ) = 30

所以所以FIFO_DEPTH(min) = 100 - 30= 70。

二、写时钟 = 读时钟(写读一样快)

1、读写没有空闲周期,且相位相等

这种情况不需要设计FIFO

2、读写没有空闲周期,相位不等

设计一个深度为 1 的FIFO就足够了

3、读写有空闲周期,无相位差

假设:
写入时钟 wr_clk = 50MHZ,
读取时钟 rd_clk = 50MHZ,
写空闲周期 = a,
读空闲周期 = b,
假设 a = 1,b = 2,
突发数据长度 Burst length = 100,

因为读写都有空闲周期,写一个数据,等1个周期再写下一个数据,相当于每2个时钟周期写一个数据;而读一样,读一个数据,等2个周期再读下一个数据,相当于每3个时钟周期读一个数据;

写入一个数据需要 2*(1/50MHZ) = 40ns,写入100个数据需要 100 * 40 = 4000ns;

在4000ns内可以读取 4000/(3*1/50MHZ) = 66.6

所以所以FIFO_DEPTH(min) = 100 - 66.6 = 34。

三、写时钟 < 读时钟(读比写快)

1、读写没有空闲周期 因为读比写快,所以不会发生数据丢失的情况,不需要设计FIFO

2、读写有空闲周期 假设: 写入时钟 wr_clk = 20MHZ, 读取时钟 rd_clk = 50MHZ, 写空闲周期 = a, 读空闲周期 = b, 突发数据长度 Burst length = 100,

因为读写都有空闲周期,写一个数据,等a个周期再写下一个数据,相当于每1+a个时钟周期写一个数据;而读一样,读一个数据,等b个周期再读下一个数据,相当于每1+b个时钟周期读一个数据;

四、最坏情况(背靠背)

1、背靠背

之前的写入和读取,相当于 是均匀写入和读取,而当写入操作没有说每几个时钟周期写入一个数据,而是在几个时钟周期内写入多少数据;在几个时钟周期内读出多少数据的时候。

2、背靠背计算

写数据时钟频率fa=50MHz
读数据时钟频率fb=40MHz
在写时钟周期内,每80个周期就有40个数据写入FIFO
在读时钟周期内,每10个周期可以有6个数据读出FIFO

在最坏的情形中,为了得到更安全的FIFO深度,我们需要考虑最坏情况,以防数据丢失,读写的速率应该相差最大,也就是说需要找出最大的写速率 和 最小的读速率,这样才能适配所有写入和读取的情况

写入的方式很多种,有均匀写入,有先写20再写20,方式很多。我们画出背靠背的情况

在背靠背(最坏)情况下,突发长度需要设置为 80,并且写速率设置为最大的50MHZ;而因为读时钟周期内,每10个周期可以有6个数

据读出FIFO,假设均匀读出,所以读速率设置为最小的40MHZ * 6/10 = 24MHZ

写入 80个数据需要的时间: 80 * 1/50MHZ = 1600ns

在1600ns内可以读出 1600 / 1/24MHZ = 38.4个数据

所以所以FIFO_DEPTH(min) = 80- 38.4 = 42。

每100个clock写入50个,每50个读出25个。fifo深度至少为。

每100写入50个,考虑背靠背每200个写入100个。 突发长度设置为100.

因为为同步fifo读写时钟频率应该相同。 读一个数据花费时间为50/25 = 2clk

则写入100个数据花费时间为100 clk

100clk/2 clk= 50个

100 - 50 = 50.