基于modelsim-SE的简单仿真流程

编写RTL功能代码

要进行功能仿真,首先得用需要仿真的模块,也就是RTL功能代码,简称待测试的模块,该模块也就是在设计下载到FPGA的电路。一个电路模块想要有输出,就得有输出,数字电路也是一样的,时钟和复位信号是必不可少的测试激励信号之一,同时可能还包括控制信号、数据信号。这里总结一下,一般系统中包括的测试激励信号主要为四大类:

  1. 系统信号(时钟、时钟使能信号、复位信号等);
  2. 控制信号(使能信号、片选信号、握手信号,状态机控制信号等);
  3. 数据信号(并行接口数据信号、串行接口数据信号等);
  4. 地址信号(模块的地址信号、内部寄存/存储器地址信号等)。

而对于测试结果,在放在不同的测试激励信号的条件下分析,不同的测试激励产生相应的测试结果,通过分析就可以知道相应的测试结果与目标结果是否一致,如果不一致便进行RTL的修改,如果一致则修改测试激励信号,遍历完不同情况下的测试激励,完成整体100%的功能测试,才能确保RTL功能模块的设计功能完整性。

这里需要注意一点,功能仿真正确不一定能确保最后综合、布局布线后下载到FPGA产生的功能结果正确,但是功能仿真不正确,FPGA产生的功能结果一定不正确!所以功能仿真是很必要的!

本实验需要设计一个8bit的计数器,功能很简单,该计数器在每个时钟的上升沿进行加一并将结果输出,当计数到255的时候返回到0重新计数,以此循环,模块接口如下所示。

测试激励信号是时钟和复位信号,时钟信号为50M,复位信号为低电平有效。测试结果为8bit的计数值,范围为0~255,如果从波形上看是一个锯齿波。

module counter(

clk,

reset_n,

counter_out

);

input clk;

input reset_n;

output [7:0]counter_out;

reg [7:0]counter_reg;

assign counter_out = counter_reg;

always @(posedge clk or negedge reset_n)

begin

if(reset_n == 1'b0)

begin

counter_reg <= 8'd0;

end

else

begin

counter_reg <= counter_reg + 1'b1;

end

end

endmodule

编写testbench代码

TestBench基本概念:测试激励->待测RTL功能模块->观察比对波形/在终端打印或生产文本/自动对比输出结果。

TestBench编写三步曲

  1. 对被测试设计的顶层接口进行例化;
  2. 给被测试设计的输入接口添加激励信号;
  3. 判断被测试设计的输出想要是否满足设计要求;

TestBench内容主要分为

  1. 时钟的产生;
  2. 复位的产生;
  3. 控制信号的产生;
  4. 其他激励信号的产生(用户自定义 )。

相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理。

双向端口inout的设置方法:

为双向端口inout设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为wire型变量,然后用输出使能控制传输方向。

inout pin_dir_port;

wire pin_dir_port;

reg pin_dir_port_reg;

reg pin_dir_port_oe;

assign pin_dir_port = pin_dir_port_oe ? pin_dir_port_reg:1'bz;

用pin_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值,等于两个模块之间用inout双向口互连。

本实验的testbench主要是为8bit的计数器产生测试激励信号,即产生50M的时钟信号clk和复位信号reset_n。

一个完成的testbench文件内容主要包括三个部分:

  1. 仿真时间单位;
  2. 待测试模块信号映射;
  3. 激励信号产生;

仿真时间单位

如上图标注所示:`timescale 1 ns/ 10 ps表示,时间单位为1ns,精度为10ps,时间单位应该大于时间精度,不然仿真过程将会报错,同时仿真的时间精度越小,仿真结果的波形的可视精度就越小,对仿真花费时间的要求越高,精度越小,仿真时间越长。

待测试模块信号映射

将测试功能模块映射到testbench中,如图中的标注2所示,一般采用如下格式进行映射,其中测试功能模块的输入信号在testbench中定义为reg信号,因为要在always中进行赋值操作,而测试功能模块的输出信号定义为wire信号,该信号只用于观察,不用于赋值操作。

测试功能模块 例化测试功能模块名(

.输入信号(测试激励信号),

.输出信号(定义为wire型信号进行观察)

);

激励信号产生

激励信号的产生涉及到两个阶段:初始化阶段和赋值操作阶段。初始化阶段在initial模块中进行操作,赋值操作阶段在always模块进行,如下格式。$display为显示语句,括号内双引号内的内容为要显示的内容,该内容将会在modelsim软件的脚本显示窗口中显示出来。

Initial模块只执行一次。

initial

begin

// code that executes only once

// insert code here --> begin

对激励信号进行初赋值操作

// --> end

$display("Running testbench");

end

在初始化完成后,需要对激励信号进行赋值操做,赋值操作在always中进行,always模块一直在执行。本实验时钟信号为50M,定义的时间单位为1ns,所以在每个10ns进行一次翻转,复位信号为低电平有效,所以在初始化的时候设置为低电平,在always模块里面设置为高电平。格式如下所示:

always

// optional sensitivity list

// @(event1 or event2 or .... eventn)

begin

// code executes for every event on sensitivity list

// insert code here --> begin

激励信号赋值操作,持续执行

// --> end

end

testbench代码:

`timescale 1 ns/ 10 ps

module counter_tst();

// constants

// general purpose registers

// test vector input registers

reg clk;

reg reset_n;

// wires

wire [7:0]counter_out;

counter counter_1(

.clk (clk),

.reset_n (reset_n),

.counter_out(counter_out)

);

initial

begin

// code that executes only once

// insert code here --> begin

clk<=1'b0;

reset_n<=1'b0;

// --> end

$display("Running testbench");

end

always

// optional sensitivity list

// @(event1 or event2 or .... eventn)

begin

// code executes for every event on sensitivity list

// insert code here --> begin

#10 clk<=~clk;

reset_n<=1'b1;

// --> end

end

endmodule

创建工程

运行 ModelSim,方法是点击开始->程序->ModelSim SE->ModelSim 或双击桌面上的快捷方式,会出现如下图所示的界面,如果上一次使用ModelSim 建立过工程,这时候会自动打开上一次所建立的工程,可以close project,具体操作:选中工程的文件,右击,在出现的栏目中选择close project。

点击 File->New->Project,会出现如下图所示的界面。

选择project后,会出现如下界面在 Project Name 中我们输入建立的工程名字为counter,在Project Location 中点击browse按键,选择工程保存的路径,注意 ModelSim 不能为一个工程自动建立一个目录,这里最好是选择已经创建好的一个工程文件夹作为目录,在 Default Library Name 中为我们的设计编译到哪一个库中,这里使用默认值,这样,在编译设计文件后,在 Workspace 窗口的 Library中就会出现 work 库。这里我们输入完以后,点击 OK。

在点击OK按键后会出现选择仿真文件的界面,如下图所示,可以点击不同的图标来为工程添加不同的项目,点击 Create New File 可以为工程添加新建的文件, 点击 Add Existing File为工程添加已经存在的文件,点击 Create Simulation 为工程添加仿真,点击Create New Folder 可以为工程添加新的目录。这里我们点击Add Existing File;

这里将前面设计的counter.v文件和counter_tst.v文件包含进工程里面,点击browse按键,将文件包含进来,如下图所示,然后点击ok按键。

接着会在modelsim的工程工作窗口出现如下图所示,即已经将两个文件包含进来,其中在状态那一栏出现两个问号,表明文件包含进来了,还没有进行编译。

每日推送不同科技解读,原创深耕解读当下科技,敬请关注微信公众号“科乎”。

基于modelsim-SE的简单仿真流程—上的更多相关文章

  1. 基于modelsim-SE的简单仿真流程—下

    基于modelsim-SE的简单仿真流程—下 编译 在 WorkSpace 窗口的 counter_tst.v上点击右键,如果选择Compile selected 则编译选中的文件,Compile A ...

  2. 基于modelsim-SE的专业进阶仿真流程

    基于modelsim-SE的专业进阶仿真流程 通过<基于modelsim-SE的简单仿真流程>和<调用altera IP核的仿真流程>是否感受到仿真流程中的繁琐步骤,特别是在m ...

  3. 调用altera IP核的仿真流程—上

    调用altera IP核的仿真流程—上 在学习本节内容之后,请详细阅读<基于modelsim-SE的简单仿真流程>,因为本节是基于<基于modelsim-SE的简单仿真流程>的 ...

  4. 搭建Modelsim SE仿真环境-使用do文件仿真

    本章我们介绍仿真环境搭建是基于Modelsim SE的.Modelsim有很多版本,比如说Modelsim-Altera,但是笔者还是建议大家使用Modelsim-SE,Modelsim-Altera ...

  5. Modelsim SE 仿真 ALTERA FPGA IP

    Modelsim SE 仿真 ALTERA FPGA IP 最近,有几个朋友问过我是不是有新版本的Modelsim altera,其原因是 Qii 升级为新版本的,但是没配套的modelsim,没办法 ...

  6. Modelsim se仿真Xilinx IPcore

    Modelsim se仿真Xilinx IPcore 方法:先写好do文件常规框架,根据modelsim报错再添加ise IP核库仿真文件.注:记得添加并仿真glbl.v全局控制仿真文件到sim/is ...

  7. Modelsim SE自动化仿真——如何将.do文件中自定义的库链接到testbench顶层模块

    我们用Modelsim SE进行仿真时,为了方便,一般会编写.do文件来启动当前仿真.关于.do文件的编写,一般网上都有成型的模板,我们只要稍微改几个参数,就可以符合我们的仿真需求了.但是如果仿真时需 ...

  8. 服务器文档下载zip格式 SQL Server SQL分页查询 C#过滤html标签 EF 延时加载与死锁 在JS方法中返回多个值的三种方法(转载) IEnumerable,ICollection,IList接口问题 不吹不擂,你想要的Python面试都在这里了【315+道题】 基于mvc三层架构和ajax技术实现最简单的文件上传 事件管理

    服务器文档下载zip格式   刚好这次项目中遇到了这个东西,就来弄一下,挺简单的,但是前台调用的时候弄错了,浪费了大半天的时间,本人也是菜鸟一枚.开始吧.(MVC的) @using Rattan.Co ...

  9. 基于Modelsim的直方图统计算法仿真

    一.前言 本篇主要针对牟新刚编著<基于FPGA的数字图像处理及应用>第六章第五节中直方图统计相关类容进行总结,包括代码实现及 基于Modelsim的仿真.书读百遍,其意自现. 2020-0 ...

随机推荐

  1. The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory

    The method getJspApplicationContext(ServletContext) is undefined for the type JspFactory 这是由于项目里面的一些 ...

  2. Delphi_02_Delphi程序的结构

    一.工程文件 program MultiUnit; {$APPTYPE CONSOLE} uses SysUtils, Unit1 in 'Unit1.pas'; begin //引用unit1中的变 ...

  3. Windows10应用Docker部署DoNet Core

    Win10和Mac稳定版的Docker发布了,之前看了下徐磊老师的几篇Docker4Dotnet的文章http://devopshub.cn/2016/07/08/docker4dotnet-1-ov ...

  4. PHP flush()与ob_flush()的区别

    buffer ---- flush()buffer是一个内存地址空间,Linux系统默认大小一般为4096(1kb),即一个内存页.主要用于存储速度不同步的设备或者优先级不同的 设备之间传办理数据的区 ...

  5. push方法的兼容性问题

    在IE8及以下中,不支持aplly方法中的第二个参数是 伪数组 需要对push方法进行封装. 将 push 的判断,放入一个沙箱中: 好处:在页面加载的时候就会执行这段代码,保证了代码只会检测一次 以 ...

  6. Atitit 《控制论原理与概论attilax总结

    Atitit <控制论原理与概论attilax总结 <控制论> 奠基之作,出自创始人维纳.虽然内容权威,但我认为带有相当强烈的个人色彩,且门槛较高,不适合入门.深入研究控制论必看书籍 ...

  7. 玩儿转物联网IoT - 在Beagle Bone Black上运行node.js 程序

    物联网(IoT)技术方兴未艾,智能手环,智能血压计,智能眼镜甚至智能鞋垫都开始进入我们的生活,各种智能设备层出不穷,世界已经到了一个"人有多大胆,地有多大产"的时代,不玩儿点物联网 ...

  8. Parcelable序列化的使用,关于intent.getParcelableArrayExtra的使用

    Parcelable相较于Serializable的效率更高 public class ChargeMode implements Parcelable{ public String name; pu ...

  9. Google C++单元测试框架GoogleTest---Google Mock简介--概念及基础语法

    就在昨天终于做了gtest的分享,我的预研工作终于结束了,感觉离我辞职的日子不远了,毕竟是专注java二百年啊,要告别实习啦.. 这篇是GoogleMock的简介文档,会在后边附带一个自己的例子. 一 ...

  10. android Broadcast介绍

    在Android中,Broadcast是一种广泛运用的在应用程序之间传输信息的机制.而BroadcastReceiver是对发送出来的Broadcast进行过滤接受并响应的一类组件.发送Broadca ...