Verilog中的FIFO设计

本文介绍了一种同步FIFO的设计方法,详细阐述了使用Verilog实现的具体过程,包括参数定义、信号声明、写入与读取逻辑、空满状态判断等核心模块,并通过测试平台验证其功能。
module syn_fifo(clk, rstn, wr_en, rd_en, wr_data, rd_data, fifo_full, fifo_empty);

    //参数定义
    parameter   width = 8;
    parameter   depth = 8;
    parameter   addr  = 3;

    //输入信号
    input   clk;    //时钟信号
    input   rstn;   //下降沿复位
    input   wr_en;  //写入使能
    input   rd_en;  //读取使能

    //数据信号
    input   [width - 1 : 0] wr_data;    //写数据
    output  [width - 1 : 0] rd_data;    //读数据

    reg [width - 1 : 0] rd_data;

    //空满判断信号
    output  fifo_full;
    output  fifo_empty;

    //定义一个计数器,用于判断空满
    reg [$clog2(depth): 0] cnt;

    //定义读写地址
    reg [depth - 1 : 0] wr_ptr;
    reg [depth - 1 : 0] rd_ptr;

    //定义一个宽度为为width,深度为depth的fifo
    reg [width - 1 : 0] fifo [depth - 1 : 0];

    //写地址操作
    always @ (posedge clk or negedge rstn) begin
        if(!rstn)
            wr_ptr <= 0;
        else if(wr_en && !fifo_full)    //写使能,且fifo未写满
            wr_ptr <= wr_ptr + 1;
        else
            wr_ptr <= wr_ptr;
    end

    //读地址操作
    always @ (posedge clk or negedge rstn) begin
        if(!rstn)
            rd_ptr <= 0;
        else if(rd_en && !fifo_empty)   //读使能,且fifo不为空
            rd_ptr <= rd_ptr + 1;
        else
            rd_ptr <= rd_ptr;
    end

    //写数据
    integer i;

    always @ (posedge clk or negedge rstn) begin
        if(!rstn) begin //复位清空fifo
            for(i = 0; i < depth; i = i + 1)
                fifo[i] <= 0;
        end
        else if(wr_en)  //写使能时将数据写入fifo
            fifo[wr_ptr] <= wr_data;
        else    //否则保持
            fifo[wr_ptr] <= fifo[wr_ptr];
    end

    //读数据
    always @ (posedge clk or negedge rstn) begin
        if(!rstn)
            rd_data <= 0;
        else if (rd_en)
            rd_data <= fifo[rd_ptr];    //从fifo中读取数据
        else
            rd_data <= rd_data;
    end

    //辅助计数,用于判断空满
    always @ (posedge clk or negedge rstn) begin
        if(!rstn)
            cnt <= 0;
        else if (wr_en && !rd_en && !fifo_full) //有效的只写入
            cnt <= cnt + 1;
        else if (!wr_en && rd_en && !fifo_empty) //有效的只读取
            cnt <= cnt - 1;
        else 
            cnt <= cnt;
    end

    //空满判断
    assign fifo_full = (cnt == depth)? 1 : 0;
    assign fifo_empty = (cnt == 0) ? 1 : 0;
endmodule


module syn_fifo_tb;
    reg clk, rstn;
    reg wr_en, rd_en;

    wire fifo_full, fifo_empty;

    reg [7 : 0] wr_data;
    wire    [7 : 0] rd_data;


    //生成波形
    /*
    initial begin
        $fsdbDumpfile("wave.fsdb");
        $fsdbDumpvars(0, myfifo);
        $fsdbDumpon();
    end
    */

    //例化
    syn_fifo myfifo(
        .clk(clk),
        .rstn(rstn),
        .wr_en(wr_en),
        .rd_en(rd_en),
        .fifo_full(fifo_full),
        .fifo_empty(fifo_empty),
        .wr_data(wr_data),
        .rd_data(rd_data)
    );

    initial begin
        rstn = 1;
        wr_en = 0;
        rd_en = 0;


        repeat(2) @(negedge clk);  
        rstn = 0;

        @(negedge clk);  
        rstn = 1;

        @(negedge clk);  
        wr_data = {$random}%60;
        wr_en = 1;

        repeat(2) @ (negedge clk);
        wr_data = {$random}%60;

        @(negedge clk);
        wr_en = 0;
        rd_en = 1;

        repeat(4) @ (negedge clk);
        rd_en = 0;
        wr_en = 1;
        wr_data = {$random}%60;

        repeat(5) @ (negedge clk);
        wr_data = {$random}%60;

        repeat(2) @ (negedge clk);
        wr_en = 0;
        rd_en = 1;

        repeat(2) @ (negedge clk);
        rd_en = 0;
        wr_en = 1;
        wr_data = {$random}%60;

        repeat(3) @ (negedge clk);
        wr_en = 0;

        #50 $finish;
    end

    initial begin
        clk = 0;
        forever #5 clk = ~clk;
    end
endmodule



在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值