【TestBench内容编写与方法总结】

随着数字电路设计的规模和复杂性越来越大,设计验证也变得更加困难和复杂。为了解决这一挑战,验证工程师使用了一些验证工具和方法。

对于大型的、数百万门电路级的设计,通常使用一套正式的验证工具。这些工具通常是商业化的,并且具有许多高级特性,如代码覆盖率分析、功能覆盖率分析、动态波形仿真等等。这些工具能够有效地完成大规模电路的验证任务,并且可以保证电路的正确性。

然而对于小型的设计,则通常会使用带有testbench的HDL仿真工具进行测试。这些仿真工具可以帮助设计工程师检查电路的正确性,并且发现其中可能存在的错误。HDL仿真工具是一种被广泛采用的验证方法,因为它们易于使用,且成本较低。

通常,Testbenches会实现以下任务:

  • 实例化被测模块
  • 通过对模块功能,编写测试激励
  • 输出仿真结果到终端或波形窗口观察调试,或者输出成文件
  • 将实际结果与预期结果进行比对

testbench可用VHDL、Verilog和System Verilog编写。由于它们仅用于仿真,所以不受可综合过程中使用的RTL语言子集的语义约束限制。这意味着可以更通用地编写测试testbenches,使它们更易于维护。

一、`timescale

这个指令是Verilog语法中的一条预编译指令,通常用来指定仿真中时间的单位与精度,用于指定testbenches的单位时间步长。

这条指令的语法为:

`timescale reference_time/precision

其中reference_time是仿真中的时间单位,而precision则决定了仿真时间的精度

注意:

  • 时间单位和时间精度只能是1、10和100这3个整数中之一
  • 单位可以是s、ms、us、ns、ps和fs
  • 时间精度必须小于或等于时间单位

下面看一个简单的例子来了解下`timescale的使用方法:

`timescale 10ns/1ns //单位10ns,精度1ns

module testbench;
    reg set;
    localparam d = 1.8;
    initial begin
        #1    set = 0;    //1*10 ns  = 10ns
        #d    set = 1;    //1.8*10ns = 18ns
    end
endmodule

说明:

  • 时间单位设置为10ns,精度设置为1ns
  • 第1次在#1时对set赋值0,此时延时时间为10ns,因为时间单位为10ns,#1表示延时1个时间单位
  • 第2次在#d时对set赋值1,此时延时时间为18+10ns,因为时间单位为10ns,#d表示延时1.8个时间单位,即18ns

小tips:

1、不要设置无意义的高精度,时间精度越高,对应的仿真所消耗的资源和时间就越多,比如“timescale 1ns/1ps”,一般仿真时不需要精确到ps级,所以只需要设置成ns级就行,比如“`timescale 1ns/1ns”。

2、模块中虽然可以包含多个timescale,但建议只设定一个`timescale语句。注意预编译指令通常都是顺序执行的,新的一条相同的预编译指令会覆盖旧的预编译指令。

二、时钟信号

时序逻辑是必须有时钟的,生成时钟逻辑很简单,如下所示:

Parameter Period = 10;//周期
wire clk;
always #(Period/2) clk = ~clk;

延时表示:#+时间,如#2,即表示从现在开始20个时间单位后执行操作。

三、initial语句块

initial语句块一般只能用于行为仿真,但简单的使用initial对变量初始化也是可以综合的。

Verilog文件中的所有initial块都是同时并发执行的,但在每个initial块内部是按照写入的顺序执行的。

编写测试激励时,可以使用多个initial块将复杂逻辑分成多个部分,这样写的代码更具可读性和可维护性。

代码示例:

//参数定义
reg reset, start_r, stop_r;

//initial
initial begin
reset = 1;
Load = 0;
stop_r = 0;
#10 reset = 0;
#100 start_r = 1;
#200 stop_r = 1;
$stop;
end

四、常用系统函数

1、 f i n i s h 和 finish和 finishstop

$finish表示停止仿真,当程序仿真执行到该语句时,软件会提示要不要退出仿真。如果选是,则仿真结束,退出仿真窗口。

$stop表示暂停仿真,当程序仿真执行到该语句时,仿真会暂停,常用于抓取仿真过程中出现错误状态时,或检测某个信号时,暂停仿真。

一般与wait函数配合使用,检测到仿真结束条件时,停止仿真,这样就不用一直盯着仿真界面。

直接在initial语句中,调用该语句即可,如:

reg reset, start_r;
wire data_end;

initial begin
reset = 1;
start_r = 0;
#10 reset = 0;
#100 start_r = 1;
wait(data_end);//等待检测到结束信号,仿真自动停止。
$stop;
end

2、$timeformat

t i m e f o r m a t 用于修改 timeformat用于修改%t格式下显示时间的方式,在一个initial块中,会一直保持生效,直到执行了新的 timeformat用于修改timeformat。

语法:

$timeformat(units_num, precision_num, suffix_str, minimum_field_wdith);

说明:

(1)units_num

  表示打印的时间值的单位, 0 表示秒,-3 表示毫秒,-6 表示微秒,-9 表示纳秒, -12 表示皮秒, -15 表示飞秒;-10表示以100ps为单位。

(2)precision_num

   表示在打印时间值时,小数点后保留的位数。其默认值为0。

(3)suffix_str

     在时间值后面打印的一个后缀字符串。其默认值为空字符串。

(4)minimum_field_wdith

     时间值字符串与后缀字符串合起来的这部分字符串的最小长度,若这部分字符串不足这个长度,则在这部分字符串之前补空格。其默认值为20。

3、$display

可以在终端窗口打印出一条文本信息,支持自动换行。

$display("Hello world!");    
$display("%b %b",a,b) ;

变量输出格式:

%t    将显示的$realtime值按照格式化为$timeformat设定的时间格式;

%h   用于十六进制格式;

%d   用于十进制格式;

%o   用于八进制格式;

%b   用于二进制格式;

%c   用于ASCII 码格式输出;

%s  用于字符串格式输出。

4、$monitor

用于追踪变量的变化情况,只有追踪的变量发生变化才会在终端打印显示结果,支持自动换行。

$monitor("%t %b", $realtime, a);

5、应用示例

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

仿真结果:
在这里插入图片描述

五、测试激励示例

下面给一个经典示例,包括时钟、被测模块、测试激励和结果监控。

移位寄存器的简单Verilog设计:

module shift_reg (
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) begin
   if (reset)
       shiftreg = 0;
   else if (load)
       shiftreg = data;
   else begin
       case (sel)
       2'b00 : shiftreg = shiftreg;
       2'b01 : shiftreg = shiftreg << 1;
       2'b10 : shiftreg = shiftreg >> 1;
       default : shiftreg = shiftreg;
       endcase
    end
end
endmodule

测试激励:

module testbench; // declare testbench name
 
 reg clock;
 reg load;
 reg reset; // declaration of signals
 wire [4:0] shiftreg;
 reg [4:0] data;
 reg [1:0] sel;
 
 // instantiation of the shift_reg design below
 shift_reg dut(.clock (clock), 
    .load (load), 
    .reset (reset), 
    .shiftreg (shiftreg),
    .data (data), 
    .sel (sel));
 
 //this process block sets up the free running clock
 initial begin
     clock = 0;
     forever #50 clock = ~clock;
 end
 
 initial begin// this process block specifies the stimulus. 
     reset = 1;
     data = 5'b00000;
     load = 0;
     sel = 2'b00;
     #200
     reset = 0;
     load = 1;
     #200
     data = 5'b00001;
     #100
     sel = 2'b01;
     load = 0;
     #200
     sel = 2'b10;
     #1000 $stop;
 end
 initial begin// this process block pipes the ASCII results to the 
//terminal or text editor
     $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

六、自动化验证

在大型设计测试中,各种信号变量非常多,如果只通过观察,是看不过来的。

那有没有更有效的验证方法呢?

这时可以考虑自动化验证,将预期结果存储成一个大型数组,与实际输出的结果自动进行一一对比,这时候只需要观察check信号,如果实际结果与预期不一致,这时候就可以暂停仿真。

接下来再进一步添加调试信号,逐步定位到问题模块和逻辑,修正后再仿真,直至整个测试仿真都通过,那这个功能模块就初步通过了验证。

注:文章转自公众号:FPGA从入门到精通,作者:未可知摩尔

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FPGAtestbench是用于对使用硬件描述语言(HDL)设计的电路进行仿真验证的。它的主要目的是测试设计电路的功能和性能是否与预期的目标相符。编写testbench可以帮助开发者更好地理解和验证设计电路的行为。而且在FPGA行业中,具备编写testbench的能力是非常重要的,因为大部分公司都会让你来编写testbench测试文件。 一个基本的testbench通常包含三个部分:信号定义、模块接口和功能代码。信号定义部分用于定义输入输出信号的类型和大小,这些信号需要使用register类型来存储输入的数据。模块接口部分定义了需要测试的模块的输入输出接口。功能代码部分则包含了对测试模块进行功能验证的代码。 编写testbench时,需要遵循规范化的设计和苛刻的结构。testbench编写规范可以参考Modelsim仿真步骤的相关文档。 总结起来,FPGAtestbench是对设计电路进行仿真验证的重要工具,它需要包含信号定义、模块接口和功能代码三个部分,并且需要遵循规范化的设计和苛刻的结构。掌握编写testbench的能力对于在FPGA行业中的发展非常重要。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [【FPGA自学总结Testbench测试代码推荐编写规范](https://blog.csdn.net/zhaogoudan/article/details/111933722)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值