同步FIFO分析及rtl代码

来源:互联网 发布:ppt图表编辑数据没反应 编辑:程序博客网 时间:2024/05/21 09:06

        同步FIFO的意思是说FIFO的读写时钟是同一个时钟,因此时钟频率是相同的,只是在相位上可能有差别,不同于异步FIFO,异步FIFO的读写时钟是完全异步的。同步FIFO的对外接口包括时钟,清零,读请求,写请求,数据输入总线,数据输出总线,空以及满信号。下面分别对同步FIFO的对外接口信号作一描述:

Ø 1.  时钟,用于同步FIFO的读和写,上升沿有效。

Ø 2.  清零,异步清零信号,低电平有效,该信号有效时,FIFO被清空。

Ø 3.  写请求,低电平有效,该信号有效时,表明外部电路请求向FIFO写入数据。

Ø 4.  读请求,低电平有效,该信号有效时,表明外部电路请求从FIFO中读取数据。

Ø 5.  数据输入总线,当写信号有效时,数据输入总线上的数据被写入到FIFO中。

Ø 6.  数据输出总线,当读信号有效时,数据从FIFO中被读出并放到数据输出总线上。

Ø 7.  空,当该信号为高电平,表明FIFO中没有任何数据,全部为空。

Ø 8.  满,当该信号为高电平,表明FIFO已经满了,没有空间可用来存贮数据。
为了更好的理解FIFO的工作方式,我们设定同步FIFO的数据宽度(bit位)为任意,深度为8。同步FIFO的难点主要是状态判断,下面就来看看如何对空状态和满状态来进行判断。

       可以看出,当读指针read_pointer和写指针write_pointer的值一样的时候,FIFO的状态为空。比较麻烦的是对FIFO是否已经满的状态的判断,因为存在两种情况,第一种情况时写指针write_pointer比读指针read_pointer大,比如写指针writer_pointer = 7而读指针read_pointer = 0,还有一种情况时写指针writer_pointer比读指针read_pointer小,比如写指针writer_pointer = 2而读指针read_pointer = 3。由于读写电路在循环的读写RAM,所以在上面的两种情况下FIFO实际上都已经满了。那么如何对读写指针的判断比较容易的得出FIFO已经满了,同时这样的判断电路还要容易参数化?

附上verilog代码及相应test_bench,在modelsim上仿真通过!

fifo.v

module syn_fifo(    clock,    reset_n,    read_n,    write_n,    data_in,    data_out,    full,    empty    );    parameter   DATA_WIDTH     = 8 ;    parameter   DATA_DEPTH     = 8;    parameter   DATA_PTR_WIDTH = 3 ;    input                   clock   ;    input                   reset_n ;    input                   read_n  ;    input                   write_n ;    input [DATA_WIDTH-1:0]  data_in ;    output[DATA_WIDTH-1:0]  data_out;    output                  full    ;    output                  empty   ;    wire                    clock   ;    wire                    reset_n ;    wire                    read_n  ;    wire                    write_n ;    wire[DATA_WIDTH-1:0]    data_in ;    reg [DATA_WIDTH-1:0]    data_out;    wire                    full    ;    wire                    empty   ;    reg[DATA_PTR_WIDTH  :0] counter   ;    reg[DATA_PTR_WIDTH-1:0] rd_pointer;    reg[DATA_PTR_WIDTH-1:0] wr_pointer;    reg[DATA_WIDTH    -1:0] fifo_mem[0:DATA_DEPTH-1];    assign full  = (counter == DATA_DEPTH) ? 1'b1 : 1'b0;    assign empty = (counter == 0) ? 1'b1 : 1'b0;    always @(posedge clock)begin        if(reset_n) begin                  rd_pointer <= 0;            wr_pointer <= 0;            counter    <= 0;        end        if(read_n && (~write_n) && (~empty)) begin                    counter  <= counter-1;            data_out <= fifo_mem[rd_pointer];            rd_pointer <= rd_pointer+1;        end        if((~read_n) && write_n && (~full)) begin                    counter <= counter+1;            fifo_mem[wr_pointer] <= data_in;            wr_pointer <= wr_pointer+1;        end      endendmodule


fifo_tb.v

//fifo testbench`define DEL 1module fifo_tb;    parameter   DATA_WIDTH  = 8 ;    parameter   DATA_DEPTH  = 16;    reg                   clock   ;    reg                   reset_n ;    reg                   read_n  ;             // read data to data_out from fifo_mem    reg                   write_n ;             // write data in fifo_mem from data_in    reg [DATA_WIDTH-1:0]  data_in ;    wire[DATA_WIDTH-1:0]  data_out;    wire                  full    ;    wire                  empty   ;    integer fifo_count;    //实例化 syn_fifo 模块/*    syn_fifo syn_fifo_1(        .clock(clock),        .reset_n(reset_n),        .read_n(read_n),        .write_n(write_n),        .data_in(data_in),        .data_out(data_out),        .full(full),        .empty(empty)        );*/    syn_fifo syn_fifo_2(        clock,        reset_n,        read_n,        write_n,        data_in,        data_out,        full,        empty        );    initial begin        data_in=255;        fifo_count=0;        read_n=0;        write_n=1;        clock=1;        reset_n=1;        #4 reset_n=0;    end    always #10 clock = ~clock;    always @(posedge clock && (~reset_n)) begin        if(write_n && ~read_n)begin            fifo_count <= fifo_count+1;            data_in    <= data_in+1;end        else if(~write_n && read_n)begin            fifo_count <= fifo_count-1;        end    end    always@(negedge clock) begin   //negedge        if (full)begin            read_n  <= 1;            write_n <= 0;end        else if (empty)begin            read_n  <= 0;            write_n <= 1;        end    end    //dump fsdb file for debussy    initial begin        $fsdbDumpfile("wave.fsdb");        $fsdbDumpvars;    endendmodule


 

原创粉丝点击