7.5仿真测验文件(Testbench)的规划办法
7.5.1测验文件的用处
跟着规划量和杂乱度的不断增加,数字规划验证变得越来越难,所耗费的本钱也越来越高。面临这种应战,验证工程师有必要依托相应的验证东西和办法才行。关于大型的规划,比方上百万门的规划验证,工程师有必要运用一整套规范的验证东西;而关于较小的规划,运用具有HDLtestbench的仿真器是一个不错的挑选。
Testbench现已成为了HLL(High-Level-Language,高档言语)规划规范验证办法。一般来说,它能够完结下面一些使命。
·实例化DUT(DesignUnderTest,被测规划)。
·经过为模块增加测验向量对DUT进行仿真。
·经过终端或波形窗口供给仿真成果。
·比较实践输出与希望输出的差异。
一般来说,Testbench运用工业规范VHDL或许VerilogHDL言语来描绘。简略的Testbench经过调用用户规划的功用模块,然后进行仿真。较为杂乱的Testbench还包括一些其他的功用,比方包括特定的鼓励向量或许进行实践输出与希望输出的比较等。
如图7.32所示是一个规范的HDL验证流程,图中表达了上述的Testbench功用。
图7.32HDLTestbench仿真流程
因为Testbench是运用VHDL或许VerilogHDL编写的,因而Testbench的验证流程是跨渠道的。一起因为这两种言语是规范的非私有言语,所以运用它们进行验证的流程能够在未来的规划中持续运用。
下面解说Testbench的规划办法。
7.5.2测验文件规划办法
因为测验文件只是在仿真时运用,因而在归纳中对RTL言语的语法约束在测验文件中并不存在。相反地,测验文件能够编写得愈加浅显,一切的行为结构语法都能够运用,使之愈加简单了解。一切的测验文件都包括了如表7.1所示的结构。
表7.1 测验文件的一起结构
VHDL |
VerilogHDL |
实体和结构声明(Entity,Architecture) |
模块声明(Module) |
信号声明(Signal) |
信号生命(Signal) |
顶层模块实例化 |
顶层模块实例化 |
鼓励向量 |
鼓励向量 |
正如所述,测验文件除了包括这些共有的结构意外,还完结一些额定的作业。例如显现成果、嵌入的误码检测等。下面经过一些比方来展示测验文件中常用的结构。
1.发生测验时钟
仿真有必要发生时钟才干进行,只要在推动的仿真时钟中才干够断定输出的成果是否契合规划的要求。交互时钟是硬件规划言语里边最简单完成的时钟,下面经过Verilog言语的比方来阐明怎么生成测验时钟。
Parameter ClockPeriod = 10; // 声明时钟周期常量
//时钟生成办法1:
initial begin
forever Clock = #(ClockPeriod / 2) ~ Clock;
end
//时钟生成办法2:
initial begin
always #(ClockPeriod / 2) Clock = ~Clock;
end
在两种完成办法中,都是用了initial块句子。在办法1中,运用了forever句子,是最常用的发生时钟的办法。在办法2中,运用过了always句子,相同也完成了时钟的生成。两种办法都发生了周期为10的时钟波形。
2.供给鼓励源
为了得到Testbench的验证成果,有必要为DUT供给鼓励向量。并行鼓励模块常常被用来为测验文件供给必要的鼓励。有两种不同的办法来完成并行的鼓励:一种是肯定时刻鼓励,另一种是相对时刻鼓励。
在肯定时刻鼓励中,一切的仿真时刻值都是相对仿真时刻零点界说的。而在相对时刻鼓励中,一般会供给初始化值,然后等候事情来触发鼓励向量。两种办法都能够依据规划者的需要在同一个测验文件中运用。
下面分别是两种办法发生鼓励的比方。
(1)肯定时刻。
initialbegin
Reset=1;//仿真时刻零点鼓励
Load=0;//仿真时刻零点鼓励
Count_UpDn=0;//仿真时刻零点鼓励
#100Reset=0;//肯定时刻100鼓励
#20Load=1;//肯定时刻120鼓励,相对上一个时刻点20
#20Count_UpDn=1;//肯定时刻140鼓励,相对上一个时刻点20
end
(2)相对时刻。
always@(posedgeclock)
TB_Count=TB_Count+1;//肯定时刻的递加
initialbegin
if(TB_Count=5)begin//触发事情,发生下列鼓励
Reset=1;
Load=0;
Count_UpDn=0;
end
elsebegin//触发事情,发生下列鼓励
Reset=0;
Load=1;
Count_UpDn=1;
end
end
initialbegin
if(Count==1100)begin//触发事情,发生归零鼓励,并显现成果
Count_UpDn=0;
$display(TerminalCountReached,nowcountingdown.);
end
end
值得留意的是,VerilogHDL言语的initial模块之间是并行履行的,可是initial模块内部是次序履行的。也便是说,测验文件的鼓励次序在仿真时刻零点一起发动并行模块,然后依据各个模块的内部鼓励次序发生鼓励向量。
3.成果输出
测验文件经过关键词$display和$monitor来完成成果的输出。下面是运用VerilogHDL言语完成在终端上显现成果的比方:
//在终端中打印信号的ASCII值
initialbegin
$timeformat(-9,1,ns,12);//设置输出时钟格局
$display(TimeClkRstLdSftRgDataSel);//显现输入的字符串
$monitor(%t%b%b%b%b%b%b,//设置输出信号的格局
$realtime,clock,reset,load,shiftreg,data,sel);//指定输出的信号
end
$display是将函数内部双引号中的字符串输出在终端中。而$monitor则不同,因而它的输出是事情驱动的。在比方中,$monitor信号列表中的$realtime信号改变会触发终端显现事情的发生,该信号被规划者对应到仿真时刻中,每次$monitor的触发将会把信号列表中的信号值显现在终端中。
$monitor句子中的“%”用于界说信号列表中信号的输出格局。例如,%t将信号依照时刻格局输出,%b将信号依照二进制格局输出。别的,VerilogHDL言语还供给了其他的输出格局,比方%h为十六进制输出,%d为十进制输出,%o为八进制输出等。更为具体的格局输出界说能够参看Verilog参阅手册。
7.5.3测验常用句子
常用的Verilog测验用结构句子,比方$monitor、$display和$time在上面现已介绍过了。下面再来介绍一些其他的常用句子。
1.force/release
force和release句子能够用来强制对履行进程中的寄存器或网络型信号量赋值。这两条句子一起完结一个强制赋值的进程。当一个被force的信号被release今后,这个信号将会坚持其时的状况直到下一个赋值句子发生停止。
下面举个比方来阐明这两条句子的运用。
moduletestbench;
…
initialbegin
reset=1;//在仿真时刻零点将reset鼓励为1
forceDataOut=101;//在仿真时刻零点强制使DataOut为101,并坚持
#25reset=0;//在仿真肯定时刻25将reset鼓励为0
#25releaseDataOut;//在仿真肯定时刻50开释
//DataOut值将坚持直至下一个对它的赋值句子
…
end
endmodule
2.assign/deassign
assign/deassign句子与force/release句子相相似,不过assign/deassign句子只能对规划中的寄存器型信号赋值。它们常常被用来设置输入值。
下面是这两个句子的比方。
moduletestbench;
…
initialbegin
reset=1;//肯定时刻零点对reset赋值1
DataOut=101;
#25reset=0;//肯定时刻25对reset赋值0
releaseDataOut;
…
end
initialbegin
#20assignreset=1;//此条句子掩盖之前的赋值句子(即肯定时刻零点的赋值)
#25reset=0;//肯定时刻45对reset赋值0
#50releasereset;//肯定时刻95开释reset信号
endmodule
3.timescales
timescale句子用于界说测验文件的单位时刻,一起也对仿真的精度有影响。它的语法界说如下:
‘timescalereference_time/precision
其间,reference_time是单位时刻的衡量,precision决议了仿真的推动推迟精度,一起也设置了仿真的推动步进单位。下面是timescale句子的运用典范:
‘timescale1ns/1ps//衡量参阅为1ns,精度为1ps
moduletestbench;
…
initialbegin
#5reset=1;//5个仿真时刻推迟,相当于5×1ns=5ns的仿真时刻
#10reset=0;
…
end
initialbegin
//display句子将在每一个仿真推动步进中履行,也便是1ps履行一次
$display(“%d,Reset=%b”,$time,reset);
end
endmodule
应该留意的是,假如仿真中运用了时刻推迟值,那么仿真的精度应大于最小的推迟值。例如仿真中运用了9ps的仿真时刻推迟,那么仿真的推动步进精度有必要为1ps来确保9ps的推迟。
4.ReadingMemoryInitializationFiles
VerilogHDL供给了$readmemb和$readmemh指令来读取ASCII文件,用于初始化memory的内容。这两个句子能够用于初始化FPGA中由IPCore生成的存储器宏模块,例如RAM、ROM等。
下面是使用这个句子对Xilinx的实例(design_instance)进行初始化的比方。
$readmemb(“design.mif>”,design_instance);
其间,mif文件是Xilinx的CoreGenerator树立的对存储器进行初始化的文件。用户也能够自己编写这个文件的内容。