用ModelSim仿真FIFO
2013-02-28 12:24
357 查看
由于仿真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代码如下:
[plain] view
plaincopy
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 源码
[plain] view
plaincopy
`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的代码:
[plain] view
plaincopy
`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
[plain] view
plaincopy
#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随着数据的写入而增加
在累积了一段时间数据后,又迎来了读请求信号,看下图:(还是:上升沿判断,下一个上升沿读取。。。),不再赘述
OK,今天的仿真就到这里吧。。
在仿真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代码如下:
[plain] view
plaincopy
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 源码
[plain] view
plaincopy
`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的代码:
[plain] view
plaincopy
`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
[plain] view
plaincopy
#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随着数据的写入而增加
在累积了一段时间数据后,又迎来了读请求信号,看下图:(还是:上升沿判断,下一个上升沿读取。。。),不再赘述
OK,今天的仿真就到这里吧。。
相关文章推荐
- 用ModelSim仿真FIFO
- modelsim仿真fifo和rom时候,输出出现高阻
- 使用modelsim直接仿真IP(FIFO)
- Modelsim LPM(fifo, PLL)仿真关注
- [转]用ModelSim仿真FIFO
- 用ModelSim仿真FIFO .
- ise调用modelsim时,怎么改变仿真时间呢
- 别的电脑上的ISE工程放到本电脑上后使用ModelSim仿真时出错的解决办法
- modelsim仿真MCB DDR3 IP核时的报错
- 重定义在ModelSim仿真中的便捷实用
- Verilog语法_4(Modelsim自动化仿真)
- 搭建Modelsim SE仿真环境-使用do文件仿真
- vivado与modelsim的联合仿真(一)
- 关于modelsim仿真出现红线的问题
- Quartus II 与ModelSim-Altera联合仿真FFT IP核之FFT IP调用与自产生信号分析-lab2
- ISE与modelsim联合仿真的问题
- Modelsim高级脚本Do仿真
- ModelSim之命令行仿真入门
- Modelsim仿真查看内部信号
- ModelSim_Altera6.4使用ModelSim_Altera6.3d破解成功,可仿真波形!!!