同步FIFO分析及rtl代码

        同步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  
    end
endmodule


fifo_tb.v

//fifo testbench
`define DEL 1

module 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;
    end
endmodule


 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值