目录

1. 完整的TESTBENCH文件结构

2.时钟激励产生

3.复位信号设计

4.双向信号设计

5. 特殊信号设计

6.仿真控制语句以及系统任务描述

7.加法器的仿真测试文件编写


  

Verilog功能模块HDL设计完成后,并不代表设计工作的结束,还需要对设计进行进一步的仿真验证。掌握验证的方法,即如何调试自己的程序非常重要。在RTL逻辑设计中,要学会根据硬件逻辑来写测试程序即写Testbench。Verilog测试平台是一个例化的待测(MUT)模块,重要的是给它施加激励并观测其输出。逻辑块与其对应的测试平台共同组成仿真模型,应用这个模型就可以测试该模块能否符合自己的设计要求。

  编写TESTBENCH的目的就是为了测试使用HDL设计的电路,对其进行仿真验证、测试设计电路的功能、性能与设计的 预期是否相符。通常,编写测试文件的过程如下:

  • 产生模拟激励(波形)
  • 将产生的激励加入到被测试模块中并观察其响应;
  • 将输出响应与期望值比较。

1. 完整的TESTBENCH文件结构

module Test_bench()//一般简单的测试文件无输入输出信号或变量声明定义逻辑设计中输入信号在这里对应reg型变量逻辑设计中的输出信号在这里对应wire型使用initial或always语句块产生激励例化猜测是模块UT监控和比较输出响应endmodule

2.时钟激励产生

下面列举一些常用的生成时钟激励的方法:

方法一: forever

//*========================================================50%占空比时钟
==========================================================*//
parameter ClockPeriod = 10 ;initialbeignclk_i = 0;forever # (ClockPeriod/2) clk_i = ~clk_i ;end

方法2: always块

//=========================================================50%时钟占空比
==============================================================*/
Parameter ClockPeriod = 10 ;initialbeginclk_i =0 ;always #(ClockPeriod/2) clk_i =~clk_i ;end

方法3:产生固定数量的时钟脉冲

parameter CloclPeriod = 10 ;initialbeginclk_i = 0 ;repeat(6)#(ClockPeriod/2) clk_i =~ clk_i;end

方法4:产生占空比非 50%的时钟

parameter ClockPeriod  =  10 ;initialbeginclk_i = 0 ;foreverbegin#((ClockPeriod/2)-2) clk_i = 0 ;#((ClockPeriod/2)+2) clk_i = 1;endend

3.复位信号设计

方法1:异步复位

initialbeginrst_n_i = 1 ;#100 ;rst_n_i = 0 ;#100 ;rst_n_i = 1;end

方法2:同步复位

initialbeginrst_n_i = 1;@(negedge clk_i)  rst_n_i = 0;#100 ;    //这里给的是固定时间复位repeat(10) @(negedge clk_i) ;  //这里可以设置 固定数量的时钟周期@(negedge clk_i)rst_n_i = 1;end 

方法3:对复位进行任务封装

task reset ;input[31:0] reset_timer  ; //将复位的时间作为输入,达到复位时间可调的目的RST_ING = 0              ;//复位的方式可调,低电平有效或高电平有效beginrst_n = RST_ING ;   //复位中 #reset_time         //设置的复位时间rst_n_i = ~ RST_ING ;end
endtask

4.双向信号设计

双向信号的描述方式并不唯一,常用的方法如下:

描述方式1: inout在testbench中定义为wire型变量

//为双向端口设置中间变量inout_reg作为intou的输出寄存,其中inout变量定义为wire型,使用输出使能控制
//传输的方向
//inout bir_port;wire birport      ;  //将双向接口变量定义为wire型
reg  bir_port_reg ;  //定义一个reg型的中间变量,作为双向口的输出寄存
reg  bi_port_oe   ;  //定义输出使能,用于控制传输的方向assign birport = (bir_port_oe)?bir_port_reg:1'bz;

描述方式2:强制force

当双向端口作为输出端口时,不需要对其进行初始化,而只需开通三态门;当双向接口作为输入时,只需要对其初始化,并关闭三态门,初始化赋值需要使用wire数据,通过force命令来对双向端口进行输入赋值

//assign dinout = (!en)din: 16'hz ; 完成双向赋值initialbeginfor dinout = 20 ;#200 force dinout = dinout -1 ;end

5. 特殊信号设计

1.输入信号任务的封装

方便产生激励数据。

task i_data  ;
input[7:0] dut_data;
begin@(posedge data_en) ;send_data = 0;@(posedge data_en) ;send_data = dut_data[0];@(posedge data_en) ;send_data = dut_data[1];@(posedge data_en) ;send_data = dut_data[2];@(posedge data_en) ;send_data = dut_data[3];@(posedge data_en) ;send_data = dut_data[4];@(posedge data_en) ;send_data = dut_data[5];@(posedge data_en) ;send_data = dut_data[6];@(posedge data_en) ;send_data = dut_data[7];@(posedge data_en) ;send_data = 1;
#100  ;
endendtask//调用该task的方法: i_data(8'hXX) ;

2.多输入信号任务封装

task more_input;input [7:0] a;
input [7:0] b;
input [31:0] times ;
output[8:0] c;beginrepeat(times)                //等待times个时钟上升沿@(posedge clk_i)    c= a+b ;//时钟上升沿, a和b相加
endendtask//调用方法: more_input(x,y,t,z);

3.输入信号产生,一次SRAM写信号产生

initialbegincs_n = 1 ;     //片选无效wr_n = 1 ;     //写使能无效rd_n =1  ;     //读使能无效addr = 8'hxx;  //地址无效data = 8'hxx;  //数据无效#100 ;cs_n = 0 ;wr_n = 0 ;addr = 8'hF1 ;data = 8'h2C ;#100  ;cs_n = 1;wr_n = 1 ;#10  ;addr = 8'hxx;data = 8'hxx;end

Testbench中的 和 wait

//wait都是使用电平触发

intialbeginstart = 1'b1    ;wait(en = 1'b1) ;#10;start = 1'b0    ;end

6.仿真控制语句以及系统任务描述

仿真控制语句以及系统能够任务描述:

$stop        //停止运行仿真,modelsim中可以继续仿真
$stop(n)     //带参数系统任务,根据参数0,1,或2不同,输出仿真信息
$finish      //结束运行仿真,不可继续仿真
$finish(n)   //带参数系统任务,根据参数的不同:0,1或2,输出仿真信息// 0: 不输出任何信息// 1: 输出当前仿真时刻和位置// 2:输出房前仿真时刻、位置和仿真过程中用到的memory以及cpu时间的统计
$random        //产生随机数
$random%n     //产生范围-n到n之间的随机数
{$random}%n    //产生范围0到n之间的随机数

仿真终端显示描述

$monitor    //仿真打印输出,打印出仿真过程中的变量,使其终端显示/*  $monitor($time,,,"clk = %d reset = %d out = %d",clk,reset,out); */$display   //终端打印字符串,显示仿真结果等/*  $display("Simulation start !");$display("At time %t,input is %b %b %b,output is %b",$time,a,b,en,z);*/
$time      //返回64位整型时间
$stime     //返回32位整型时间
$realtiime //实行实型模拟时间

文本输入方式:$readmemb /$readmemh

//激励具有复杂的数据结构 //verilog提供了读入文本的系统函数
$readmemb/$readmemh("<数据文件名>",<存储器名>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>);
$readmemb/$readmemh("<数据文件名>",<存储器名>,<起始地址>,<结束地址>); $readmemb:/*读取二进制数据,读取文件内容只能包含:空白位置,注释行,二进制数
数据中不能包含位宽说明和格式说明,每个数字必须是二进制数字。*/ $readmemh: /*读取十六进制数据,读取文件内容只能包含:空白位置,注释行,十六进制数数据中不能包含位宽说明和格式说明,每个数字必须是十六进制数字。*/ /*当地址出现在数据文件中,格式为@hh...h,地址与数字之间不允许空白位置, 可出现多个地址*/
module ;reg [7:0] memory[0:3];//声明8个8位存储单元
integer i; initial begin$readmemh("mem.dat",memory);//读取系统文件到存储器中的给定地址 //显示此时存储器内容 for(i=0;i<4;i=i+1)  $display("Memory[%d]=%h",i,memory[i]); end
endmodule

mem.dat的文件内容格式:

//mem.dat文件内容
@001
AB CD
@003
A1 //仿真输出为
// Memory[0] = xx;
// Memory[1] = AB;
//Memory[2] = CD;
//Memory[3] = A1; 

7.加法器的仿真测试文件编写

上面只例举了常用的 testbench 写法,在工程应用中基本能够满足我们需求,至于其他更为复杂的 testbench写法,大家可参考其他书籍或资料。

这里提出以下几点建议供大家参考:

  • 封装有用且常用的 testbench,testbench 中可以使用 task 或 function 对代码进行封装,下次利用时灵活调用即可;
  • 如果待测试文件中存在双向信号(inout)需要注意,需要一个 reg 变量来表示输入,一个 wire 变量表示输出;
  • 单个 initial 语句不要太复杂,可分开写成多个 initial 语句,便于阅读和修改;
  • Testbench 说到底是依赖 PC 软件平台,必须与自身设计的硬件功能相搭配。

下面具体看一段程序:

module add(a,b,c,d,e);// 模块接口
input [5:0] a; // 输入信号a
input [5:0] b; // 输入信号b
input [5:0] c; // 输入信号a
input [5:0] d; // 输入信号b output[7:0] e; // 求和输出信号 wire [6:0]outa1,outa2; // 定义输出网线型
assign e = outa2+outa1; // 把两部分输出结果合并 /*
通常,我们模块的调用写法如下:
被调用的模块名字- 自定义的名字- 括号内信号
这里比如括号内的信号,.ina(ina1)
这种写法最常用,信号的顺序可以调换
另外还有一种写法没可以直接这样写
adder u1 (ina1,inb1,outa1);
这种写法必须确保信号的顺序一致,这种写法几乎没有人采用 */ adder u1 (.ina(a),.inb(b),.outa(outa1)); // 调用adder 模块,自定义名字为u1
adder u2 (.ina(c),.inb(d),.outa(outa2)); // 调用adder 模块,自定义名字为u2
endmodule 
//adder 子模块 module adder(ina,inb,outa );// 模块接口
input [5:0] ina; // ina-输入信号
input [5:0] inb; // inb-输入信号
output [6:0] outa; // outa-输入信号
assign outa = ina + inb; // 求和
endmodule // 模块结束 

仿真文件:

`timescale 1ns / 1ps
module add_tb(); reg [5:0] a;
reg [5:0] b;
reg [5:0] c;
reg [5:0] d;
wire[7:0] e;
reg [5:0] i; //中间变量 // 调用被仿真模块模块
add uut (
.a(a),
.b(b),
.c(c),
.d(d),
.e(e)); initial begin    // initial 是仿真用的初始化关键词 a=0 ;  // 必须初始化输入信号 b=0 ;c=0 ;d=0  for(i=1;i<31;i=i+1)begin #10 ; a = i; b = i; c = i; d = i; endend
initial begin $monitor($time,,,"%d + %d + %d + %d ={%d}",a,b,c,d,e); // 信号打印输出#500 $finish; end
endmodule 

仿真波形:

终端显示:

Verilog测试:TestBench结构相关推荐

  1. 简单的Verilog测试模板结构

    这里记录一下曾经用到的简单的测试模板,如下所示: //timescale `timescale 1ns/1ns module tb_module(); //the Internal motivatio ...

  2. verilog测试代码(一)读写文件数据

    1.文件指针定义 一般使用integer进行定义 integer file,file1; file = $fopen("数据文件1.txt","r"); //只 ...

  3. (07)System Verilog 类与结构体区别

    (07)System Verilog 类与结构体区别 1.1 目录 1)目录 2)FPGA简介 3)System Verilog简介 4)System Verilog 类与结构体区别 5)结语 1.2 ...

  4. 四类九种移位寄存器总结(循环(左、右、双向)移位寄存器、逻辑和算术移位寄存器、串并转换移位寄存器、线性反馈移位寄存器LFSR|verilog代码|Testbench|仿真结果)

    移位寄存器总结 一.前言 二.简单循环左移/右移/双向移位寄存器 2.1 简单循环左移/右移/双向移位寄存器 2.2 verilog代码 2.3 Testbench 2.4 仿真结果 三.逻辑移位与算 ...

  5. 模型机设计(VERILOG)-模型机结构与Verilog语言

    前言 模型机是本学期电子电路课程的综合设计实验作业,主要利用数字电路逻辑部分的知识完成一个能实现多个指令的模型机,使用Verilog语言实现各个部件并完成最终的部件连接及验证.         在实现 ...

  6. 七种计数器总结(格雷码计数器、环形计数器、约翰逊计数器、FLSR、简易时分秒数字秒表|verilog代码|Testbench|仿真结果)

    七种计数器总结 一.可复位/置数计数器 1.1 可复位/置数计数器 1.2 Verilog代码 1.3 Testbench 1.4 仿真结果 二.双向(可加可减)计数器 2.1 双向(可加可减)计数器 ...

  7. 线性反馈移位寄存器LFSR(斐波那契LFSR(多到一型)和伽罗瓦LFSR(一到多型)|verilog代码|Testbench|仿真结果)

    线性反馈移位寄存器LFSR 一.前言 二.LFSR简介 三.斐波那契LFSR和伽罗瓦LFSR 3.1 斐波那契LFSR 3.1.1 斐波那契LFSR 3.1.2 verilog代码 3.1.3 Tes ...

  8. Verilog中testbench的设计,文件读取和写入操作

    1. 激励的产生 对于 testbench 而言,端口应当和被测试的 module 一一对应. 端口分为 input,output 和 inout 类型产生激励信号的时候, input 对应的端口应当 ...

  9. 数字分频器设计(偶数分频、奇数分频、小数分频、半整数分频、状态机分频|verilog代码|Testbench|仿真结果)

    数字分频器设计 一.前言 二.偶数分频 2.1 触发器级联法 2.2 计数器法 2.3 verilog代码 2.4 Testbench 2.5 仿真结果 三.奇数分频 3.1 占空比非50%奇数分频 ...

  10. 220V黄金光的LED灯带测试与结构

    ▌01 黄金色LED灯带 本来是在前几天在TB购买的 2835双排金黄光灯带 (¥4.05×2=8.04),它同样是 为了替代传统的感应线圈 用于 全国大学生智能车竞赛 中车模运行时间测量车模通过传感 ...

最新文章

  1. java利用opencv降维_opencv中PCA降维
  2. 英特尔挖走苹果M1芯片功臣,他主导苹果放弃x86架构
  3. 靠二进制画几何[图论]
  4. python os模块安装_二十七、深入浅出Python中的 os模块
  5. jasig CAS实现单点登录(数据库认证)
  6. zephyr 系统--- 内存池使用方法
  7. zookeeper的名词复盘-Stat状态信息
  8. 官宣!.NET官网发布中⽂版
  9. 百练 05 切割回文
  10. properties 配置回车_非常全面的讲解SpringCloud中Zuul网关原理及其配置,看它就够了! - 风平浪静如码
  11. 公钥、私钥和数字签名是什么
  12. 关于PCB板热设计的学习总结
  13. 《第一行代码》ListView控件使用
  14. django中url与view配置方法
  15. idea数据库管理工具配置连接数据库
  16. C语言问题,if条件里面按位取反
  17. PyG利用MessagePassing搭建GCN实现节点分类
  18. mysql异地容灾备份开启log_bin
  19. Java job interview:Java对象持久化的新的规范JDO
  20. Android短信Messaging数据库字段分析

热门文章

  1. R语言中写入Excel的不同sheet表格
  2. ASP.NET 访问项目网站以外的目录文件
  3. qq android qav,33 BK.QQAVManager 音视频管理
  4. 单片机应用案例大全-900套(保持更新)
  5. Docker学习(四)Docker镜像原理 镜像commit操作补充
  6. 同济启明星深基坑支挡结构设计计算软件FRWS 8.1全功能\
  7. DS1302说明文档
  8. 基于jsp+mysql+Spring+SpringMVC+mybatis的ssm学生网上请假系统
  9. java 甘特图_[Java教程]JQuery.Gantt(甘特图)开发
  10. 王道考研计算机网络笔记目录