• [转]用ModelSim仿真FIFO


    文章转自:http://blog.csdn.net/ruby97/article/details/7348939

    由于仿真FIFO需要时钟资源,故使用了前一篇文章中使用的PLL模块。

    在仿真FIFO模块时,我使用了一个数据发生模块,参考的下面这篇文章中的源码

    datagene.v (可以去链接网址下载源码)

    数据发生模块的输入输出框图如下所示:

    我在Modelsim中利用了该模块进行FIFO的仿真。若对FIFO的IP核不熟悉,可以参考官方文档:http://www.altera.com/literature/ug/ug_fifo.pdf

    下面是具体仿真过程:

    首先,看一下FIFO配置:

    数据单元位宽:16

    FIFO最大数据量:512个

    读和写使用不同的时钟

    OK,下面给出FIFO模块的框图:

    找到Quartus中生成的FIFO模块的 verilog文件,把它复制到Modelsim工程中;此外,FIFO仿真还需要的文件是:

    • Altera库文件:altera_mf.v ,220_model.v (前一篇有提到这两个文件的位置)
    • 数据发生器文件:datagene.v (参考特权同学的博客,里面可以下载到)
    • PLL模块:sys_ctrl.v clk_ctrl.v前一篇博文有提到
    • FIFO模块:wrfifo.v 
    • 模块封装以及测试文件
    所有文件加入工程后如下所示:
     
    其中,write_fifo_module.v代码如下:
    module write_fifo_module   
    (  
        wrf_din,          
        clk_100m,     
        clk_20m,  
        sdram_wr_ack,  
        wrf_wrreq,    
        sys_data_in,  
        wrf_use  
    );  
      
        input   [15:0]   wrf_din;      //data write to FIFO  
        input            clk_100m;     //write clock  
        input          clk_20m;      //read  clock  
        input            wrf_wrreq;    //write fifo request  
        input            sdram_wr_ack; //read fifo request  
        output  [15:0]  sys_data_in;  //read-data  
        output  [8:0]   wrf_use;      //the count of data in fifo  
          
    wrfifo          uut_wrfifo(  
                        .data(wrf_din),  
                        .rdclk(clk_20m),  
                        .rdreq(sdram_wr_ack),  
                          
                        .wrclk(clk_100m),  
                        .wrreq(wrf_wrreq),  
                        .q(sys_data_in),  
                        .wrusedw(wrf_use)  
                        );    
    endmodule  
    
    

    下面是fifo_test_module.v 源码

    `timescale 1 ps /1 ps  
      
    module fifo_test_module(  
        clk,  
        reset,  
        clk_20m,  
        clk_100m,  
        clk_sdram,  
        system_reset,  
        sdram_rd_ack,  
        sdram_wr_ack,  
        syswr_done,  
        write_fifo_req,  
        write_fifo_data_in,  
        moni_addr,  
        sys_data_in,  
        wrf_use  
    );  
      
    input clk;  
    input reset;  
      
    output clk_20m;  
    output clk_100m;  
    output clk_sdram;  
    output system_reset;  
      
    input sdram_rd_ack;  
    input sdram_wr_ack;  
      
    output syswr_done;  
    output write_fifo_req;  
    output [15:0]write_fifo_data_in;  
    output [21:0]moni_addr;  
    output [15:0]sys_data_in;  
    output [8:0]wrf_use;  
      
    sys_ctrl        uut_sysctrl(  
                        .clk(clk),  
                        .rst_n(reset),  
                        .sys_rst_n(system_reset),  
                        .clk_20m(clk_20m),  
                        .clk_100m(clk_100m),  
                        .sdram_clk(clk_sdram)  
                        );  
      
    datagene            uut_datagene(  
                            .clk_20m(clk_20m),  
                            .clk_100m(clk_100m),  
                            .rst_n(system_reset),  
                            .wrf_din(write_fifo_data_in),  
                            .wrf_wrreq(write_fifo_req),  
                            .moni_addr(moni_addr),  
                            .syswr_done(syswr_done),  
                            .sdram_rd_ack(sdram_rd_ack)  
                        );  
      
    write_fifo_module    uut_write_fifo_module(  
                 .wrf_din(write_fifo_data_in),        
                   .clk_100m(clk_100m),   
                   .clk_20m(clk_20m),  
                   .sdram_wr_ack(sdram_wr_ack),  
                   .wrf_wrreq(write_fifo_req),    
                   .sys_data_in(sys_data_in),  
                   .wrf_use(wrf_use)                                      
                        );  
    endmodule  

    最后,是测试激励fifo_test_module_tb的代码:

    `timescale 1 ps /1 ps  
      
    module fifo_test_module_tb;  
      
    reg clk;  
    reg reset;  
      
    wire clk_20m;  
    wire clk_100m;  
    wire clk_sdram;  
    wire system_reset;  
      
    reg sdram_rd_ack;  
    reg sdram_wr_ack;  
      
    wire syswr_done;  
    wire write_fifo_req;  
    wire [15:0]write_fifo_data_in;  
    wire [21:0]moni_addr;  
    wire [15:0]sys_data_in;  
    wire [8:0]wrf_use;  
      
    fifo_test_module fifo_test_module_uut(  
        .clk(clk),  
        .reset(reset),  
        .clk_20m(clk_20m),  
        .clk_100m(clk_100m),  
        .clk_sdram(clk_sdram),  
        .system_reset(system_reset),  
        .sdram_rd_ack(sdram_rd_ack),  
        .sdram_wr_ack(sdram_wr_ack),  
        .syswr_done(syswr_done),  
        .write_fifo_req(write_fifo_req),  
        .write_fifo_data_in(write_fifo_data_in),  
        .moni_addr(moni_addr),  
        .sys_data_in(sys_data_in),  
        .wrf_use(wrf_use)  
    );  
      
      
      
     initial  
     begin  
         clk = 0;  
         reset=1;  
         sdram_rd_ack=0;  
         sdram_wr_ack=0;  
         #500000000 sdram_rd_ack=1;  
         #1000000 sdram_rd_ack=0;  
     end  
       
     always #25000 clk = ~clk;  
       
     always #4000000 sdram_wr_ack=~sdram_wr_ack;  
      
      
    endmodule  

    OK,下面编写ModelSim命令文件: fifo.do

    #Creat a work lib  
    vlib work   
    #Map the work lib to current lib  
    vmap work work  
       
    #Compile the source files  
    vlog E:/Project/ModelSim/sdram_test/src/lib/altera_mf.v  
    vlog E:/Project/ModelSim/sdram_test/src/lib/220model.v  
    vlog E:/Project/ModelSim/sdram_test/src/pll/clk_ctrl.v  
    vlog E:/Project/ModelSim/sdram_test/src/pll/sys_ctrl.v  
    vlog E:/Project/ModelSim/sdram_test/src/data_gen/datagene.v  
    vlog E:/Project/ModelSim/sdram_test/src/fifo/wrfifo.v  
    vlog E:/Project/ModelSim/sdram_test/src/fifo/write_fifo_module.v  
    vlog E:/Project/ModelSim/sdram_test/src/fifo/fifo_test_module.v  
    vlog E:/Project/ModelSim/sdram_test/src/fifo_test_module_tb.v  
       
    #Start simulation  
    vsim  -novopt work.fifo_test_module_tb  
       
    #add wave  
    add wave -hex /*  
      
      
       
    run 200us

    下面就可以观察波形了。。:)))

    首先,可以看到,在385000ps时,PLL模块初始化完成,可以看到clk_20m,clk_100m,clk_sdram的波形了。

    系统运行到约100us时,产生了第一次写FIFO请求信号

    下面为了观察FIFO的时序,我们把波形放大:

    图不是很清晰,只能看清大概,下面具体分析一下:(两个图是连续的,游标位置没有变)

    clk_20m:读FIFO时钟

    clk_100m:写FIFO时钟(可能会觉得奇怪,为什么读FIFO写到SDRAM的时钟比 写FIFO时钟还慢,确实,原本都是100M,我为了实验,把读时钟改为了20M)

    sdram_wr_ack : FIFO读请求信号(这里命名很奇怪。。是因为后面要接SDRAM,写SDRAM即:读FIFO的数据写到SDRAM),高电平有效

    write_fifo_req :表示FIFO写请求信号,高电平有效

    write_fifo_data_in :写入FIFO的数据(由数据发生器产生)

    sys_data_in :FIFO读出的数据

    wrf_use:当前FIFO队列里存在的数据个数

     先看写FIFO的过程,每一个时钟(clk_100m)上升沿,判断写请求信号是否为高电平,如果为高电平,那么就将数据线上的数据写入FIFO,然后在下一个时钟上升沿,wrf_use增加1,表示FIFO队列里的数据增加了一个。

    细心的朋友可能会发现,其实在这一过程中,读请求信号一直为高电平,仔细分析这两张图片,大概可以得出如下判断:

    在每个读时钟的上升沿,首先判断读请求信号是否为高电平,若为高电平,再判断FIFO是否为空,如果不为空,那么在下一个read_clock的上升沿将数据读出,具体可看下图:

    不难发现,第一个read_clock上升沿,FIFO为空;第二个上升沿,FIFO不为空,准备开始读出数据;第三个上升沿,读出数据,同时wrf_use要减1,

    而wrf_use是由write_clock维护的,故在下一个写时钟的上升沿,更新wrrf_use (8变成7)。

    ---------------------------------------------------------------------------------------------------------------------

    再看一副图,下一个8*16bit 数据,道理还是和上面的一样。

    下面看一下读请求为低电平的情况

    不难看出,wrf_use随着数据的写入而增加

    在累积了一段时间数据后,又迎来了读请求信号,看下图:(还是:上升沿判断,下一个上升沿读取。。。),不再赘述

  • 相关阅读:
    于丹的婚姻观
    相貌与成功的关系—俞敏洪6月2号在同济大学的演讲
    NetBeans IDE 6.9.1 发布
    NetBeans IDE 6.9.1 发布
    NetBeans 时事通讯(刊号 # 112 Aug 05, 2010)
    VS Feature Pack学习之使用CMFCMenuBar自定义菜单栏
    使用 Apache Wink、Eclipse 和 Maven 开发 RESTful Web 服务
    Have to run sudo dhclient eth0 automatically every boot
    java regex
    HTTPCLIENT 解决乱码方案 linfeng_0212的日志 网易博客
  • 原文地址:https://www.cnblogs.com/woshitianma/p/2832056.html
Copyright © 2020-2023  润新知