FIFO基础
FIFO系列旨在教笨蛋自己,所以可能会有废话和吐槽,以及出现反复的说明。
基础知识
参考这个视频https://www.youtube.com/watch?v=dCj5HAnaCd8
FIFO是什么?
FIFO(First input First Output):先进先出,先写入的数据先读取
为什么我们需要fifo
FIFO的种类
同步FIFO和异步FIFO
格雷码
格雷码是任意两个相邻数的代码只有一位二进制数不同的编码,这样说太复杂看不懂,下面用3位二进制的表来说明:
十进制 | ( $B_2$ ) | ( $B_1$ ) | ( $B_0$ ) |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 1 | 0 |
3 | 0 | 1 | 1 |
4 | 1 | 0 | 0 |
5 | 1 | 0 | 1 |
6 | 1 | 1 | 0 |
7 | 1 | 1 | 1 |
由此表我们可以看到3→4的 $B_2$ $B_1$ $B_0$ 都发生了变化,这种变化可能会导致亚稳态的出现。为了防止这种情况的发生,我们将引入格雷码的概念。
格雷码的规则是:
格雷码位 | 转换规则(异或表示) | 转换规则(加法表示) |
---|---|---|
( $G_2$ ) | ( $G_2 = B_2$ ) | ( $G_2 = B_2$) |
( $G_1$ ) | ( $G_1 = B_2 \oplus B_1$ ) | ( $G_1 = B_2 + B_1$ ) |
( $G_0$ ) | ( $G_0 = B_1 \oplus B_0$ ) | ( $G_0 = B_1 + B_0$ ) |
所以它的格雷码转换如下:
十进制 | ($ G_2 $) | ( $G_1$ ) | ( $G_0$ ) |
---|---|---|---|
0 | 0 | 0 | 0 |
1 | 0 | 0 | 1 |
2 | 0 | 1 | 1 |
3 | 0 | 1 | 0 |
4 | 1 | 1 | 0 |
5 | 1 | 1 | 1 |
6 | 1 | 0 | 1 |
7 | 1 | 0 | 0 |
FIFO的理解
FIFO结构
- wptr: 写指针
- rptr: 读指针
- full: 满信号
- empty: 空信号
FIFO的运行
- 初始:rst(复位)过一次后wptr和rptr会在初始的位置(0地址位)上,意思是初始化后大家都从零开始。
- 开始写入:现在假设一直在写入数据,从0一直写到7。
- 写满:当wptr写到7就代表FIFO现在是满(full)的状态,rptr读指针现在还是0(因为没有操作)。
- 写满后写指针:写满后+1,即(111+1=1000),wptr会重新回到0(因为FIFO只看$B_2$$B_1$$B_0$的数据,即000),此时wptr和rptr会重合
——FIFO提问:你的wptr和rptr都是0了,我怎么知道是full还是empty?——
- 什么时候是空信号(empty)?
即 wptr=rptr
【我靠你这不矛盾吗?上面刚说wptr和rptr重合了,明明已经把7个位置都沾满了咋还说我是空的?】
为了处理这个问题,还需要再添加一个地址位来处理。 - 多的地址位:上面我们可以看到写满后+1地址位变成了4个(111+1=1000),多出来的1就是我们的解题关键了
- 满信号(full)的条件:wptr的3位与rptr的3位相同(1[000]和0[000]) + wptr多出来的地址位取反与rptr相同([1]000和[0]000):
full= {~wptr[3],wptr[2:0]}=={rptr[3:0]}
此时我们再把上面的空信号满足条件补充一下:
empty= wptr[3:0]==rptr[3:0] - 空信号(empty)也滚了一周后:上面读满一次让空信号(empty)也+1了,后面的其实也不用担心,因为满信号(full)读满+1就变成0了,如果读满只会和空信号又正好相反。如果FIFO为空,则无法从中读取信号