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

图1  异步FIFO验证平台

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

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

/*******************************版权申明********************************

**                     电子技术应用网站, CrazyBird

**     https://www.chinaaet.com, https://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

**     https://www.chinaaet.com, https://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

**     https://www.chinaaet.com, https://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   

            wr_data 

        end

        else if(normal_wr == 1'b1)

        begin

            if(wr_full == 1'b0)

            begin

                wr_en   

                wr_data 

            end

            else

            begin

                wr_en   

                wr_data 

            end

        end

        else

        begin

            wr_en   

            wr_data 

        end

    end

    //******************************************************************

    //  读FIFO信号的产生

    //******************************************************************

    always @(negedge wr_clk or negedge wr_rst_n)

    begin

        if(wr_rst_n == 1'b0)

            rd_en   

        else if(normal_rd == 1'b1)

        begin

            if(rd_empty == 1'b0)

                rd_en   

            else

                rd_en   

        end

        else

            rd_en   

    end

endmodule

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

图2  只写异步FIFO

图3  只读异步FIFO

图4  同时读写异步FIFO

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

招聘信息

查看原文 >>
相关文章