搜档网
当前位置:搜档网 › verilog HDL的系统任务及testbench写法

verilog HDL的系统任务及testbench写法

verilog HDL的系统任务及testbench写法
verilog HDL的系统任务及testbench写法

verilog HDL的系统任务及testbench写法

硬件知识2010-02-23 14:16:58 阅读22 评论0 字号:大中小订阅

通用的HDL包括VHDL和v erilog HDL

HDL既可以用来design也可以用来test/conf irm

用HDL写出来的测试文件称为test bench

被测试的模块成为dev ice under test,简称DUT,既可以是behav ioral级描述也可以是R TL级或gat e级描述

v erilog simulator是v erilog语言的仿真器,wav ef orm v iewer是波形观测器

test bench中应该例化DU T,对应端口名称可以不同

testbench中使用两种信号类型:wire reg,test中用法与design时一样

wire类型不能在alway s或initial块中使用

reg类型只能在alway s或initial块中使用

initial和alway s是顺序控制模块,但它们之间是在仿真开始时并行执行的

initial和alway s块中可以插入begin end或f ork join来安排执行顺序

tesbench开始需要给所有信号设置初值,一般是一个initial块

默认的wire类型是Z 默认的reg类型是X

`timescale设置了时间步长和时间精度

测试文件中两项重要的元素是clocks和resets

$display和$monitor格式相同,但?不同

task只能在initial或者alway s中被调用,用于将重复出现的操作打包出来单独存放

后仿真时需要库和SDF文件

所有系统任务都以$开头,都只能在initial或alway s模块里(在initial块中只执行一次,在alway s里满足条件将不断执行) 显示、探测、监控任务

%h%H %d%D %b%B %O %o %C%c %S%s %T%t %M%m

以上都以表达式的最大可能值所占用的位数来显示表达式当前值

%0h%0H %0d%0D %0b%0B %0O %0o

以上都以表达式的当前值最小占用的位数来显示表达式当前值

输出时,如果所有位均为不定值,则输出结果为小写的x;所有位均为高阻则输出结果为小写的z

输出时,如果部分位为高阻值,则输出结果为大写的X;部分位为高阻则输出结果为大写的Z

$display $display b $display o $display h

格式:$display("simulation time is %t",$time);

$write $writeb $writeo $writeh

格式: $write("simulation time is %t",$time);

$display$write这两个任务的作用基本相同,唯一的区别就是$display任务执行完以后自动添加一个换行符\n,而$write不自动添加

$display("a=%d");和$write("a=%d\n");作用相同

用于在满足某个条件(如时钟边沿来时)是输出仿真数据

$strobe $strobeb $strobeh $strobeo

格式: $strobe("the f lip-f lop v alue is %b at time %t",q,$time);

用于在指定的时刻之后输出显示仿真数据

$strobe和$display不同之处在于$display是遇到该时刻时执行,$strobe是当前时刻结束(下一时刻开始)时执行

以上任务通常都在alway s块中执行

$monitor $monitorb $monitorh $monitoro

格式: $monitor("at %t, d=%d,clk=%d",$time,d,clk);

连续监控指定的参数,只要参数表中的参数值发生变化,就在当前仿真时刻结束时显示

$monitoron开启所有的$monitor任务$monitoroff关闭所有的$monitor任务

在多模块测试时$monitoron 和$monitoroff用于使能和关闭本模块的监视功能

$display $write $strobe 多用于alway s模块,$monitor用于initial模块

alway s(a or b or c)$display("....");效果与initial $monitor("...");一样

文件的打开与关闭:

$f open打开一个文件(以整数文件指针方式) 格式:integer f ile_pointer=$f open(f ile_name)

$fclose关闭一个文件(以整数文件指针方式) 格式: $fclose(f ile_pointer)

将信息输出到文件:

显示任务写入任务探测任务监控任务都有用于向文件输出信息的相应命令,即

$f display $f display b $f display h $f display o

$f write $f writeb $f writeh $f writeo

$fstrobe $f strobeb $fstrobeh $f strobeo

$f monitor $fmonitorb $f monitorh $f monitoro

与相应的无文件输出命令相比,只是多了打开文件、写入文件、关闭文件三个步骤

从文件中读数据:

$readmemb 读取二进制文件

$readmemh 读取十六进制文件

格式:

$readmemb("<数据文件名>",<存储器名>);

$readmemb("<数据文件名>",<存储器名>,<起始地址>);

$readmemb("<数据文件名>",<存储器名>,<起始地址>,<结束地址>);

仿真控制任务:

$stop

格式: 在initial中#500 $stop

$f inish

格式: 在initial中#500 $f inish

$stop暂停仿真后返回软件操作主窗口,将控制权交给user

$f inish终止仿真后关闭软件操作主窗口

时间显示格式:

$time 返回64位整型时间

$stime 返回32位整型时间

$realtime 返回实型时间

$time 任何时间以`timescale定义的时间单位为单位

$realtime 任何时间以`timescale定义的时间单位+时间精度为单位

随机函数:

$random(seed)

seed必须是reg或者integer寄存器类型,返回的随机数是32位有符号数

$random%60 产生的是-59~59之间的随机数

{$random}%60产生的是0~59之间的随机数

可以让出现时间随机也可以让某些位随机出现1或0

层次命令:模块标示符任务标示符函数标示符程序块标识符,通过层次命令可以访问到任何变量

其他模块中共享task和f unction的方法: 1.使用层次路径名 2.使用头文件.h来包含需要共享的f untion和task VCD文件(v alue change dump文件)是常用的波形记录文件,与波形的作用等同,是一个ASCII文件$dumpon $dumpoff在一个initial块中控制dump的开始和结束

$dumpv ars $dumpf ile 分别在initial中指定VCD文件名(*.dump)和变量

dump系统任务基本都在initial模块中使用

测试模块的构成部分:

测试模块命名:modulename_tb

输入输出信号(与v eilog电路描述文件中的端口属性相反)

initial或alway s块来产生激励信号

initial或alway s块中加入系统任务

模块实例化

测试中常用的波形有两类:

initial块及块内延迟来产生特定序列

alway s块及内内延迟来产生周期性序列

常用alway s块来描述时钟,alway s产生时钟的两种方法;

常用一个initial设置初值;

常用一个initial来设置仿真的启停控制;

initial中用f orev er(无数次)和repeat(有限次)产生循环信号

技巧:(用assign及延迟可以产生相移时钟、模块调用方法可以产生多种规格的时钟、读入.v ec文件中数据以及比较的写法)quartus的语法诊错能力比modesim强,modesim的输入语法显示比quartus好

`include命令:

一个`include命令只能指定一个被包含模块

意义是在包含文件里复制被包含模块的代码

易于将一个模块做成特定功能的块,然后结构化组织起来

使用时由高层include低层模块,所有模块文件放在同一个文件夹内

编写高效率的testbench

Writing Efficient Testbenches 编写高效的测试设计(testbenches) 原文作者:Mujtaba Hamid 注: 一个设计的测试验证是非常重要的。有效的测试可以助我们快速的完成或改善设计。Testbenches建议编写有效的测试代码来通过软件实现可靠的验证。无意中发现,顺手译为中文,以备将来方便。也贴给没有找到更好中文版本的同道人。 Testbenches本意应该是测试平台更合理,但是在中文中阅读起来很不舒服。所以本文中有时译为“测试设计”,“测试代码”,有时干脆是“测试”。 摘要: 应用笔记为HDL验证设计的新手,或者是没有丰富的测试设计经验的逻辑设计者而编写。 测试设计是验证HDL设计的主要手段。本应用笔记为创建或准备和构建有效的测试设计提供准则。它也提供一个为任何设计开发自较验测的测试设计的一个代数方法。 涉及的所有设计文件可以从以下的站点获得: PC: ftp://https://www.sodocs.net/doc/5b13708911.html,/pub/applications/xapp/xapp199.zip UNIX: ftp://https://www.sodocs.net/doc/5b13708911.html,/pub/applications/xapp/xapp199.tar.gz 简介: 由于设计的规模越来越大也越来越复杂,数字设计的验证已经成为一个日益困难和繁琐的任务。验证工程师们依靠一些验证工具和方法来应付这个挑战。对于几百万门的大型设计,工程师们一般使用一套形式验证(formal verification)工具。然而对于一些小型的设计,设计工程师常常发现用带有testbench的HDL仿真器就可以很好地进行验证。 Testbench已经成为一个验证高级语言(HLL --High-Level Language) 设计的标准方法。通常testbench完成如下的任务: 1.实例化需要测试的设计(DUT); 2.通过对DUT模型加载测试向量来仿真设计; 3.将输出结果到终端或波形窗口中加以视觉检视; 4.另外,将实际结果和预期结果进行比较。 通常testbench用工业标准的VHDL或Verilog硬件描述语言来编写。Testbench调用功能设计,然后进行仿真。复杂的testbench完成一些附加的功能—例如它们包含一些逻辑来选择产生合适的设计激励或比较实际结果和预期结果。 后续的章节描述了一个仔细构建的testbench的结构,并且提供了一个自动比较实际结果与预期结果的进行自我检查的testbench例子。 图1给出了一个如上所描述步骤的标准HDL验证流程。由于testbench使用VHDL或Verilog来描述,testbench的验证过程可以根据不同的平台或不同的软件工具实现。由于VHDL 或Verilog是公开的通用标准,使用VHDL或Verilog编写的testbench以后也可以毫无困难地重用(reuse)。

verilog,testbench

Testbench专题所谓testbench,即测试平台,详细的说就是给待验证的设计添加激励,同时观察输出响应是否符合设计要求。 也许我们会把把程序开发出来算作一个工程项目的重大的比例,这在今天的FPGA设计中,并不是如此,往往在仿真验证上的工作量占到一半以上。试想这么一个测试,一个16位的

输入总线,它可以有多少种组合?如果每次随机产生一种输入,用波形的去画一画,眼花! 波形是最直观的测试手段,但不是唯一手段。 一个完整的测试平台如下图所示,

它是分结构组成的,其中对设计测试结果的判断不仅可以通过观察对比波形得到,而且可以灵活使用脚本命令将有用的输出信息打印到终端或者产生文本进行观察,也可以写一段代码让它们自动比较输出结果。 TB的设计是多种多样,可以使用灵活的VERILOG的验证脚本,但是它也是基于硬件语言但是又服务于软件测试的语

言,有时并行有时顺序,只有掌握这些关键点,才能很好服务测试。 技巧1 Tb中的例化应该把INPUT转换成REG,因为待测设计的输入值是由TB 决定的。相应的OUTPUT 就应该转换成WIRE,因为待测设计的输出值不是由tb决定的。这里需要注意Inout端口,在例化中也是一个wire型。

技巧2 时钟产生 第一种:parameter PERIOD=XX; Initial begin Clk=0; Forever #( PERIOD /2) clk =~clk; End 第二种 parameter PERIOD=XX; always begin #( PERIOD /2) clk=0;

# (PERIOD /2) clk=1; End 技巧3 复位信号 Initial begin Reset_task(XX);//注意时间尺度 ……. End Task reset_task; Input [15:0]reset_time; Begin Reset=0; # reset_time;

怎样写testbench(内有一个实例分析)

怎样写testbench 本文的实际编程环境:ISE 6.2i.03 ModelSim 5.8 SE Synplify Pro 7.6 编程语言 VHDL 在ISE中调用ModelSim进行仿真 一、基本概念和基础知识 Testbench不仅要产生激励也就是输入,还要验证响应也就是输出。当然也可以只产生激励,然后通过波形窗口通过人工的方法去验证波形,这种方法只能适用于小规模的设计。 在ISE环境中,当前资源操作窗显示了资源管理窗口中选中的资源文件能进行的相关操作。在资源管理窗口选中了testbench文件后,在当前资源操作窗显示的ModelSim Simulator中显示了4种能进行的模拟操作,分别是:Simulator Behavioral Model(功能仿真)、Simulator Post-translate VHDL Model(翻译后仿真)、Simulator Post-Map VHDL Model(映射后仿真)、Simulator Post-Place & Route VHDL Model(布局布线后仿真)。如图1所示: 图1 l Simulator Behavioral Model 也就是所说的功能仿真、行为仿真、前仿真。验证功能是否正确,这是设计的第一步。功能仿真正确的程序不一定能被正确综合,也 就是硬件实现。有的在综合时报错误,有的虽然能综合但结果并不正确。当然,功 能仿真如果都不能通过,以后的步骤也就无法进行。这是必做的仿真。 l Simulator Post-translate VHDL Model 也就是翻译后仿真。对源程序进行编译后首先排除了语法错误,对一些像类属命令(Generic)、生成语句(Generate)等进 行了展开。不是必做的仿真。 l Simulator Post-Map VHDL Model也就是映射后仿真。不同的器件内部结构也不尽相同,映射的作用就是将综合后产生的网表文件对应到实际的器件上去。由于映射 不包含布线,也就是要用什么类型的逻辑单元虽然已经确定但要用哪个位置的还没 有确定,因此,映射后仿真不包含布线延时。不是必做的仿真。 l Simulator Post-Place & Route VHDL Model也就是所说的布局布线后仿真、时序仿真、后仿真。这是最完整的仿真,既包含逻辑延时又包含布线延时。在做布局布 线后仿真时要用到一个叫SDF的文件。SDF文件包含设计中每个单元(Cell)的延

testbench时钟信号的编写(verilog)

testbench时钟信号的编写 2011-01-13 11:07:38| 分类:FPGA的分享| 标签:clock parameter reg 占空比 time_period |举报|字号大中小订阅 /******************************************************* 时钟信号的编写 *******************************************************/ 'timescale 1ns/1ps //定义时间单位/时间精度 /******************占空比50%(采用initial)**************/ parameter TIME_PERIOD = 10; reg clock; initial begin clock = 0;//初始化clock为0 forever # (TIME_PERIOD/2) clock = ~clock; end /******************占空比50%(采用always)***************/ parameter TIME_PERIOD = 10; reg clock; initial clock = 0;//初始化clock为0 always # (TIME_PERIOD/2) clock = ~clock; /******************非50%占空比(采用always)*************/ parameter HI_TIME = 5, LO_TIME = 10; reg clock; always begin # HI_TIME clock = 0; # LO_TIME clock = 1; end /***********固定数目时钟占空比50%(采用initial)*********/ parameter PULSE_COUNT = 4, TIME_PERIOD = 10; reg clock; initial begin clock = 0;//初始化clock为0 repeat (2*PULSE_COUNT)

Modelsim 仿真步骤总结

Modelsim 仿真步骤总结 Modelsim 仿真主要有以下三个方面:各版本的方法大体一致。(1)建立库并映射库到物理目录; (2)编译源代码(包括testbench); (3)执行仿真; 下面具体演示每一步的操作方法及流程,为力求简洁,其中有多种操方法的只介绍一种。 一)建立库的演示: 步骤为——启动modelsim>点击file菜单>(Change Directory)>new>(project)>library.注括号内的步骤非必须。 1.1)启动modelsim; (1.2)点击file菜单,此时若需更改路径,可以点击其中的Change Directory.(注modelsim会自动默认路径。我们也可以在1.1步骤之前建立一个文件夹用于modelsim的工程,再将路径更改到我们新建的文件夹路径。)

(1.3)点击file子菜单中的new,选择project用于新建立一个modelsim工程。(虽然此步非必须,但是建立一个新工程有益 于接下来整个仿真文件的管理。)

1.4)点击file子菜单new,再点击new下的library,用于建立 一个库。(仔细观察1.3步,新建工程的同时亦可建立库)。 至此,modelsim仿真第一大步建立库的工作完毕。

二)编译源代码(包括testbench): 大家都已知道在quartus中编译源代码的方法,这里说明一下在modelsim中编译源代码及testbench的方法。 步骤为——建立一个新工程(同时建立库)后,会自动提示你四个选项。如图: 选create new file后提示对话框,(也可以在有源文件的情况下选择add existing file到工程中。例如我们用quartus写好文件后,可以用此方法将quartus中的文件添加到modelsim工程中来)让你命名你即将创建的新文件,完毕后,会自动出现一个空白的编辑窗口,在那里输入源代码和testbench。(提示:这样编写完后点保存,便可以直接保存到上面设臵好的work库中。比起另一种方法,不建工程直接建库,再通过菜单栏source添加源

VHDL——如何写简单的testbench

use ieee.std_logic_1164.all; use ieee.std_logic_arith.all; --use ieee.std_logic_unsigned.all; entity cnt6 is port (clr,en,clk :in std_logic; q :out std_logic_vector(2 downto 0) ); end entity; architecture rtl of cnt6 is signal tmp :std_logic_vector(2 downto 0); begin process(clk) -- variable q6:integer; begin if(clk'event and clk='1') then if(clr='0')then tmp<="000"; elsif(en='1') then if(tmp="101")then tmp<="000"; else

tmp<=unsigned(tmp)+'1'; end if; end if; end if; q<=tmp; -- qa<=q(0); -- qb<=q(1); -- qc<=q(2); end process; end rtl; 二、六进制计数器testbench的代码

signal en :std_logic:='0'; signal clk :std_logic:='0'; signal q :std_logic_vector(2 downto 0); constant clk_period :time :=20 ns; begin instant:cnt6 port map ( clk=>clk,en=>en,clr=>clr,q=>q ); clk_gen:process begin wait for clk_period/2; clk<='1'; wait for clk_period/2; clk<='0'; end process; clr_gen:process begin clr<='0'; wait for 30 ns; clr<='1'; wait; end process; en_gen:process begin en<='0'; wait for 50ns; en<='1'; wait; end process; end rtl;

1 ModelSim的使用与Testbench的编写

ModelSim的使用与Testbench的编写 重温了基本的Quartus操作和语法后,需要对手头的工作进行仿真验证,Quartus 9.x自带的Vector Waveform已经淘汰掉了,必须用 ModelSim进行仿真。现在就开始一步步入手ModelSim,并通过与Quartus无缝衔接实现仿真。本文使用了ModelSim10.0c + QuartusII 10.0,其他版本基本雷同,请自行研究。 源程序如下: module add( mclk, rst_n, a_in, b_in, c_out ); input mclk, rst_n; input[7:0] a_in, b_in; output[8:0] c_out; reg[8:0] c_out; always@(posedge mclk, negedge rst_n) begin if(!rst_n) c_out <= 9'h0; else c_out <= a_in + b_in; end endmodule 请建立工程,将源程序编译通过. 1.设置第三方EDA工具 在Tools -> Options中设置ModelSim的安装路径,注意要设置到win32文件夹(64位软件对应的就是win64)。

仿真工具为ModelSim。这样Quartus就能无缝调用ModelSim了。

当然也可以在建立工程的时候就设置仿真工具。

2.编写Testbench 说到Testbench,你可以叫它Testbench,或者Testbenches,但不是Test Bench。说起来,就连Quartus也没注意这个问题,至于原因嘛参见Common Mistakes In Technical Texts一文。文章中还列举了些别的错误用语,包括Flip-flop不能写成Flipflop,等等。文章链接: https://www.sodocs.net/doc/5b13708911.html,/papers/Technical_Text_Mistakes.pdf 我们可以通过Quartus自动生成一个Testbench的模板,选择Processing -> Start -> Start Test Bench Template Writer,等待完成后,在导航栏中打开刚才生成的Testbench,默认是保存在simulation\modelsim文件夹下的.vt格 式文件。

如何写testbench

如何编写testbench 今天,我来带领大家写一个简单的testbench,顺便讲解如何写好一个testbench以及写testbench时应该注意的地方。 在讲解testbench之前,我们先看一下前面的那个AND_2程序的仿真图,如下: 如上图中所标,在1处,B已经为低电平了,但是输出C仍然为高电平,这样求与运算就会出错。在2处,A和B都是低电平了,C仍然为高电平,直到下次出现时钟的上升沿为止,为什么会这样呢?编译的时候并没有报错,呵呵,出了怪事了啊!其实编译器只能检查处语法错误,无法检测到逻辑错误,这个图给出的结果和我们程序所表达的结果一样,但是这并不是我们所要的求与运算,我们想要的是A和B同时为高电平时,C才输出高电平。我们把程序的敏感列表改为: always@(posedge clk or negedge rst or A or B) 就可以了,把A的电平改变和B的电平改变都加进敏感列表,激励不变,所得到的仿真图: 这才是我们所要的求与运算! 好了,现在开始讲如何写testbench。Testbench不像RTL级代码,可以用高级行为语句,不用考虑其可综合性,这样就能写出高效的检测代码。在语法上,testbench和可综合代码一样,都是类C结构。好了,我们开始吧! 1,建立工程等,与之前的一样,但是在创建文件的时候,我们一次创建两个。取名分别为ParallelSerial_Mult和ParallelSerial_Mult_test。创建完成后,如下图:

这两个代码分别如下: module ParallelSerial_Mult(Clk,Rst,MultiplicandIn,MultiplierIn,Load,Product,Out_en); parameter N=8; parameter CYCLES=3; input Clk,Rst,Load; input[N-1:0]MultiplicandIn,MultiplierIn; output[2*N-1:0]Product; output Out_en; reg[2*N-1:0]Product; wire Out_en; reg[N-1:0]Multiplicand; reg[2*N-1:0]NextProduct; reg[CYCLES:0]Count; reg Busy; wire[N-1:0]Sum; wire Carry; assign{Carry,Sum}=Multiplicand+Product[2*N-1:N]; assign Out_en=Count[CYCLES]; always@(posedge Clk or negedge Rst) if(!Rst) begin Multiplicand<=0; Count<=0; Product<=0; Busy<=0; end else begin Product<=NextProduct; if(Load) begin Multiplicand<=MultiplicandIn; Count<=0; Busy<=1'b1; end else begin if(Busy) Count<=Count+1'b1; if(Count[CYCLES]) begin

Verilog仿真文件testbench编写样例

Verilog 仿真文件testbench编写样例 `timescale 1ns/100ps module testbench; localparam DATA_WIDTH = 32; localparam CLK_100_PERIOD = 5; localparam CLK_200_PERIOD = 2.5; localparam SIM_TIME = 150000; localparam ; localparam ; reg clk_100, clk_200; wire clk; assign clk = clk_100; always begin clk_100 = 0; forever #CLK_100_PERIOD clk_100 = ~clk_100; end always begin clk_200 = 0; forever #CLK_200_PERIOD clk_200 = ~clk_200;

end reg rstn; integer fp_testin; integer fp_matlab_out; integer fp_sim_out; integer fp_outdiff; reg signed [DATA_WIDTH/2-1:0] matlab_in_re, matlab_in_im; reg signed [DATA_WIDTH/2-1:0] matlab_out_re, matlab_out_im; reg signed [DATA_WIDTH/2-1:0] matlab_diff_re, matlab_diff_im; reg signed [DATA_WIDTH/2-1:0] matlab_diff_re2, matlab_diff_im2; reg signed [DATA_WIDTH/2-1:0] max_diff_re, max_diff_im; initial begin max_diff_re = 0; max_diff_im = 0; rstn = 0; #500 rstn = 1;

1_VHDL修改Quartus自己产生的testbench

VHDL编写testbench(.vht文件) 对modelsim自己产生的.vht文件修改进行仿真时,需要更改两处,分别是如下: 1.对于Signal信号需要赋初值。 例如: 原文件中: SIGNAL CLK_IN : STD_LOGIC; SIGNAL Q : STD_LOGIC_VECTOR(3 DOWNTO 0); 更改后为: SIGNAL CLK_IN : STD_LOGIC := '1'; SIGNAL Q : STD_LOGIC_VECTOR(3 DOWNTO 0) := "0000"; 最简单的记法,格式都是如下: SIG<=’1’;WAIT FOR 10 NS; SIG<=’0’;WAIT FOR 10 NS; 时钟信号: process_clk : PROCESS BEGIN CLK_IN <= '0'; WAIT FOR 10NS; CLK_IN <= '1'; WAIT FOR 10NS; END PROCESS process_clk; 复位信号: process_rst : PROCESS BEGIN RST_N <= '1'; WAIT FOR 20NS; RST_N <=’0’; WAIT FOR 20NS; WAIT; END PROCESS process_rst; 一般激励信号: process_sig : PROCESS BEGIN SIG<=’1’;WAIT FOR 10 NS; SIG<=’0’;WAIT FOR 20 NS;

SIG<=’1’;WAIT FOR 20 NS; SIG<=’0’;WAIT FOR 10 NS; END PROCESS process_ sig;

如何编写Testbench

2 如何编写Testbench 1) 何时使用initial和always initial和always 是2个基本的过程结构语句,在仿真的一开始即开始相互并行执行。通常被动的检测响应使用always语句,而主动的产生激励使用initial语句。 initial和always的区别是always 语句不断地重复执行,initial语句则只执行一次。但是,如果希望在initial里的多次运行一个语句块,怎么办?这时可以在initial里嵌入循环语句(while,repeat,for,forever 等),如: initial begin forever /* 无条件连续执行*/ begin …… end end 其它循环语句请参考一些教材,这里不作赘述。 另外,如果希望在仿真的某一时刻同时启动多个任务,可以使用fork....join语句。例如,在仿真开始的 100 ns 后,希望同时启动发送和接收任务,而不是发送完毕后再进行接收,如下所示: initial begin #100 ; fork /*并行执行 */ Send_task ; Receive_task ; join End 2) 如何作多种工作模式的遍历测试 如果设计的工作模式很多,免不了做各种模式的遍历测试,而遍历测试是需要非常大的工作量的。我们经常遇到这样的情况:很多时候,各种模式之间仅仅是部分寄存器配置值的不同,而各模式间的测试都是雷同的。有什么方法可以减轻这种遍历测试的工作量?不妨试

试for循环语句,采用循环变量来传递各种模式的配置值,会帮助减少很多测试代码,而且不会漏掉每一种模式. initial begin for ( i = 0 ; i < m ; i = i + 1 ) /*遍历模式1至模式m*/ for ( j = 0 ; j < n ; j = j +1 ) /*遍历子模式1至子模式n */ begin case ( j ) /* 设置每种模式所需的配置值 */ 0 : 配置值= a ; 1 : 配置值= b ; 2 : 配置值= c ; …… endcase /*共同的测试向量*/ end end 3) 如何加速问题定位过程 在这部分里,通过一些实际例子,介绍在出现问题时如何借助 testbench 加快问题的定位过程。 1、监测内存分配 内存分配和回收示意图 在这个例子里,假设总共有2K的内存块,希望在测试程序里监测内存分配和回收的块号是否正确,监测是否存在同一块号重复分配、重复回收的情况。设置一个 2K位的变量对内存的使用情况进行记录,每一位对应一个内存块,空闲的块号记为1,被占用的块号记为0。

Verilog HDL培训(3)_如何编写TESTBENCH

08:291 如何编写TESTBENCH 计算机学院微电子所627室 陈海燕

08:292 主要内容 Verilog 对验证的支持 系统函数和系统任务 如何编写模块的TESTBENCH

08:293 系统任务和系统函数 是Verilog中预先定义好的,用于调试和编译预处理的任务或函数。 以$开头,用于控制和检测仿真模拟过程 主要有: (1)用于获取仿真时间的系统函数 (2)支持文本输出(检测信号、显示信号)的系统任务 (3)用于文件输入、输出操作的系统任务 (4)用于暂停和退出仿真的系统任务 (5)用于产生随机数的系统任务

08:29 4获取当前仿真时间的系统函数 $time,$realtime,$stime:返回当前仿真时间。 $time返回一个64位的整数时间值, $realtime返回的结果是实数时间值,是更为精确的仿真时间 $stime返回一个32位整数时间值。(对大于232的 时间,返回模232的值。使用它可以节省显示及打 印空间。) 这些函数的返回值使用调用模块中`timescale 定义的模块仿真时间尺度为单位

08:295 例 ..\..\verilog_example\Dec2x4.v ..\..\verilog_example\Dec_Test.v # At time 0, input is 0,0,0, output is,xxxx # At time 4, input is 0,0,0, output is,1111# At time 10, input is 0,0,1, output is,1111# At time 13, input is 0,0,1, output is,0111# At time 20, input is 1,0,1, output is,0111# At time 23, input is 1,0,1, output is,0101# At time 26, input is 1,0,1, output is,1101# At time 30, input is 1,1,1, output is,1101# At time 33, input is 1,1,1, output is,1100# At time 36, input is 1,1,1, output is,1110# At time 40, input is 0,1,1, output is,1110# At time 44, input is 0,1,1, output is,1011# At time 50, input is 0,0,1, output is,1011 # At time 54, input is 0,0,1, output is,0111

VHDL——如何写简单的testbench

弄了好长时间vhdl,一直对testbench很迷惑。前几天静下心来好好看了下资料,终于会写简单的testbench了。 六进制计数器的代码 [c-sharp]view plaincopy 1.library ieee; https://www.sodocs.net/doc/5b13708911.html,e ieee.std_logic_1164.all; https://www.sodocs.net/doc/5b13708911.html,e ieee.std_logic_arith.all; 4.--use ieee.std_logic_unsigned.all; 5. 6.entity cnt6 is 7. port 8. (clr,en,clk :in std_logic; 9. q :out std_logic_vector(2 downto 0) 10. ); 11.end entity; 12. 13.architecture rtl of cnt6 is 14.signal tmp :std_logic_vector(2 downto 0); 15.begin 16. process(clk) 17.-- variable q6:integer; 18. begin 19.if(clk'event and clk='1') then 20.if(clr='0')then 21. tmp<="000"; 22. elsif(en='1') then 23.if(tmp="101")then 24. tmp<="000"; 25.else 26. tmp<=unsigned(tmp)+'1'; 27. end if; 28. end if; 29. end if; 30. q<=tmp; 31.-- qa<=q(0); 32. -- qb<=q(1); 33. -- qc<=q(2); 34. end process; 35.end rtl;

编写testbench的一些技巧

1 Testbench的结构 1) 单顶层结构 一种结构是testbench 只有一个顶层,顶层再把所有的模块实例化进去。打个比方,类似树结构,只有一个模块有子节点而没有父节点,其它模块都有父节点。如下图结构所示: 测试模块是一些接口模型,接口模型还可能包含了一些激励在内。测试模块和DUV之间通过端口映射进行互连。 2) 多顶层结构 另外一种结构是多顶层结构,如下图所示: 在这种结构中,有一个顶层是作为测试向量模块,一个或多个顶层是一些公用子程序,这些子程序由于完成一些通用的功能被封装成任务、函数等被公用。 还有一个叫harness的顶层,该顶层由DUV和一些接口模型构成一个狭义上的测试平台,其它模块可以调用BFM里面的task 或event 等,向DUV施加激励。注意这些顶层之间是没有端口映射的,它们之间的互相调用和访问是通过层次路径名的方式来访问,上图的虚线表示层次路径名的访问。下面举例说明层次路径是如何访问的。 由于大部分人对C都有所认识,在这里作个比较,便于了解。Verilog HDL的顶层类似于C的结构体,而实例化的模块、任务、函数、变量等就是结构体里的成员,可以通过句点( . )隔开的方式访问结构体里面的每一个成员。如:顶层harness 实例化进来的模块BFM1 里面有一个任务SEND_DATA , 该任务可以产生激励输入到DUV,在testcase 里

调用该任务就可写为: initial begin …… harness . BFM1 . SEND_DATA (……); end 多顶层结构的可扩展和重用性比单顶层结构强得多。层次路径的访问方式非常有用,在下一节会讲述更多的应用。 2 如何编写Testbench 1) 何时使用initial和always initial和always 是2个基本的过程结构语句,在仿真的一开始即开始相互并行执行。通常被动的检测响应使用always语句,而主动的产生激励使用initial语句。 initial和always的区别是always 语句不断地重复执行,initial语句则只执行一次。但是,如果希望在initial里的多次运行一个语句块,怎么办?这时可以在initial里嵌入循环语句(while,repeat,for,forever 等),如: initial begin forever /* 无条件连续执行*/ begin …… end end 其它循环语句请参考一些教材,这里不作赘述。 另外,如果希望在仿真的某一时刻同时启动多个任务,可以使用fork....join语句。例如,在仿真开始的100 ns 后,希望同时启动发送和接收任务,而不是发送完毕后再进行接收,如下所示: initial begin #100 ; fork /*并行执行*/ Send_task ;

编写高效率的testbench

编写高效率的testbench 简介: 由于设计的规模越来越大也越来越复杂,数字设计的验证已经成为一个日益困难和繁琐的任务。验证工程师们依靠一些验证工具和方法来应付这个挑战。对于几百万门的大型设计,工程师们一般使用一套形式验证(formal verification)工具。然而对于一些小型的设计,设计工程师常常发现用带有testbench的HDL仿真器就可以很好地进行验证。 Testbench已经成为一个验证高级语言(HLL --High-Level Language) 设计的标准方法。通常testbench完成如下的任务: 1.实例化需要测试的设计(DUT); 2.通过对DUT模型加载测试向量来仿真设计; 3.将输出结果到终端或波形窗口中加以视觉检视; 4.另外,将实际结果和预期结果进行比较。 通常testbench用工业标准的VHDL或Verilog硬件描述语言来编写。Testbench调用功能设计,然后进行仿真。复杂的testbench完成一些附加的功能—例如它们包含一些逻辑来选择产生合适的设计激励或比较实际结果和预期结果。 后续的章节描述了一个仔细构建的testbench的结构,并且提供了一个自动比较实际结果与预期结果的进行自我检查的testbench例子。 图1给出了一个如上所描述步骤的标准HDL验证流程。由于testbench使用VHDL或Verilog来描述,testbench的验证过程可以根据不同的平台或不同的软件工具实现。由于VHDL或Verilog是公开的通用标准,使用VHDL或Verilog编写的testbench以后也可以毫无困难地重用(reuse)。 图1使用Testbench的HDL验证流程 构建Testbench Testbench用VHDL或Verilog来编写。由于testbench只用来进行仿真,它们没有那些适用于综合的RTL语言子集的语法约束限制,而是所有的行为结构都可以使用。因而testbench可以编写的更为通用,使得它们可以更容易维护。 所有testbench包含了如表1的基本程序段。正如上面所提到的,testbench通常包含附加功能,如在终端上可视的结果和内建的错误检测。

VivadoHLS工程testbench的三个要素

编写高效Vivado HLS工程testbench的三个要素在C程序的设计中,任何一个C程序的顶层都是main()函数。而在vivado HLS的设计中,只要函数的层次在main()函数以下,都可以被综合。但是每个vivado HLS工程只能指定一个top层函数作为输出RTL模块的顶层,其它和这个函数层次平行,不需要被综合的函数都可以作为testbench来使用。这样就带来一个问题,如何编写vivado HLS工程的testbench更高效,或者说能更好的让HLS工具自动重用C testbench验证产生的RTL代码就变得非常重要。 通常,在Vivado HLS中,好的C testbench设计原则是testbench设计和需要实现的算法函数分别保存在不同的文件中,并且充分利用头文件。Testbench 常常包含了一些HLS综合不支持的操作,比如通过文件的读写取得仿真数据并保存结果,或者打印一些测试结果进行分析。在头文件中,完成对testbench中所有的数据类型和函数的定义,以及包含共享的设计文件和函数库。 Vivado HLS中,只能指定一个top层函数用于综合,top层函数可以包含多个子函数。当需要综合多个并行层次的函数时,可以编写一个wrapper函数作为top层函数,将需要综合的多个并行函数封装起来。 C testbench的目不仅是要验证需要综合的top函数功能正确(C编译器验证环境),同时重用C testbench作为综合产生RTL代码的仿真激励,HLS工具自动调用C testbench来验证RTL功能的一致性(C编译器和RTL仿真器的协同仿真环境)。这样,编写一个好的风格testbench可以很好的提高设计的验证效率,如果在HLS综合前和综合过程中,需要修改综合函数的代码,可以用testbench验证,确保需要综合的C算法功能正确。 Vivado HLS中推荐高效的testbench具有如下三个特征:

实例解读Testbench编写方法

实例解读Testbench编写方法 前言: 在进行quartusII设计时,不少人刚开始觉得仿真极其不方便,还需要编写测试文件,浪费时间精力。不过小编想告诉大家,其实testbench编写很容易学,不外乎wait for 语句的堆叠就可以了,至于高深的用法,对一般程序都涉及不到,没必要弄得那么复杂。 下面看看实例吧,将详细说明testbench的编写: 我们可以通过Quartus自动生成一个Testbench的模板,选择Processing -> Start -> Start Test Bench Template Writer,等待完成后打开刚才生成的Testbench,默认是保存在simulation\modelsim文件夹下的.vt格式文件。 打开vt文件后可以看到Quartus已经为我们完成了一些基本工作,包括端口部分的代码和接口变量的声明,我们要做的就是在这个做好的模具里添加我们需要的测试代码。 一个最基本的Testbench包含三个部分,信号定义、模块接口和功能代码。

‘timescale 1ns/ 1ps表示仿真的单位时间为1ns,精度为1ps。想要进行仿真首先要规定时间单位,而且最好在Testbench里面统一规定时间单位,而不要在工程代码里定义,因为不同的模块如果时间单位不同可能会为仿真带来一些问题,而timescale本身对综合也就是实际电路没有影响。 其实Testbench本身可以看做一个模块或者设备(本例中的模块名为add_vlg_tst),和你自己编写的模块进行通信。通过Testbench模块向待测模块输出信号作为激励,同时接收从待测模块输出的信号来查看结果。因此,在待测模块中的reg型信号在Testbench 中就变成了wire,待测模块中的wire型信号在Testbench中则对应为reg型。那么inou t怎么办呢,inout型信号也要设成wire,同时要用一个reg型信号作为输出寄存器,同时

modelsim测试程序的编写

Testbench的编写 下面将以8位计数器的verilog源程序为例编写modelsim仿真所需的测试激励文件,我们可以通过Quartus自动生成一个Testbench的模板,选择Processing -> Start -> Start TestBench Template Writer,等待完成后打开刚才生成的Testbench,默认是保存在simulation\modelsim文件夹下的.vt 格式文件。

打开vt文件后可以看到Quartus已经为我们完成了一些基本工作,包括端口部分的代码和接口变量的声明,我们要做的就是在这个做好的模具里添加我们需要的测试代码。 一个最基本的Testbench包含三个部分,信号定义、模块接口和功能代码。‘timescale 1ns/ 1ps表示仿真的单位时间为1ns,精度为1ps。想要进行仿真首先要规定时间单位,而且最好在Testbench里面统一规定时间单位,而不要在

工程代码里定义,因为不同的模块如果时间单位不同可能会为仿真带来一些问题,而timescale本身对综合也就是实际电路没有影响。 其实Testbench本身可以看做一个模块或者设备(本例中的模块名为counter_vlg_tst),和你自己编写的模块进行通信。通过Testbench模块向待测模块输出信号作为激励,同时接收从待测模块输出的信号来查看结果。因此,在待测模块中的reg型信号在Testbench中就变成了wire,待测模块中的wire 型信号在Testbench中则对应为reg型。处理完接口和声明之后,需要自己设置一些激励信号,激励信号的内容就是输入到待测模块中的波形。在写测试程序时我们只需要在下图中红色方框的位置写代码即可。 下面我们就以计数器verilog源程序为例写一个简单的测试程序。 首先是复位信号 initial begin reset = 0; #5 reset = 1; #4 reset = 0; end

如何编写testbench的总结

空间管理您的位置: 中国电子顶级开发网(EETOP)-电子设计论坛、博客、超人气的电子工程师资料分享平台 ?多云转晴 ?日志 欢迎大家和我讨论Xilinx FPGA方面的问题 如何编写testbench的总结(非常实用的总结)(转) 上一篇 / 下一篇 2011-09-19 21:08:27 / 个人分类:FPGA知识 查看( 23717 ) / 评论( 0 ) / 评分( 0/ 0) 1.激励的设置 相应于被测试模块的输入激励设置为reg型,输出相应设置为wire类型,双向端口inout在测试中需要进行处理。 方法1:为双向端口设置中间变量inout_reg作为该inout的输出寄存,inout口在testbench中要定义为w ire型变量,然后用输出使能控制传输方向。 eg: inout [0:0] bi_dir_port; wire [0:0] bi_dir_port; reg [0:0] bi_dir_port_reg; reg bi_dir_port_oe; assign bi_dir_port=bi_dir_port_oe?bi_dir_port_reg:1'bz; 用bi_dir_port_oe控制端口数据方向,并利用中间变量寄存器改变其值。等于两个模块之间用inout双向口互连。往端口写(就是往模块里面输入) 方法2:使用force和release语句,这种方法不能准确反映双向端口的信号变化,但这种方法可以反映块内信号的变化。具体如示: module test(); wire data_inout; reg data_reg;

reg link; #xx; //延时 force data_inout=1'bx; //强制作为输入端口 ............... #xx; release data_inout; //释放输入端口 endmodule 从文本文件中读取和写入向量 1)读取文本文件:用$readmemb系统任务从文本文件中读取二进制向量(可以包含输入激励和输出期望值)。$readmemh 用于读取十六进制文件。例如: reg [7:0] mem[1:256] // a 8-bit, 256-word 定义存储器mem initial $readmemh ( "mem.data", mem ) // 将.dat文件读入寄存器mem中 initial $readmemh ( "mem.data", mem, 128, 1 ) // 参数为寄存器加载数据的地址始终 2)输出文本文件:打开输出文件用?$fopen 例如: integer out_file; // out_file 是一个文件描述,需要定义为integer类型 out_file = $fopen ( " cpu.data " ); // cpu.data 是需要打开的文件,也就是最终的输出文本 设计中的信号值可以通过$fmonitor, $fdisplay, 2. Verilog和Ncverilog命令使用库文件或库目录 ex). ncverilog -f run.f -v lib/lib.v -y lib2 +libext+.v //一般编译文件在run.f中, 库文件在lib.v中,lib2目录中的.v文件系统自动搜索 使用库文件或库目录,只编译需要的模块而不必全部编译 3.Verilog Testbench信号记录的系统任务: 1). SHM数据库可以记录在设计仿真过程中信号的变化. 它只在probes有效的时间内记录你set probe o n的信号的变化.

相关主题