同步FIFO设计(上)

电子说

1.3w人已加入

描述

1.介绍

FIFO ,First In First Out,先入先出队列,顾名思义,即第一个到达的数据也将会是第一个离开。由于同步FIFO的操作速度非常快,并且能 降低系统的复杂性 ,因此在很多高性能系统中是非常理想的选择。且同步FIFO相比异步FIFO来说实现起来更简单。所以在实际项目中用得相对较多。

UART项目中也使用了同步FIFO进行数据的缓存,本文主要对此进行讲解。

2.FIFO设计

FIFO存储

同步fifo架构,取自《硬件架构的艺术》

根据系统时钟和响应速度,需要确定 FIFO深度 。本设计中深度设置为15,数据宽度8bit。同步FIFO设计的关键在于空满信号的产生。

设计中rptr为 读指针 ,指向下一个要读的地址;wptr为 写指针 ,同样指向下一个要写的地址。有效的读写使能使读写指针递增。

wfull为 写满信号 ,表示FIFO空间已经写满,不能再写入数据;rempty为 读空信号 ,表示FIFO内没有可供读写的有效数据。空满信号的产生是根据读写指针(读写地址)产生的。

  • FIFO复位

此FIFO模块中有两个复位,一个是系统复位rst_,一个是FIFO复位fifo_rst。

系统复位为是整系统复位信号,该系统中所有寄存器会在此复位信号有效时有一个初始值,避免不定态的产生。

FIFO复位信号是同步FIFO的复位信号,只对此模块有效,该信号有效时读写指针会归0。

满足FIFO复位单独可控的设计要求。

  • 空满信号产生

当FIFO复位信号fifo_rst有效时,读写指针会归零,这时rempty信号会拉起,表示FIFO为空状态,此时往fifo中写数据;当fifo中没有空间可以写时,写地址是ram的深度即15,写指针指向下一个写地址会回到0,此时fifo为满状态,wfull信号拉起。

FIFO存储

空满产生

可以发现,在读写指针相等时,FIFO要么空要么满。那么我们怎么对空满状态进行区分呢?

FIFO深度为15,正常地址应该为4bit[3:0],为了区分空满状态,我们将指针设置为5bit[4:0]。

根据上述的空满状态产生原理,可以发现:

1) 当FIFO为空时,读写指针完全相等;

2) 当FIFO为满时,读写指针的最高位是相反的,而低4位一定相等。

FIFO存储

空满信号产生

  • FIFO数据状态指示

由于设计要求FIFO数据量需要可查询,所以增加一个fifo_cnt,它的值为写指针与读指针的差值。表示FIFO中剩余的数据量,作为输出传递到寄存器配置模块供系统查询。

最后附上本项目中所用到的同步FIFO代码,可将FIFO数据位宽和深度参数化,减少改动方便重复调用。另外要养成良好的代码习惯,多加注释。

同步FIFO Verilog代码:

1`timescale 1ns/1ps
 2
 3module    UART_FIFO(
 4    //inputs
 5    clk,
 6    rst_,
 7    fifo_rst,
 8    rinc,
 9    winc,
10    data_i,
11    //outputs
12    data_o,
13    wfull,
14    rempty,
15    fifo_cnt
16);
17
18input           clk;                 // ARM clock
19input           rst_;                // ARM reset
20input           fifo_rst;            // FIFO reset control signal.high active
21input           rinc;                // FIFO read enable signal
22input           winc;                // FIFO write enable signal
23input  [7:0]    data_i;              // in data line
24
25output          wfull;               // write full signal
26output          rempty;              // read empty signal
27output [7:0]    data_o;              // FIFO out data
28output [4:0]    fifo_cnt;            // FIFO statu register
29
30reg  [7:0]      data_o;
31reg  [4:0]      fifo_cnt;
32reg  [4:0]      wptr;                // write pointer
33reg  [4:0]      rptr;                // read pointer
34reg  [7:0]      ram[15:0];           // ram in FIFO
35
36// write data in ram
37always@(posedge clk or negedge rst_) begin
38    if(!rst_) begin
39        data_o <= 8'd0;
40        rptr   <= 5'd0;
41    end
42    else begin
43        if(fifo_rst) begin
44            rptr <= 5'd0;
45        end
46        else begin
47            if(rinc && !rempty) begin
48                data_o <= ram[rptr[3:0]];
49                rptr   <= rptr + 1'b1;
50            end
51        end
52    end
53end
54
55// read data from ram
56always@(posedge clk or negedge rst_) begin
57    if(!rst_) begin
58        wptr <= 5'd0;
59    end
60    else begin
61        if(fifo_rst) begin
62            wptr <= 5'd0;
63        end
64        else begin
65            if(winc && !wfull) begin
66                ram[wptr[3:0]] <= data_i;
67                wptr           <= wptr + 1'b1; 
68            end
69        end
70    end
71end
72
73// the number of data in the FIFO
74always@(posedge clk or negedge rst_) begin
75    if(!rst_) begin
76        fifo_cnt <= 5'd0;
77    end
78    else begin
79        fifo_cnt <= wptr - rptr;
80    end
81end
82
83// produce full and empty signal
84assign    wfull  = ({!wptr[4],wptr[3:0]}==rptr)? 1'b1 : 1'b0;
85assign    rempty = (wptr==rptr)? 1'b1:1'b0;
86
87endmodule
88
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分