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)       //下面是对读指针的描述     
           begin
                if(rst_n==1'b0)
                        rptr<=4'b0;
                else if(empty==1‘b0&re==1’b1)          //这段代码的意思是非空读使能,读指针加1
                        rptr<= rptr+1’b1;
                else
                        rptr<= rptr;
           end
           
           always@(posedge clk or negedge rst_n)       //下面是对读操作的描述     
           begin
                if(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];
                else
                        dout<= dout;
           end
           
          always@(posedge clk or negedge rst_n)        //下面是对写指针的描述     
           begin
                if(rst_n==1'b0)
                        wptr<=4'b0;
                else if(full==1‘b0&we==1’b1)           //这段代码的意思是非满写使能,写指针加1
                        wptr<= wptr+1’b1;
                else
                        wptr<= wptr;
           end
           
          always@(posedge clk )        //下面是对写操作的描述     
           begin
                if(full==1‘b0&we==1’b1)                //这段代码的意思是非满写使能,将输入数据写到写指针对应的ram中
                         ram[wptr]<= din;
                else
                         ram[wptr]<= ram[wptr];
           end
          
           always@(posedge clk or negedge rst_n)   //下面是对计数器的描述
           begin
                 if(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)   //非满写使能,表示一次写行为,计数器加1
                          cnt<=cnt+1'b1;
                 else if(empty==1‘b0&re==1’b1)   //非空读使能,表示一次读行为,计数器减1
                          cnt<=cnt-1'b1;
                 else
                          cnt<=cnt;
           end              
                        
           assign empty =(cnt==5‘b0)? 1’b1:1‘b0;  //当计数器为0时,表示同步FIFO中没有数据可读,所以empty为1
           assign  full =(cnt==5‘d16)?1’b1:1‘b0;  //当计数器为16时,表示同步FIFO中存储的数据已满,所以full为1

           endmodule

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,50Mhz
                                            clk=0;
                         forever    #10     clk=~clk;
               end
       
       initial begin
                         rst_n=1'b0;                 //设置初始状态,复位,读无效,写无效,输入数据为0
                         we   =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);     //第一个读出的数为1
                                repeat(15)        //读取剩余的数
                                   begin
                                       @(posedge clk);   
                                   end
                                   #2;
                                     re=1‘b0;        //结束读操作
                                    
              end    
endmodule

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

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值