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

图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所示(具体情况可自行分析)。

图2  只写异步FIFO

图3  只读异步FIFO

图4  同时读写异步FIFO

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

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

基于FPGA的异步FIFO验证的更多相关文章

  1. 基于FPGA的异步FIFO设计

    今天要介绍的异步FIFO,可以有不同的读写时钟,即不同的时钟域.由于异步FIFO没有外部地址端口,因此内部采用读写指针并顺序读写,即先写进FIFO的数据先读取(简称先进先出).这里的读写指针是异步的, ...

  2. 异步FIFO总结

    异步FIFO总结 异步FIFO的基本概念 异步FIFO读写分别采用相互异步的不同时钟,使用异步FIFO可以在两个不同时钟系统之间快速而方便地传输实时数据 FIFO的常见参数 FIFO的宽度:即FIFO ...

  3. 【iCore、iCore2、iBoard例程】【异步FIFO跨时钟域通信(通过ARM 读FPGA FIFO)】

    欢迎访问电子工程师学堂,以便了解更多内容:http://www.eeschool.org 一.本实验基于iCore2 完成,通过简单改动,即可用在 iCore 核心板.iBoard 电子学堂上. iC ...

  4. 基于FPGA的音频信号的FIR滤波(Matlab+Modelsim验证)

    1 设计内容 本设计是基于FPGA的音频信号FIR低通滤波,根据要求,采用Matlab对WAV音频文件进行读取和添加噪声信号.FFT分析.FIR滤波处理,并分析滤波的效果.通过Matlab的分析验证滤 ...

  5. 异步fifo的设计(FPGA)

    本文首先对异步 FIFO 设计的重点难点进行分析 最后给出详细代码 一.FIFO简单讲解 FIFO的本质是RAM, 先进先出 重要参数:fifo深度(简单来说就是需要存多少个数据)           ...

  6. 异步FIFO的verilog实现与简单验证(调试成功)

    最近在写一个异步FIFO的时候,从网上找了许多资料,文章都写的相当不错,只是附在后面的代码都多多少少有些小错误. 于是自己写了一个调试成功的代码,放上来供大家参考. 非原创 原理参考下面: 原文 ht ...

  7. 异步FIFO的FPGA实现

    本文大部分内容来自Clifford E. Cummings的<Simulation and Synthesis Techniques for Asynchronous FIFO Design&g ...

  8. 基于FPGA的线阵CCD图像测量系统研究——笔记

    本文是对基于FPGA的线阵CCD图像测量系统研究(作者:高尚)的阅读笔记 第一章绪论 1. 读读看 读了前面的摘要依然没有看懂作者要做什么.接着往下读....终于看到了一个字眼“基于机器视觉的图像测量 ...

  9. 基于FPGA的OLED真彩色动态图像显示的实现

    源:基于FPGA的OLED真彩色动态图像显示的实现 作为第3代显示器,有机电致发光器件(Organic Light Emitting Diode,OLED)由于其主动发光.响应快.高亮度.全视角.直流 ...

随机推荐

  1. PS中标尺工具在哪里

    打开photoshop应用程序,然后在PS菜单中点击“视图——标尺”选项即可打开ps标尺栏. 单位设置:      按Ctrl+K快捷键会弹出“首选项”对话框,你选择“单位与标尺”项,在“单位”一栏里 ...

  2. C#.NET常见问题(FAQ)-如何引用定义好的dll文件

    1 添加引用,找到dll文件   2 引用类的名称空间,生成类的实例,调用类的方法,测试OK.     更多教学视频和资料下载,欢迎关注以下信息: 我的优酷空间: http://i.youku.com ...

  3. U盘去保护方法

    一.基本信息 U盘大小是16G的,估计用了2G的空间存储,没有任何开关设置,格式化或写入时提示被写保护: U盘放到任何一台电脑上都是只能读不能写,说明与电脑无关,用了各种U盘修复程序都无效: 二.一般 ...

  4. 单链表的增、删、改、减(C++)

    首先是是一个简单的例子,单链表的建立和输出. 程序1.1 #include<iostream> #include<string> using namespace std; st ...

  5. iOS键盘高度自适应(中英文输入)

    一:添加通知监测键盘高度变化 [self keyBoardAutoSize]; 二:动态改变高度 #pragma mark keyboard height auto /* NSNotification ...

  6. Java从零开始学二十五(枚举定义和简单使用)

    一.枚举 枚举是指由一组固定的常量组成的类型,表示特定的数据集合,只是在这个数据集合定义时,所有可能的值都是已知的. 枚举常量的名称建议大写. 枚举常量就是枚举的静态字段,枚举常量之间使用逗号隔开. ...

  7. 【转】Spring中IoC的优点与缺点

    1. 优点 我们知道,在Java基本教程中有一个定律告诉我们:所有的对象都必须创建:或者说:使用对象之前必须创建,但是现在我们可以不必一定遵循这个定律了,我们可以从Ioc容器中直接获得一个对象然后直接 ...

  8. eclipse no java machine vitual was found

      eclipse no java machine vitual was found CreateTime--2018年4月27日10:41:20 Author:Marydon 1.错误提示 2.问题 ...

  9. 〖Android〗酷派手机固件.cpb文件的分解程序

    /* * ===================================================================================== * * Filen ...

  10. 插入UUID,出现Data truncation: Data too long for column 'id' at row 1

    ssc.udf.register("getuuid", () => UUID.randomUUID().toString) val stuPCountDF_tmp1=ssc. ...