分享

【原创博文】基于FPGA的异步FIFO验证

 ChinaAET 2020-10-31

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

图1  异步FIFO验证平台

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

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

/*******************************版权申明******************************** **                     电子技术应用网站, CrazyBird **     http://www., http://blog./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., http://blog./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., http://blog./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所示(具体情况可自行分析)。

图2  只写异步FIFO

图3  只读异步FIFO

图4  同时读写异步FIFO

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

 招聘信息 

 

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多