FIFO深度计算


当读数据的速率小于写数据的速率时,这就需要先将数据缓存下来,这时候就要计算需要开辟多大的空间缓存这些数据,缓存开大了会浪费资源,开小了会丢失数据

假如模块A不间断的向FIFO中写数据,模块B同样不间断的从FIFO中读数据,不同的是模块A写数据的时钟频率要大于模块B读数据的时钟频率,那么在一段时间内总是有一些数据没来得及被取走,如果系统一直在工作,那些没有被取走的数据会越积累越多,FIFO的深度需要时无穷大的。

如果写操作时连续的数据流,那么再大的FIFO都无法保证数据不溢出,因此可以认为这种情况写数据的传输时“突发burst”的,即写操作并不连续,要确定FIFO的深度,关键在于计算出在突发读写这段时间内有多少个数据没有被读走,也就是FIFO的深度就等于没有被读走的数据的个数。

case1:fA > fB 读写之间没有空闲周期

写速率fA = 80MHz
读速率fB = 50MHz
突发长度Burst Length = 120
读写之间没有空闲周期,是连续读写一个突发长度

sol

在突发传输过程中,数据都是连续读写的
写一个数据需要的时间 = 1 / 80MHz = 12.5ns
写一个突发需要的时间 = 120 * 12.5ns = 1500ns
读一个数据需要的时间 = 1 / 50MHz = 20ns
每1500ns,120个数据被写入FIFO,但读一个数据需要20ns的时间
可以计算出,1500ns内读出多少个数据,1500 / 20 = 75
剩下的没有读出,就存在FIFO中,则需要120 - 75 = 45
所以这种情况下,FIFO最小深度为45

case2:fA > fB 读写之间存在周期延迟

写速率fA = 80MHz
读速率fB = 50MHz
突发长度Burst Length = 120
读写之间存在空闲周期,读比写慢两拍

sol

在异步FIFO中,需要去判断FIFO的空满来保证逻辑的正确性,读写指针处在不同的时钟域下,需要采用格雷码和两级同步寄存器去降低亚稳态的概率,既然两级同步,那就会导致空满标志位的判断至少延迟两拍,判满需要将读指针同步到写时钟域,防止被写满,判空需要将写指针同步到读时钟域,防止被读空,具体实现可以看看链接: 同步和异步FIFO的实现.
所以
case2的FIFO最小深度应该比case1的45略大?还是一样大?

case3:fA > fB 读写之间存在空闲周期

写速率fA = 80MHz
读速率fB = 50MHz
突发长度Burst Length = 120
连续写入之间的空闲周期为1,也就是写入一个数据后,模块A等待一个时钟周期,开始下一个写入,可以理解为每两个时钟周期,一个数据被写入
连续读取之间的空闲周期为3,也就是读取一个数据后,模块B等待三个时钟周期,开始下一个读取,可以理解为每四个时钟周期,一个数据被读出

sol

写一个数据需要的时间 = 21 / 80MHz = 25ns
写一个突发需要的时间 = 120 * 25ns = 3000ns
读一个数据需要的时间 = 4
1 / 50MHz = 80ns
每3000ns,120个数据被写入FIFO,但读一个数据需要80ns的时间
可以计算出,3000ns内读出多少个数据,3000 / 80 = 37.5
剩下的没有读出,就存在FIFO中,则需要120 - 37.5 = 82.5
所以这种情况下,FIFO最小深度为83

case4:fA > fB 给定wr_enb和rd_enb占空比

写速率fA = 80MHz
读速率fB = 50MHz
突发长度Burst Length = 120
写使能信号占整个burst时间比重为1/2
读使能信号占整个burst时间比重为1/4

sol

这个场景和场景3一样的
case4中一个数据项将在2个时钟周期内写入,而一个数据项将在4个时钟周期内读取
因此FIFO的最小深度也是83

case5:fA < fB 读写之间没有空闲周期

写速率fA = 30MHz
读速率fB = 50MHz
突发长度Burst Length = 120

sol

突发传输中,数据都是连续读写的,读数据要比写数据快,这种情况下永远也不会发生数据丢失,因此FIFO只起到了跨时钟域的作用
因此FIFO的最小深度为1

case6:fA < fB 给定wr_enb和rd_enb占空比

写速率fA = 40MHz
读速率fB = 50MHz
突发长度Burst Length = 120
连续写入之间的空闲周期为1,也就是写入一个数据后,模块A等待一个时钟周期,开始下一个写入,可以理解为每两个时钟周期,一个数据被写入
连续读取之间的空闲周期为3,也就是读取一个数据后,模块B等待三个时钟周期,开始下一个读取,可以理解为每四个时钟周期,一个数据被读出

sol

写一个数据需要的时间 = 21 / 40MHz = 50ns
写一个突发需要的时间 = 120 * 50ns = 6000ns
读一个数据需要的时间 = 4
1 / 50MHz = 80ns
每6000ns,120个数据被写入FIFO,但读一个数据需要80ns的时间
可以计算出,6000ns内读出多少个数据,6000 / 80 = 75
剩下的没有读出,就存在FIFO中,则需要120 - 75 = 45
所以这种情况下,FIFO最小深度为45

case7:fA = fB 读写之间没有空闲周期

写速率fA = 50MHz
读速率fB = 50MHz
突发长度Burst Length = 120

sol

读和写没有空闲周期,这意味着突发中的所有项都以连续的时钟周期写入和读取
如果clkA和clkB之间没有相位差,则不需要FIFO;如果clkA和clkB之间存在相位差,深度为1的FIFO就足够了

case8:fA = fB 给定wr_enb和rd_enb占空比

写速率fA = 50MHz
读速率fB = 50MHz
突发长度Burst Length = 120
连续写入之间的空闲周期为1
连续读取之间的空闲周期为3

sol

写一个数据需要的时间 = 21 / 50MHz = 40ns
写一个突发需要的时间 = 120 * 40ns = 4800ns
读一个数据需要的时间 = 4
1 / 50MHz = 80ns
每4800ns,120个数据被写入FIFO,但读一个数据需要80ns的时间
可以计算出,4800ns内读出多少个数据,4800 / 80 = 60
剩下的没有读出,就存在FIFO中,则需要120 - 60 = 60
所以这种情况下,FIFO最小深度为60

case9:数据速率如下所示

前面的几种情况给的条件都是每隔几个时钟周期读写一次,这种周期性读写在实际中很常见,但是还有这样一种情况,只给出数据在一段时间内的读写速率,怎么读写完全随机,这种情况就需要考虑最坏的一种,避免数据丢失
最坏的情况,读写之间的数据速率差异应该是最大的,因此对于写操作,应该考虑最大数据速率,对于读操作,应该考虑最小数据速率

写速率fA = 读速率fB = 50MHz
在写时钟周期内,每100个周期就有80个数据写入FIFO
在读时钟周期内,每10个周期就有8个数据读出FIFO
在这里插入图片描述
写操作的最大数据速率为Case-4,写操作在最小的时间内完成,这种背靠背的情况就是写速率最高的情况,突发长度为160,在160个周期内写入160个数据
在读时钟周期内,每10个周期可以有8个数据读出FIFO,即一个周期可以读出8/10个数据,所以160个时钟读了160*8/10 = 128个数据
考虑背靠背(20个clk空闲、80个clk发数据、80个clk发数据、20个clk空闲,共200个clk),所以FIFO的最小深度为160 - 128 = 32

总结

求FIFO最小深度主要有以下要点,

  1. 求之前要验证一下在允许的最大时间长度内写入的数据量是否等于读出的数据量,保证有解,不会算出来无穷大
  2. 求FIFO就要考虑最坏的情况,读写的速率应该相差最大,也就是说需要找出最大的写速率和最小的读速率
  3. 计算FIFO的深度,关键在于计算出在突发读写这段时间内有多少个数据没有被读走
  4. 由于FIFO判空满标志位可能会有延迟,在实际应用中需要预留一些余量
  5. 注意单位,给定burst长度为20K,应该是20,000还是20*1012?

写时钟周期为clkw,读时钟周期为clkr,在读时钟周期内,每x个周期内可以有y个数据读出FIFO,在写时钟周期内,每m个周期内可以有n个数据写入FIFO,背靠背的情况是FIFO读写的最坏情况,burst长度记作B
由此可以得到,FIFO的最小深度为 B - B * (clkr/clkw) * (y / x)

变形一下,得到B - ( (B * (1/clkw)) ) / ( (X*(1/clkr)) / Y )

(B * (1/clkw)),也就是整个burst持续的时间
(X*(1/clkr)) / Y,表示读出一个数据所需要的时间
两者相除就是一段时间内的读出的数据总量
B是突发长度,两者相减就是FIFO中残留的数据,也就是理论上FIFO的最小深度

计算的例子

  1. A/D采样率50MHz,dsp读A/D读的速率40MHz,要不丢失地将10万个采样数据送入DSP,在A/D在和DSP之间至少加多大容量(深度)的FIFO才行?

    sol:
    100,000 / 50MHz = 1/500 s = 2ms
    (50MHz - 40MHz) * 1/500 = 20k就是FIFO深度。

  2. FIFO深度计算: 写入时钟20MHz,读出时钟40MHz,每1000个时钟周期写入500个数据,每4个时钟周期读出1个数据,读写数据位宽一致。
    写时钟频率w_clk, 读时钟频率 r_clk, 写时钟周期里,每B个时钟周期会有A个数据写入FIFO 读时钟周期里,每Y个时钟周期会有X个数据读出FIFO 则,FIFO的最小深度是?

    sol:
    fifo_depth = burst_length - burst_length * X / Y * r_clk / w_clk
    首先认为写操作是Burst(突发)进行的,但是写操作的效率并不是100%,而是A/B,因此实际的写速率为Fwr = (A/B) * w_clk。同理,实际的读速率为Frd = (X/Y) * r_clk。
    这类题没有约束突发长度场景,在计算时要考虑极端的情况,即“背靠背”的情况。
    空闲——Burst——Burst——空闲——空闲——Burst——Burst——空闲
    这就是”背靠背“的极端情况。
    所以这里的burst_length = (A+A) / w_clk = (500+500) / 20MHz
    此题得解。
    fifo_depth = 1000-1000(1/4)*(40/20) = 500

  3. 一个8bit宽的AFIFO,输入时钟为100MHz,输出时钟为95MHz,设一个package为4Kbit,且两个package之间的发送间距足够大。求AFIFO的深度?

    sol:
    fifo_depth = burst_length - burst_length * (X / Y) * (r_clk/w_clk)
    burst_length = 4Kbit/8bit ,有两种结果
    其一,根据存储厂商的惯用算法,4Kbit=4000bit,burst_length=500;
    其二,用一般二进制算法,4Kbit=4*1024=4096bit,burst_length=512。
    因为X和Y的值没有给出,所以默认为1.
    其一,fifo_depth = 500 - 500 *(95/100)= 25 ,所以fifo_depth最小取值是25 。
    其二,fifo_depth = 512 - 512 *(95/100)= 25.6 ,所以fifo_depth最小取值是26 。

  • 5
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值