• 基于FPGA的异步FIFO验证


     现在开始对上一篇博文介绍的异步FIFO进行功能验证,上一篇博文地址:http://blog.chinaaet.com/crazybird/p/5100000872 。对异步FIFO验证的平台如图1所示。

    测试平台.jpg

    图1  异步FIFO验证平台

        其中,clock为时钟生成器,asyn_fifo_if为产生异步FIFO读写命令的模块,asyn_fifo为异步FIFO设计模块。

        验证顶层模块testbench的代码如下所示:

    /*******************************版权申明********************************
    **                     电子技术应用网站, CrazyBird
    **     http://www.chinaaet.com, http://blog.chinaaet.com/crazybird
    **
    **------------------------------文件信息--------------------------------
    ** 文件名:          clock.v
    ** 创建者:          CrazyBird
    ** 创建日期:        2016-1-16
    ** 版本号:           v1.0
    ** 功能描述:        时钟生成器
    **                   
    ***********************************************************************/
    // synopsys translate_off
    `timescale 1 ns / 1 ps
    // synopsys translate_on
    module testbench;
        //******************************************************************
        //  变量定义
        //******************************************************************
        wire            wr_rst_n;
        wire            wr_clk;  
        wire            wr_en;   
        wire    [7:0]   wr_data; 
        wire            wr_full; 
        wire    [4:0]   wr_cnt;  
        wire            rd_rst_n;
        wire            rd_clk;  
        wire            rd_en;   
        wire    [7:0]   rd_data; 
        wire            rd_empty;
        wire    [4:0]   rd_cnt;  
        
        //******************************************************************
        //  时钟生成器例化
        //******************************************************************
        clock #(
            .C_CLK_FREQ(100.0)
        )
        u_clock_wr (
            .clk    (   wr_clk  )
        );
        
        clock #(
            .C_CLK_FREQ(70.0)
        )
        u_clock_rd (
            .clk    (   rd_clk  )
        );
        
        //******************************************************************
        //  异步FIFO读写指令产生模块例化
        //******************************************************************
        asyn_fifo_if #(
            .C_DATA_WIDTH(8)
        )
        u_asyn_fifo_if (
            .wr_rst_n   (   wr_rst_n    ),
            .wr_clk     (   wr_clk      ),
            .wr_en      (   wr_en       ),
            .wr_data    (   wr_data     ),
            .wr_full    (   wr_full     ),
            .rd_rst_n   (   rd_rst_n    ),
            .rd_clk     (   rd_clk      ),
            .rd_en      (   rd_en       ),
            .rd_empty   (   rd_empty    )
        );
        
        //******************************************************************
        //  异步FIFO模块例化
        //******************************************************************
        asyn_fifo #(
            .C_DATA_WIDTH(8),
            .C_FIFO_DEPTH_WIDTH (4)
        )
        u_asyn_fifo (
            .wr_rst_n   (   wr_rst_n    ),
            .wr_clk     (   wr_clk      ),
            .wr_en      (   wr_en       ),
            .wr_data    (   wr_data     ),
            .wr_full    (   wr_full     ),
            .wr_cnt     (   wr_cnt      ),
            .rd_rst_n   (   rd_rst_n    ),
            .rd_clk     (   rd_clk      ),
            .rd_en      (   rd_en       ),
            .rd_data    (   rd_data     ),
            .rd_empty   (   rd_empty    ),
            .rd_cnt     (   rd_cnt      )
        );
        
    endmodule

        时钟模块clock的代码实现如下所示(时钟的频率可设置):

    /*******************************版权申明********************************
    **                     电子技术应用网站, CrazyBird
    **     http://www.chinaaet.com, http://blog.chinaaet.com/crazybird
    **
    **------------------------------文件信息--------------------------------
    ** 文件名:          clock.v
    ** 创建者:          CrazyBird
    ** 创建日期:        2016-1-16
    ** 版本号:           v1.0
    ** 功能描述:        时钟生成器
    **                   
    ***********************************************************************/
    // synopsys translate_off
    `timescale 1 ns / 1 ps
    // synopsys translate_on
    module clock(
        clk
        );
        //******************************************************************
        //  参数定义
        //******************************************************************
        parameter   C_CLK_FREQ = 100.0;         //MHz
        localparam  C_CLK_CYCLE = 1000.0 / C_CLK_FREQ;
        
        //******************************************************************
        //  端口定义
        //******************************************************************
        output reg      clk;
        
        //******************************************************************
        //  时钟生成
        //******************************************************************
        initial
        begin
            clk = 0;
            forever #(C_CLK_CYCLE/2)
                clk = ~clk;
        end
        
    endmodule

        本次测试的步骤如下所示:

        (1)只写异步FIFO

        (2)只读异步FIFO

        (3)同时读写异步FIFO

        测试步骤的代码在asyn_fifo_if模块中,如下所示:

    /*******************************版权申明********************************
    **                     电子技术应用网站, CrazyBird
    **     http://www.chinaaet.com, http://blog.chinaaet.com/crazybird
    **
    **------------------------------文件信息--------------------------------
    ** 文件名:          asyn_fifo_if.v
    ** 创建者:          CrazyBird
    ** 创建日期:        2016-1-16
    ** 版本号:           v1.0
    ** 功能描述:        产生异步FIFO的读写命令
    **                   
    ***********************************************************************/
    // synopsys translate_off
    `timescale 1 ns / 1 ps
    // synopsys translate_on
    module asyn_fifo_if(
        wr_rst_n,
        wr_clk,
        wr_en,
        wr_data,
        wr_full,
        rd_rst_n,
        rd_clk,
        rd_en,
        rd_empty
        );
        //******************************************************************
        //  参数定义
        //******************************************************************
        parameter C_DATA_WIDTH = 8;
        
        //******************************************************************
        //  端口定义
        //******************************************************************
        output reg                      wr_rst_n;
        input                           wr_clk;
        output reg                      wr_en;
        output reg  [C_DATA_WIDTH-1:0]  wr_data;
        input                           wr_full;
        output reg                      rd_rst_n;
        input                           rd_clk;
        output reg                      rd_en;
        input                           rd_empty;
        
        //******************************************************************
        //  内部变量定义
        //******************************************************************
        reg             normal_wr;
        reg             normal_rd;
        
        
        //******************************************************************
        //  变量初始化
        //******************************************************************
        initial
        begin
            wr_rst_n  = 1'b0;
            rd_rst_n  = 1'b0;
            normal_wr = 1'b0;
            normal_rd = 1'b0;
            #492;
            wr_rst_n  = 1'b1;
            rd_rst_n  = 1'b1;
            #100;
            //只写FIFO
            normal_wr = 1'b1;
            repeat(20) @(negedge wr_clk);
            normal_wr = 1'b0;
            //只读FIFO
            normal_rd = 1'b1;
            repeat(20) @(negedge rd_clk);
            normal_rd = 1'b0;
            //同时读写FIFO
            normal_wr = 1'b1;
            normal_rd = 1'b1;
            repeat(100) @(negedge wr_clk);
            normal_wr = 1'b0;
            normal_rd = 1'b0;
            repeat(20) @(negedge rd_clk);
            $stop;
        end
        
        //******************************************************************
        //  写FIFO信号的产生
        //******************************************************************
        always @(negedge wr_clk or negedge wr_rst_n)
        begin
            if(wr_rst_n == 1'b0)
            begin
                wr_en   <= 1'b0;
                wr_data <= {(C_DATA_WIDTH){1'b0}};
            end
            else if(normal_wr == 1'b1)
            begin
                if(wr_full == 1'b0)
                begin
                    wr_en   <= 1'b1;
                    wr_data <= {$random%((1 << C_DATA_WIDTH)-1)};
                end
                else
                begin
                    wr_en   <= 1'b0;
                    wr_data <= {(C_DATA_WIDTH){1'b0}};
                end
            end
            else
            begin
                wr_en   <= 1'b0;
                wr_data <= {(C_DATA_WIDTH){1'b0}};
            end
        end
        
        //******************************************************************
        //  读FIFO信号的产生
        //******************************************************************
        always @(negedge wr_clk or negedge wr_rst_n)
        begin
            if(wr_rst_n == 1'b0)
                rd_en   <= 1'b0;
            else if(normal_rd == 1'b1)
            begin
                if(rd_empty == 1'b0)
                    rd_en   <= 1'b1;
                else
                    rd_en   <= 1'b0;
            end
            else
                rd_en   <= 1'b0;
        end
        
    endmodule

        modelsim仿真结果如图2~4所示(具体情况可自行分析)。

    只写异步FIFO.png

    图2  只写异步FIFO

    只读异步FIFO.png

    图3  只读异步FIFO

    同时读写异步FIFO.png

    图4  同时读写异步FIFO

        至此,异步FIFO的设计和验证都完成了。现在预告下一篇博文:参数化的优先级编码器设计。哈哈,不要以为很简单哦。记住,是“参数化”,即输入信号的位宽可设置。大家也可以先想想如何实现。也许,灵感一来很快就想出来了,否则,半个小时、1个小时、甚至很多。

    转载:http://blog.chinaaet.com/crazybird/p/5100000874

  • 相关阅读:
    window安装maven仓库
    python代码实现将json中所有字段四舍五入保留n位小数
    Centos搭建Git服务器,添加用户名密码实现多用户管理
    python的测试工具大全
    TypeError: cannot serialize '_io.BufferedReader' object 问题记录
    mysql数据库无法插入中文字符
    jquery的相关用法
    js相关用法
    二分法+装饰器(带返回值,无敌参数,批量执行/取消装饰器)
    网络编程三 Socket
  • 原文地址:https://www.cnblogs.com/chengqi521/p/8392164.html
Copyright © 2020-2023  润新知