IC学习笔记2——同步FIFO

IC学习笔记2——同步FIFO

前言

FIFO(First in First out)是一种先进先出的数据缓存器,它与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取和写入某个指定的地址,FIFO分为同步FIFO和异步FIFO,接下来会首先介绍同步FIFO,再深入介绍异步FIFO相关问题。

一、同步FIFO

同步FIFO和异步FIFO最大的区别是,同步FIFO的读时钟和写时钟都是同一时钟。

1.1 实现原理

在这里插入图片描述

1.2 模块端口

一个简单的同步FIFO端口设计如下图所示:
在这里插入图片描述

上图列出了同步FIFO需要的外部端口信号,在这里简单的解释一下,其中clk为时钟信号。
rst_n为复位信号,后缀_n表示低电平有效。
din[7:0] 为输入数据,这里为8位数据。
we为写使能信号,当we为高电平的时候表示有效。
re为读使能信号,当re为高电平的时候表示有效。
dout[7:0]为输出数据,这里也是8位数据。
full为满信号,当full为高电平时,表明FIFO已经写满,此时即使we为高电平也不能写入数据。
empty为空信号,当empty为高电平时,表示FIFO里面数据已经读完,即使re为高电平也不能读出数据。

上面所列是一些外部信号,当然在同步FIFO中也存在一些内部信号。
wptr[3:0]为写指针信号,总是指向下一个时钟要写的地址,在这里写指针信号是4位,表示FIFO的大小为16。
rptr[3:0]为读指针信号,总是指向下一个时钟要读的地址。
[7:0] ram[0:15] ram表示同步FIFO存储数据的存储体,[7:0]表示一个数据的位数,[0:15]存储的个数,0~15表示可
以存储16个数据。

1.3 实现代码

module sfifo(input  clk,input  rst_n,input  we,input  re,input  [7:0] din,output  empty,output  full,output  reg [7:0] dout);reg[7:0] ram[0:15];reg[4:0] cnt;reg[3:0] wptr;reg[3:0] rptr;always@(posedge clk or negedge rst_n)       //下面是对读指针的描述     beginif(rst_n==1'b0)rptr<=4'b0;else if(empty==1‘b0&re==1’b1)          //这段代码的意思是非空读使能,读指针加1rptr<= rptr+1’b1;elserptr<= rptr;endalways@(posedge clk or negedge rst_n)       //下面是对读操作的描述     beginif(rst_n==1'b0)dout<=8’bzzzz_zzzz;            //同步FIFO初始输出为高阻态else if(empty==1‘b0&re==1’b1)          //这段代码的意思是非空读使能,将读指针对应的数据取出,送往输出//假如此时读指针是3,同时发生 rptr<= rptr+1’b1和dout<= ram[rptr],应注意此时后者读取是读指针为3的数据dout<= ram[rptr];elsedout<= dout;endalways@(posedge clk or negedge rst_n)        //下面是对写指针的描述     beginif(rst_n==1'b0)wptr<=4'b0;else if(full==1‘b0&we==1’b1)           //这段代码的意思是非满写使能,写指针加1wptr<= wptr+1’b1;elsewptr<= wptr;endalways@(posedge clk )        //下面是对写操作的描述     beginif(full==1‘b0&we==1’b1)                //这段代码的意思是非满写使能,将输入数据写到写指针对应的ram中ram[wptr]<= din;elseram[wptr]<= ram[wptr];endalways@(posedge clk or negedge rst_n)   //下面是对计数器的描述beginif(rst_n==1'b0)                   //初始计数器为0,表示FIFO此时写入的数据个数为0.可以被读出的个数也为0                        cnt<=5'b0;else if((empty==1‘b0&re==1’b1) && (full==1‘b0&we==1’b1))  //同时读写,计数器不变cnt<=cnt;else if (full==1‘b0&we==1’b1)   //非满写使能,表示一次写行为,计数器加1cnt<=cnt+1'b1;else if(empty==1‘b0&re==1’b1)   //非空读使能,表示一次读行为,计数器减1cnt<=cnt-1'b1;elsecnt<=cnt;end              assign empty =(cnt==5‘b0)? 1’b1:1‘b0;  //当计数器为0时,表示同步FIFO中没有数据可读,所以empty为1assign  full =(cnt==5‘d16)?1’b1:1‘b0;  //当计数器为16时,表示同步FIFO中存储的数据已满,所以full为1endmodule

1.4 仿真测试

module sfifo_tb();reg        clk;
reg        rst_n;
reg        we;
reg        re;
reg [7:0]  din;
wire [7:0] dout;
wire       empty;
wire       full;sfifo    u1(                                //例化.clk   (clk),.rst_n (rst_n),.we    (we),.re    (re),.din   (din),.empty (empty),.full  (full),.dout  (dout));initial begin                                       //设置时钟,周期是20ns,50Mhzclk=0;forever    #10     clk=~clk;endinitial beginrst_n=1'b0;                 //设置初始状态,复位,读无效,写无效,输入数据为0we   =1'b0;re   =1'b0;din  =8'b0;#28 rst_n=1'b1;             //松开复位we=1’b1;             //写使能din=8‘d1;            //输入数据为1@(posedge clk);      //写入数据repeat(15)           //接着写入2,3,4,5,6,7,8,9,10,11,12,//13,14,15,16这些数据begin#18;din=din+1'b1;@(posedge clk);  end#18    din=din+1'b1;  //此时同步FIFO已经写满了,在往同步FIFO中写数据17,17这个数据不会被写进@(posedge clk);   #18      re=1’b1;      //读使能,写无效 we=1'b0;@(posedge clk);     //第一个读出的数为1repeat(15)        //读取剩余的数begin@(posedge clk);   end#2;re=1‘b0;        //结束读操作end    
endmodule

其仿真结果波形图如下所示,在we为高时,clk上升沿时写入第一个数据1. 数据16为最后写入的数据,这个时候同步FIFO的满信号full为高。在往其中写数据17,是写不进去的。读操作和写操作类似,如下图所示。
在这里插入图片描述


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部