Testbench编写指南(1)基本组成与示例

article/2025/11/7 12:31:45

对于小型设计来说,最好的测试方式便是使用TestBench和HDL仿真器来验证其正确性。一般TestBench需要包含这些部分:实例化待测试设计、使用测试向量激励设计、将结果输出到终端或波形窗口便于可视化观察、比较实际结果和预期结果。下面是一个标准的HDL验证流程:
这里写图片描述
TestBench可以用VHDL或Verilog、SystemVerilog编写,本文以Verilog HDL为例。FPGA设计必须采用Verilog中可综合的部分子集,但TestBench没有限制,任何行为级语法都可以使用。本文将先介绍TestBench中基本的组成部分。


生成时钟信号

使用系统时钟的设计在TestBench中必须要生成时钟信号,该功能实现起来也非常简单,示例代码如下:

parameter ClockPeriod =  10;//方法1
initial beginforever clock = #(ClockPeriod/2) ~ Clock;
end//方法2
initial beginalways #(ClockPeriod/2) Clock = ~Clock;
end     

生成测试激励

只有给设计激励数据,才能得到验证结果。提供激励的方法有两种,绝对时间激励以仿真时刻0为基准,给信号赋值,示例如下:

initial beginreset = 1;load = 0;count = 0;#100 reset = 0;#20 load = 1;#20 count = 1;
end

‘#’用于指定等待的延迟时间,之后才会执行下一个激励。相对时间激励给信号一个初始值,直到某一事件发生后才触发激励赋值,示例如下:

always @ (posedge clk)tb_cnt <= tb_cnt + 1;initial beginif (tb_cnt <= 5) beginreset = 1;load = 0;count = 0;endelse beginreset = 0;load = 1;count = 1;end
end

根据需要,可以同时使用两种方法。每一个initial块、always块之间都是并行工作的关系,但在initial块内部是顺序地处理事件。因此复杂的激励序列应该分散到多个initial或always块中,以提高代码可读性和可维护性。


显示结果

Verilog中可以使用$display和$monitor系统任务来显示仿真结果,示例代码如下:

initial begin$timeformat(-9, 1, "ns", 12);$display("    Time clk rst ld sftRg data sel");$monitor("%t %b %b %b %b %b %b", $realtime,clock, reset, load, shiftreg, data, sel);
end

$display会将双引号之间的文本输出到终端窗口。$monitor的输出为事件驱动型,如上例中$realtime变量用于触发信号列表的显示,%t表示$realtime以时间格式输出,%b表示其余值以二进制格式输出。其余还有%d、%h、%o等与惯例相同。


简单示例

下面是一个简单的移位寄存器Verilog设计示例:

module shift_reg (clock, reset, load, sel, data, shiftreg);
input clock;
input reset;
input load;
input [1:0] sel;
input [4:0] data;
output [4:0] shiftreg;
reg [4:0] shiftreg;always @ (posedge clock)
beginif (reset)shiftreg = 0;else if (load)shiftreg = data;elsecase (sel)2'b00 : shiftreg = shiftreg;2'b01 : shiftreg = shiftreg << 1;2'b10 : shiftreg = shiftreg >> 1;default : shiftreg = shiftreg;endcase
end
endmodule

下面给出上述设计的TestBench示例:

module testbench; // 申明TestBench名称
reg clock;
reg load;
reg reset; // 申明信号
wire [4:0] shiftreg;
reg [4:0] data;
reg [1:0] sel;// 申明移位寄存器设计单元
shift_reg dut(.clock (clock),.load (load),.reset (reset),.shiftreg (shiftreg),.data (data),.sel (sel));initial begin   // 建立时钟clock = 0;forever #50 clock = ~clock;
endinitial begin   // 提供激励reset = 1;data = 5'b00000;load = 0;sel = 2'b00;#200reset = 0;load = 1;#200data = 5'b00001;#100sel = 2'b01;load = 0;#200sel = 2'b10;#1000 $stop;
endinitial begin   // 打印结果到终端$timeformat(-9,1,"ns",12);$display(" Time Clk Rst Ld SftRg Data Sel");$monitor("%t %b %b %b %b %b %b", $realtime,clock, reset, load, shiftreg, data, sel);
end
endmodule

TestBench中包括实例化设计、建立时钟、提供激励、终端显示几个部分。每个initial块之间都从0时刻开始并行执行。$stop用来指示仿真器停止TestBench仿真(建议每个TestBench中都有至少一个$stop)。$monitor会在终端以ASCII格式打印监测结果。


设计规则

下面给出一些编写TestBench的基本设计规则:

  • 了解仿真器特性:不同的仿真器由不同的特性、能力和性能差异,可能会产生不同的仿真结果。仿真器可分为两类:(1).基于事件,当输入、信号或门的值改变时调度仿真器事件,有最佳的时序仿真表现;(2).基于周期,在每个时钟周期优化组合逻辑和分析结果,比前者更快且内存利用效率高,但时序仿真结果不准确。即使是基于事件的仿真器,在调度事件时采用不同的算法也会影响到仿真性能(比如同一仿真时刻发生了多个事件,仿真器需要按一定的序列依次调度每个事件)。了解仿真器特性有一定必要,但目前最常用的ModelSim、Vivado Simulator等仿真器也已经非常强大。
  • 避免使用无限循环:仿真器调度事件时,会增加CPU和内存的使用率,仿真进程也会变慢。因此除非迫不得已(比如利用forever生成时钟信号),尽量不要使用无限循环。
  • 将激励分散到多个逻辑块中:Verilog中的每个initial块都是并行的,相对于仿真时刻0开始运行。将不相关的激励分散到独立的块中,在编写、维护和更新testbench代码时会更有效率。
  • 避免显示不重要的数据:对于大型设计来说,会有超过10万个事件和大量的信号,显示大量数据会极度拖慢仿真速度。因此最好的做法是每隔N个时钟周期显示重要信号的数据,以保证足够的仿真速度。

http://chatgpt.dhexx.cn/article/KunBOYcc.shtml

相关文章

Device Self-test

DST Device Self-test命令Command CompletionDevice Self-test Operations (Optional)Short Device Self-Test OperationExtended Device Self-Test Operation Device Self-test命令 Device Self-test命令用于开始一个device self-test操作&#xff0c;或者中止一个device self…

Test ignored.

项目场景&#xff1a; springboot 问题描述&#xff1a; 创建单元测试执行后控制台输出&#xff1a; Test ignored. 解决方案&#xff1a; 测试文件路径与项目文件路径不一致造成的。

Shell test命令

概述 Shell中的 test 命令用于检查某个条件是否成立&#xff0c;它可以进行数值、字符和文件三个方面的测试。 或者使用 [ ] 来判断 数值测试 #!/bin/bash num1100 num2100 if test $[num1] -eq $[num2] thenecho 两个数相等&#xff01; elseecho 两个数不相等&#xff01; …

Google Test简述

Google Test简述 Google Test 是由 Google 推出的 C 测试框架&#xff0c;具有稳定、跨平台、快速等特点&#xff0c;能够为 C 开发人员提供有效的单元测试和集成测试工具。Google Test 支持 Linux、macOS 和 Windows 操作系统&#xff0c;同时支持 gcc、clang 和 MSVC 等多种…

8051单片机基础4:数据存储类型(data,idata,xdata,code)

文章目录 存储类型使用方法详细说明8051存储器结构dataidatabdatapdataxdatacode 关于作者 参考来源&#xff1a;Keil > Help > uVision Help > Cx51 Compiler User’s Guide > Language Extensions > Memory Types 存储类型 Cx51编译器可以访问8051的所有存储…

安装xdata步骤

1.修改配置文件/etc/security/limits.conf 修改配置文件/etc/security/limits.conf 在该配置文件中添加&#xff1a; vim /etc/security/limits.conf * soft nofile 65535 * hard nofile 65535修改之后重新SSH连接即可&#xff0c;不需要重启主机或服务 2. 禁用禁用SELINUX …

ObjectARX开发笔记(二)——使用Xdata向AutoCAD图形追加自定义数据

1.自定义数据 ObjectARX开发过程中&#xff0c;有时会使用自定义数据&#xff0c;主要包括&#xff1a; 自定义对象——可以让用户按照自己希望的方式封装数据&#xff0c;并向AutoCAD中添加第三方实体类型&#xff0c;这些实体类型用于与AutoCAD自身实体一样的特性&#xff…

matlab xdata ydata,matlab中set(head1,'xdata',x1,'ydata',y1)什么意思?

满意答案 amuese6418 2014.10.25 采纳率&#xff1a;59% 等级&#xff1a;12 已帮助&#xff1a;8722人 这个主要是set的用法 它是功能 设置对象的属性。 用法 set(H,PropertyName,PropertyValue,…) 用属性值PropertyValue设置关于用参量H 标志的对象(一个或多个)的属性名P…

用Proteus仿真C51时用到xdata时的问题

在用做一个程序&#xff0c;但是51的内存资源太过稀有&#xff0c;使用到较大的数组的时候资源很快就耗尽了&#xff0c;可能会遇到以下错误&#xff1a; src\main.c(195): error C249: DATA: SEGMENT TOO LARGE这时需要用到大模式下编译。 然而在proteus下默认xdata是必须加…

xdata,volatile,extern,static,#pragma 关键字

1. xdata xdata&#xff1a;声明的变量位于外部 RAM 地址范围内某一位置。 2. volatile volatile: 的本意是“易变的” &#xff0c;因为访问寄存器要比访问内存单元快的多&#xff0c;所以编译器一般都会作减少存取内存的优化。当要求使用 volatile 声明变量值的时候&#…

51 单片机 data idata xdata 使用

51 单片机 data idata xdata 使用 简介 该篇文章只提使用&#xff0c;先不详细讲解&#xff0c;使用的原因就是自己写的代码 ROM 超了&#xff01;&#xff01;&#xff01;新建工程默认使用 data Keil 配置如下图 测试芯片FlashRAMSTC15W408AS8Kbyte512byte data idata xd…

TMS XData 4.6.0.1 Full Source XE2-DX10.3

TMS XData 4.6.0.1 Full Source XE2-DX10.3 用于多层REST / JSON HTTP / HTTPS应用服务器开发和ORM远程处理的Delphi框架。 TMS XData功能概述 基于REST / JSON架构样式的服务器 由于它是基于REST / JSON的&#xff0c;因此可以轻松地从不同的客户端平台(如.NET&#xff0c;Jav…

10.扩展数据(XData)

愿你出走半生,归来仍是少年&#xff01; 环境&#xff1a;.NET FrameWork4.5、ObjectArx 2016 64bit、Entity Framework 6. CAD中所有数据库对象都包含一个可以供开发人员进行自定义的对象&#xff1a;XDATA,本文主要针对此对象进行探索。 XDATA的使用中需要使用到部分DXFCOD…

【51】单片机中的data、idata、xdata、code等关键字的作用

说明 data&#xff1a;RAM低128字节&#xff0c;响应速度最快&#xff0c;采用直接寻址方式 idata&#xff1a;RAM高128字节&#xff0c;采用间接寻址方式&#xff0c;速度相对较慢 bdata&#xff1a;片内RAM&#xff0c;位寻址方式 xdata&#xff1a;外部扩展RAM&#xff…

Kmeans算法

Kmeans算法 是最简单的聚类算法之一&#xff0c;算法接受参数 k &#xff1b;然后将事先输入的n个数据对象划分为k个聚类以便使得所获得的聚类满足&#xff1a;同一聚类中的对象相似度较高&#xff1b;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得…

图像分割与实战(一)——基于主动轮廓(snake)的图像分割

1.主动轮廓图像分割算法的概述 1.1主要思想 将图像分割问题转化为轮廓进化问题 1.2工作原理 将一条曲线在内外力的共同作用下&#xff0c;使得曲线逐步收敛到目标轮廓 1.3 算法流程 初始化曲线利用内外力更新曲线判断曲线是否收敛&#xff0c;否则返回第2步 1.4 需要解决…

实时实例分割算法Deep Snake,速度32.3fps|CVPR 2020

论文提出基于轮廓的实例分割方法Deep snake&#xff0c;轮廓调整是个很不错的方向&#xff0c;引入循环卷积&#xff0c;不仅提升了性能还减少了计算量&#xff0c;保持了实时性&#xff0c;但是Deep snake的大体结构不够优雅&#xff0c;应该还有一些工作可以补&#xff0c;推…

数字图像处理笔记——Snakes算法、活动轮廓以及水平集(Snakes, active contours, and level sets)

Snakes算法 上一讲我们讲的图像分割算法主要是基于像素的&#xff0c;这一讲主要是基于曲线的。我们希望能得到一个能够包围住图像轮廓的平滑的曲线&#xff0c;snakes算法就是一个很有用的算法。首先我们将曲线的坐标x、y同一用参数s表示&#xff0c;s范围从0-1代表从起点绕曲…

Deep Snake for Real-Time Instance Segmentation:基于Deep Snake的实例实时分割

本文针对自己所看的 Deep Snake 做一个总结和存档&#xff0c;也方便其他同学学习 —— 阿波&#xff0c;2020.4.23 论文原文&#xff1a;Deep Snake for Real-Time Instance Segmentation 代码地址&#xff1a; snake 本篇文章工作有以下贡献&#xff1a; •提出了一种基于…