FIFO设计中与深度depth相关的问题
零、前言
关于同步FIFO如何设计请参考之前的一篇文章:手写同步FIFO。
关于异步FIFO如何设计请参考之前的一篇文章:手写异步FIFO。
一、如何设计depth不是2的幂次的异步FIFO?
如果FIFO的深度不是2的幂次,那么格雷码其实是不连续的,也即在最大值跳变到最小值时不止一个bit发生了变化。当然你也可以设计一个深度略大的,并且是2的幂次的FIFO,但是这样其实是浪费资源的。
例如我们需要一个深度为5的FIFO,此时我们可以设计一个深度为8的FIFO,但是这样会浪费资源。那么我们应该怎么办呢?
其实我们可以换一个思路,通过观察下表不难发现,格雷码具有对称性。0-15这16个格雷码,如果前后去掉相同个数的格雷码,那么剩余的格雷码仍然符合相邻两个数只有1 bit的跳变,也包括最后一个到第一个的跳变。
例如,如果要设计深度为5的FIFO,由于需要5*2 = 10个格雷码,所以可以前后各去掉三个数,也就是保留3-12这十个格雷码。可以看到,最大的数12和最小的数3也是只有1 bit的跳变。
所以我们可以这样编码:addr==0的时候,gray code不从4’b0000开始,而是从4’b0010开始;gray code最大为4’b1010。不过此时需要注意的是:
- 我们在由addr得到格雷码时不能直接转换,而是要使用addr + 3进行转换;同理由格雷码转换回addr时,也不要忘记减去3。
- 使用这种编码时,FIFO的满判断逻辑就不是简单的高两位相反,低位相同了。比如depth=5, rd_ptr=4’b0010, wr_ptr=4’b1010,表示5个entry已经满了,但此时并不能通过之前的条件去判断。具体如何判断,需要根据depth的大小寻找规律!
根据这个思路,我们就可以设计任意深度的FIFO,而相邻地址的跳变始终都保持为1 bit。
二、如何设计一个depth=1的异步FIFO?
由于该FIFO只有一个entry,所以之前设计中用到的很多东西我们都不再需要了,例如地址指针wptr/rptr,地址也只需要1bit就够了,既然是1bit那么也没必要使用格雷码了。
判断空满的逻辑也变得很简单,只要push一次数据full信号就拉高,只要pop一次数据,empty信号就拉高。
三、FIFO深度的设置怎么才合理?设置大了和设置小了会有什么影响?
请参考这篇文章:FIFO深度计算。
FIFO的深度设置大了会浪费资源,设置小了会丢失数据。