在模块化设计过程中编写testbench并仿真的方法介绍

仿真第1个子模块
  在开始设计前,根据设计划分好各功能模块(为了叙述方便,这里以对“fpga数字信号处理(十三)锁相环位同步技术的实现”中设计的系统仿真为例)。编写好第一个子模块(本例中为双相时钟生成模块),在vivado中添加仿真sim文件,编写testbench:
`timescale 1ns / 1ps//-----------------------------------------------------//   双相时钟信号生成模块测试//-----------------------------------------------------module clk_gen_sim;reg clk, rst;wire clk_d1, clk_d2;clk_gen i1(    .clk(clk),      //32mhz系统时钟    .rst(rst),      //高电平有效复位信号    .clk_d1(clk_d1),  //时钟1    .clk_d2(clk_d2)   //时钟2);always #10 clk = ~clk;initial begin    clk = 1'b1;    rst = 1'b1;    #50;    rst = 1'b0;    #1000; $stop;endendmodule  
  综合正确后,点击“run simulation”->“run behavioral simulation”进行行为仿真,仿真结果如下图:
仿真结果正确(即功能与预期相符),则表明该子模块设计正确,可以开始下一个子模块的设计和仿真。
加入第n个子模块
  和上节一样,设计好一个子模块,则添加一个仿真激励testbench文件,在仿真中确认功能正确性。最终的仿真文件清单如下所示:
vivado对多模块、多文件的仿真提供了很好的特性支持。上面有多个testbench文件,分别对不同的模块进行仿真。当仿真好第一个模块后,需要仿真第二个模块时,对第一个模块对应的testbench点右键->“disable file”,并将第二个模块对应的testbench点右键->“set as top”(当状态为enable的仿真文件只有一个时会自动设置为top),如下图所示:
如果想要重新仿真先前的模块,在testbench文件上点右键->“enable file”即可重新将其置为有效。通过这样的方法可以完成所有模块的仿真。
多模块联合仿真
  我们知道,模块化设计的代码,各个模块之间的联系是非常紧密的。对于简单的设计还比较好,可以像上节一样每个模块单独测试,各自编写testbench也并不复杂。而更多的设计在仿真时我们期望能直接使用第一个模块产生的信号,作为第二个模块的测试激励,即多模块联合仿真。比如在“fpga综合系统设计(七)基于ddc的两路信号相位差检测 ”中,在仿真ddc模块(数字下变频)时显然更希望直接使用信号生成模块(signal_gen)中产生的信号作为激励,而不是另外在testbench中生成一个信号作为激励。否则不仅费时费力,也没有测试到模块之间连接的正确性。
方法有两个:第一个是先编写好设计的顶层模块,不断的将子模块实例化到顶层模块中,只对顶层模块做仿真;第二个是在testbench中把需要的子模块都实例化好。
1. 第一种方法
  vivado可以观察模块的内部信号,在运行顶层模块的仿真后,scope窗口内显示了顶层模块内包含的所有子模块。如下图所示:
仿真波形窗口内默认只显示顶层模块的接口和在testbench文件中定义的变量。如果要观察子模块内部的信号,在子模块上右键->“add to wave window”,即可将相关信号添加到波形窗口。
借助于vivado的这个特性,可以在设计过程中不断在顶层模块中实例化子模块,达到多模块联合仿真的目的。这样做的优点是在编写testbench代码上更省力,缺点是只有一个顶层模块的testbench,无法对各个子模块进行单独测试。
2. 第二种方法
  在仿真一个子模块时希望用到其它子模块的输出信号,将两者都在testbench中实例化即可。和下面testbench代码类似:
`timescale 1ns / 1psmodule clk_iq_sim;reg clk, rst;wire clk_d1, clk_d2;wire clk_i, clk_q;clk_gen i1(    .clk(clk),      //32mhz系统时钟    .rst(rst),      //高电平有效复位信号    .clk_d1(clk_d1),  //时钟1    .clk_d2(clk_d2)   //时钟2);/*使用clk_gen模块的输出信号作为该模块的输入激励*/clk_iq i2(    .clk(clk),      //32mhz系统时钟    .rst(rst),      //高电平有效复位信号    .clk_d1(clk_d1),  //时钟1    .clk_d2(clk_d2),  //时钟2    .clk_i(clk_i),    .clk_q(clk_q));always #10 clk = ~clk;initial begin    clk = 1'b1;    rst = 1'b1;    #50;    rst = 1'b0;    #1000; $stop;endendmodule  
  这样做的好处是仍然可以保持每一个子模块都有一个对应的仿真激励文件,更方便功能测试和文件管理。尤其在经常需要修改和运行仿真的设计中,单独测试一个模块的运行时间比运行总体的顶层模块仿真要节省不少时间。
使用quartus+modelsim
  vivado自带的仿真(vivado simulation)已经足够好用,而使用quartus时,由于其自带的波形仿真工具并不方便,经常需要调用modelsim来仿真。使用quartus+modelsim也可以达到上面的效果。
多仿真文件的管理在quartus主界面的assignments菜单->settings窗口中,如下图所示:
点击eda tool settings下的simulation,在test benches窗口中可以添加和管理多个testbench文件。在compile test bench的下拉菜单里选择指定的一个testbench,调用modelsim仿真时会读取相应的文件。
modelsim仿真过程中也可以观察到顶层模块内部子模块的信号。在sim-default窗口下可以看到顶层模块和子模块之间的实例化信息,选中相应的子模块,在objects窗口(如果没有则在modelsim主界面的view菜单中选中打开)下会显示出该子模块的相关信号。
对需要显示的信号点右键->“add to”->“wave”->“selected signals”,即可添加到波形窗口。点击“run-all”重新运行仿真,新添加信号的波形便会显示出来。


一周大事件:欧普照明与整装领域先行者名匠装饰举行战略签约仪式
安装与维护齿轮减速电机时需注意的事项
Redmi K30系列曝光将率搭载高通最新的5G处理器
正点原子emmc和nand的区别
称重传感器的七种类型及常见作用途!
在模块化设计过程中编写testbench并仿真的方法介绍
VIVA (昱盛电子) VP2123 3A/21V/340kHz Synchronous Buck Converter
SpaceX将Starlink卫星网络的公开测试扩展到加拿大和英国
同步复位与异步复位的区别
ELEXCON2016:重新定义电子展
FPGA的优势和汽车电子主流需求吻合 利用FPGA提供灵活的解决方案
双十二移动电源选购指南:支持快充的移动电源分享
2030年,无人机市场的价值将达到558亿美元
数据成物联网家电核心
物联网安防在智慧社区的应用
一款中国产的LED灯被欧盟召回 被指不符合低电压指令
引起高压线缆故障的五种原因及其解决办法
柯力传感完成对COMS激光测量传感器研发商点联传感的天使轮投资
buck电路如何调整占空比?
智能变电站的发展方向