由于要对FPGA读写SDRAM的工程进行调试,第一步就是验证PLL模块的功能,故结合网上找的一些资料,进行了如下PLL仿真实验。
下面是仿真的全过程
- 首先,看一下Quartus中的PLL模块:
从上面图中可以看出:我的FPGA输入时钟是20MHZ,该PLL有三个输出,其中
C0:5倍频,100MHZ
C1:1倍频,20MHZ
C2:5倍频,100MHZ,同时相对于C0延时2ns,也就是72度的相位差。
- 下面,新建一个Modelsim的工程。然后在工程目录下新建两个文件夹,分别为src以及modelsim,如图所示
- 下面,给工程添加库文件,源文件以及激励文件:
`timescale 1 ps / 1ps modulepll_module( clk, reset, clk_20m, clk_100m, sdram_clk, sys_reset ); inputclk; inputreset; outputclk_20m; outputclk_100m; outputsdram_clk; outputsys_reset; clk_ctrl clk_ctrl_u1 ( .areset(reset), .inclk0(clk), .c0(clk_20m), .c1(clk_100m), .c2(sdram_clk), .locked(sys_reset) ); endmodule
<span style="font-size: 13px; "><span style="font-family:'Microsoft YaHei';">`timescale 1 ps / 1ps modulepll_module_tb; regclk; regreset; wireclk_100m; wireclk_20m; wiresdram_clk; wiresys_reset; pll_module u1( .clk(clk), .reset(reset), .clk_20m(clk_20m), .clk_100m(clk_100m), .sdram_clk(sdram_clk), .sys_reset(sys_reset) ); initial beginclk = 0; reset=0; end always #25000 clk = ~clk; endmodule</span></span>
由于仿真以ps为单位,而FPGA的输入时钟为20MHZ,即每周期50ns=50000ps,所以上面代码中的clk每25000个仿真时间进行一次翻转。
- 下面,我们可以开始准备仿真了。通常我们都是先编译,然后在添加波形文件,然后run xxxxxx ;这样比较繁琐,其实用命令往往比较方便快捷。
<span style="font-size: 13px; "><span style="font-family:'Microsoft YaHei';">#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/altera_mf.v vlog E:/Project/ModelSim/sdram_test/src/220model.v vlog E:/Project/ModelSim/sdram_test/src/clk_ctrl.v vlog E:/Project/ModelSim/sdram_test/src/pll_module.v vlog E:/Project/ModelSim/sdram_test/src/pll_module_tb.v #Start simulation vsim -novopt work.pll_module_tb #add wave add wave -hex /* run 500000000</span></span>
- 现在,整个modelsim工程的文件结构如下:
下面,右键点击pll.do,选择execute就可以执行该脚本了。modelsim会自动帮您把所有事情搞定。(这一过程时间比较长,请耐心等待一会),结果如下图:
不难看出,从波形上看,是满足预先的设想的。下面可以放大来看一下
从放大的图片可以看出,两个100m的时钟之间确实存在相位差,换算成时间约为2ns,这也就验证了我的PLL模块的功能。