[转]用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随着数据的写入而增加

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

 

 

 

 

 

 

 

 

转载于:https://www.cnblogs.com/woshitianma/archive/2012/12/25/2832056.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
altera_ug_fifo.pdf audio_dac_fifo.rar FIFO中文应用笔记.pdf FIFO基础知识.doc FPGASoPC软硬件协同设计纵横谈.pdf FPGA的VGA视频输出工程文件// freedev_vga FPGA的VGA视频输出工程文件.rar FreeDev FPGA音频开发环境和平台构建.pdf Nios系统基础上的UItra DMA数据传输模式.doc SD_Card_Audio// Audio_DAC_FIFO_altera的ip核 DE2_SD_Card_Audio sd_audio_aic23.rar SOPC中自定义FIFO接口与DMA数据传输.pdf 什么是FIFO.doc 关于fifo的一些概念其quartus II中IP的使用.doc 在NIOS-II 系统中AD 数据采集接口的设计与实现.doc 基于Avalon总线的TFT LCD 控制器的设计.doc 基于FPGA+PCI的并行计算平台实现 .doc 基于LPM的高速FIFO的设计.doc 基于NiosII的图像采集和显示的实现.doc 基于SOPC的扭振信号测量系统实现研究.doc 基于嵌入式Linux的 TFT LCD IP及驱动的设计.doc 异步FIFO的VHDL设计.doc 采用FPGA的高速数据采集系统.doc 非IP核相关FIFO设计// FIFO技术在SDH数字交叉连接芯片设计中的应用.pdf KPCI-817数据采集卡.pdf PCI-8325光电隔离型模入接口卡技术说明书.doc USB7325高速光电隔离型模入数据采集模块技术说明书.doc 一款低功耗异步FIFO的设计与实现.pdf 一种异步FIFO的设计方法.pdf 关于异步FIFO设计的探讨.pdf 利用FPGA实现异步FIFO设计.doc 基于DSP的高速数据采集与处理系统.pdf 基于FPGA异步FIFO的研究与实现.pdf 基于FPGA的异步FIFO硬件实现.pdf 基于FPGA的异步FIFO设计.pdf 基于FPGA的高速异步FIFO存储器设计.pdf 基于VerilogHDL的异步FIFO设计与实现.pdf 异步FIFO亚稳态问题.doc 异步FIFO结构.pdf 异步FIFO结构及FPGA设计.pdf 怎样对FIFO、RAM读写.doc 读写数据宽度不同的异步FIFO设计.PDF 高速异步FIFO的实现.pdf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值