同步 FIFO 的实现
学习目的:
- 1.给大家介绍FIFO的基本原理和组成。
- 2.学习同步单时钟FIFO的分析以及编写。
- 3.以实例体验如何将实际需求分析转换成代码。
FIFO(First In First Out)队列通常在数字系统中实现两个模块间数据的暂存,达到减少两模块之间的速度依赖,使得两个模块能够相互相对独立的运行。
FIFO是FPGA设计的一个非常基本的单元。FIFO一般用一个双口RAM和分别指示读写地址的指针,以及状态生成和指示的逻辑组成,下图是典型的FIFO结构图:

我们看到中上部是一个双口RAM,所谓双口RAM是分别有两套读写数据线地址线以及控制线,用以实现读写的同时操作。
再看到读写指针和读写控制界面,左边是写控制界面和写指针,实现对写指针的更新。右边是读控制界面和读指针,实现对读指针的更新。我们还有比较逻辑,这里产生空empty信号和full信号。
我们来看一下存储器的工作方式,实际是一个循环队列:我们来跟踪一下情景:
以下存储器有8个存储单元,在初始化的时候,读指针RP和WP都指向0地址,当向存储器里写入了8个数据后,写指针会从新回到0,这就是循环队列。
这里地址是0-7是3个BIT宽度,WP和RP也要对应的是3个bit,加1就能实现从0,1,2.。6.7.0.1.2…这样循环。下图中阴影的部分标示存储区已经占用。

以上分析了WP和RP的行为,还需要产生空和满信号的逻辑,实现方法我们这里设置一个计数器 FIFO_CNTR,用以表示有效可读数据的个数,初始化的时候是0,标示存储器内没有数据可供读。
当写入接口进行一次有效的写操作(这里规定有效的写操作是FIFO不满的时候实施的写操作)计数器FIFO_CNTR加1,
当读出接口进行一次有效的读操作(这里规定有效的读操作是FIFO不空的时候实施的读操作)计数器FIFO_CNTR减1;
而当同时实施有效的写操作和读操作时,FIFO_CNTER不发生变化(从图上可以分析出实际读指针和写指针都往前走了,他们间距还是一样的,有效可读数据的存储个数还是保持不变)。
另外关于FIFO_CONTER的个数,我们这里看到范围是是0-8,(0时为空,8时为满),因此需要4个bit来定义FIFO_CNTR.因此通常情况下FIFO_CNTR要比地址位数多1位。
至于说到full和empty很简单的由FIFO_COUNTER产生:当且仅当FIFO_COUNTER=0时候,empty=1;当且仅当FIFO_CNTER为最多可容纳存储个数时,这里说FIFO_CNTR = 8时候,full=1;
我们再总结以上的分析,具体细化一下:
1,需要一个buff双口存储器做存储载体,当地址有n位,就有2N2^{N}2N个存储单元,标号从0到(2N−12^{N-1}2N−1)。三位地址存储地址就是从0到7。
2,需要wr_ptr指针,与地址位数相同,指向下个可以写的地址。
3,需要rd_ptr指针,与地址位数相同,指向下个可以读的地址。
4,需要fifo_cntr计数器,比地址位数多一位,指示当前可读的数据个数。
5,full和empty由fifo_cntr生成。
6,区别读写操作是否有效。
7,实现上述功能。
代码呼之欲出了,我们来写代码,首先是定义端口,之后就开始写代码。写完之后进行检查。
module sc_fifo(
input clk,rst,
input [7:0] din,
input wr,
output full,
output reg [7:0] dout,
input rd,
output empty
);
//1,需要一个buff双口存储器做存储载体,当地址有n位,就有2^N个存储单元,标号从0到(2^N-1)。三位地址存储地址就是从0到7。
reg [7:0] buff[0:7] ;
//2,需要wr_ptr指针,与地址位数相同,指向下个可以写的地址。
reg [2:0] wr_ptr ;
//3,需要rd_ptr指针,与地址位数相同,指向下个可以读的地址。
reg [2:0] rd_ptr ;
//4,需要fifo_cntr计数器,比地址位数多一位,指示当前可读的数据个数。
reg [3:0] fifo_cntr ;
//5,full和empty由fifo_cntr生成。
assign full = fifo_cntr ==8 ;
assign empty= fifo_cntr==0;
//6,区别读写操作是否有效。
wire valid_rd = ~empty & rd ;
wire

本文详细介绍了FIFO(先进先出)队列在数字系统中的应用,包括同步单时钟FIFO的设计原理和代码实现,以及异步FIFO的控制逻辑与状态机设计,特别强调了在FPGA上的实现细节。
最低0.47元/天 解锁文章
355

被折叠的 条评论
为什么被折叠?



