加入收藏 | 设为首页 | 会员中心 | 我要投稿 | RSSRSS-巴斯仪表网
您当前的位置:首页 > 电子发烧 > EDA技术

testbench书写过程

时间:2013-08-27  来源:123485.com  作者:9stone

各种文件的说明

  • Netlist Files:HDL code合成後出的.v,或是比路跑HSPICE的.sp
  • Stimulus Files:HDL的testbench.vvalue change dump成.vcd,.vcd再VTRAN成vector file (.vec)
                            .vec 是用netlistinput pattern用的
  • Configuration File:用定模,要取哪些的哪些息(如或流),以存在.out.log
                                 (如果是用GUI介面,可以不需要案)
  • Technology file:NanoSim uses a tech. file in place of MOS models during simulation
  • .out File  :行模後的出案,供turboWave直接取以示/流波形
  • .fsdb File:行模後的出案,供turboWave直接取以示/流波形
  • .log File  :模果的出,面有耗情的report

由於NanoSim是Transistor-level simulator,要行NanoSim有方式

  • 提供比路的spice netlist (.sp or .spi)MOS spice module (含/度格) -- 比模
  • 提供位路的gate-level netlist (.v),cell-base spice simulation module (not cell-base Verilog simulation module)MOS spice module (含/度格) -- 位模
  • 提供比路的spice netlist (.sp or .spi)位路的gate-level netlist (.v),以VCS搭配NanoSim做比位的混合模

书写testbench之前要了解测试单元的设计规范,要很清楚规范并且要有测试文档(test bench 的结构和测试情况)
以一个四位计数器为例,计数器程序如下:
//-----------------------------------------------------
// Design Name : counter
// File Name   : counter.v
// Function    : 4 bit up counter
// Coder       : Deepak
//-----------------------------------------------------
module counter (clk, reset, enable, count);
input clk, reset, enable;
output [3:0] count;
reg [3:0] count;
always @ (posedge clk)
if (reset == 1'b1) begin
  count <= 0;
end else if ( enable == 1'b1) begin
  count <= count + 1;
end

endmodule 
test plan 如下:本test bench是自动检测测试,我们的 test bench 测试环境如下图所示: 
 
待测试的设计(DUT)是 test bench中的一部分, 其中 test bench 有 clock generator, reset generator, enable logic generator, and compare logic, which basically calculate the expected count value of counter and compare the output of counter with calculated value.
测试的情况(根据设计说明确定,应尽量使测试完全):

  •  Reset Test : We can start with reset de-asserted, followed by asserting reset for few clock ticks and deasserting the reset, See if counter sets its output to zero.
  •  Enable Test: Assert/deassert enable after reset is applied.
  •  Random Assert/deassert of enable and reset.

Test bench设计过程
1. 通式,test bench也是一个模块,其中包括module名,一般是测试设计名加_tb;进行待测设计的例化;对初始端口的初始化;时钟的设计;测试结果的输出。具体如下:

  1 module counter_tb;
  2   reg clk, reset, enable;
  3   wire [3:0] count;
  4    
  5   counter U0 (
  6   .clk    (clk),
  7   .reset  (reset),
  8   .enable (enable),
  9   .count  (count)
 10   );
 11    
 12   initial begin
 13     clk = 0;
 14     reset = 0;
 15     enable = 0;
 16   end
 17    
 18   always 
 19     #5 clk = !clk;
 20    
 21   initial  begin
 22     $dumpfile ("counter.vcd");
 23     $dumpvars;
 24   end
 25    
 26   initial  begin
 27     $display(" time, clk, reset, enable, count");
 28     $monitor("%d, %b, %b, %b, %d",$time, clk,reset,enable,count);
 29   end
 30    
 31   initial
 32   #100 $finish;
 33    
 34   //Rest of testbench code after this line
 35    
 36 endmodule

时钟设计的方法:
系统函数的说明:
$dumpfile is used for specifying the file that simulator will use to store the waveform, that can be used later to view using waveform viewer.
$dumpvars basically instructs the Verilog compiler to start dumping all the signals to "counter.vcd".
$display is used for printing text or variables to stdout (screen), is for inserting tab. Syntax is same as printf.
$monitor keeps track of changes to the variables that are in the list (clk, reset, enable, count). When ever anyone of them changes, it prints their value, in the respective radix specified.
$finish is used for terminating simulation after #100 time units (note, all the initial, always blocks start execution at time 0)

2. 加rest逻辑
假如rest是异步的(activate reset anytime during simulation)利用'events'实现,events can be triggered, and also monitored to see, if a event has occurred.
  1 event reset_trigger;
  2   event  reset_done_trigger;
  3    
  4   initial begin
  5     forever begin
  6       @ (reset_trigger);
  7       @ (negedge clk);
  8       reset = 1;
  9       @ (negedge clk);
 10       reset = 0;
 11       -> reset_done_trigger;
 12     end
 13   end
code our reset logic in such a way that it waits for the trigger event "reset_trigger" to happen, when this event happens, reset logic asserts reset at negative edge of clock and de-asserts on next negative edge as shown in code below. Also after de-asserting the reset, reset logic triggers another event called "reset_done_trigger". This trigger event can then be used at some where else in test bench to sync up.

3. test case:每一个test case 在一个initial模块里,在一个测试中有多个test
case,可以利用 a event like "terminate_sim" and execute $finish only when this event is triggered. We can trigger this event at the end of test case execution. The code for $finish now could look as below.
例如 在加之前是这样的

  1  initial 
  2   begin: TEST_CASE
  3     #10 -> reset_trigger;
  4     @ (reset_done_trigger);
  5     @ (negedge clk);
  6     enable = 1;
  7     repeat (10) begin
  8       @ (negedge clk);
  9     end
 10     enable = 0;
 11   end 
加上之后
  1 initial 
  2   begin: TEST_CASE
  3     #10 -> reset_trigger;
  4     @ (reset_done_trigger);
  5     @ (negedge clk);
  6     enable = 1;
  7     repeat (10) begin
  8       @ (negedge clk);
  9     end
 10     enable = 0;
 11     #5 -> terminate_sim;
 12   end

4. 实现自动检验测试结果
首先功能上模拟待检测的设计。
然后加上检验逻辑,当检验逻辑结果和待检测设计结果不同时输出错误,并且停止仿真。

 1 always @ (posedge clk)
 2   if (count_compare != count) begin
 3     $display ("DUT Error at time %d", $time);
 4     $display (" Expected value %d, Got Value %d", count_compare, count);
 5     #5 -> terminate_sim;
 6   end
最后在所有上面的都书写完毕后将程序中的display, monitor去掉,就得到最终的test bench。
最终结果如下:
///////////////////////////////////////////////////////////////////////////
// MODULE               : counter_tb                                     //
// TOP MODULE           : --                                             //
//                                                                       //
// PURPOSE              : 4-bit up counter test bench                    //
//                                                                       //
// DESIGNER             : Deepak Kumar Tala                              //
//                                                                       //
// Revision History                                                      //
//                                                                       //
// DEVELOPMENT HISTORY  :                                                //
//               Rev0.0 : Jan 03, 2003                                   //
//                        Initial Revision                               //
//                                                                       //
///////////////////////////////////////////////////////////////////////////
module counter_tb;

reg clk, reset, enable;
wire [3:0] count;
reg dut_error;

counter U0 (
.clk    (clk),
.reset  (reset),
.enable (enable),
.count  (count)
);

event reset_enable;
event terminate_sim;

initial
begin
 $display ("###################################################");
 clk = 0;
 reset = 0;
 enable = 0;
 dut_error = 0;
end

always
  #5 clk = !clk;

initial?
begin
  $dumpfile ("counter.vcd");
  $dumpvars;
end

initial
@ (terminate_sim)  begin
 $display ("Terminating simulation");
 if (dut_error == 0) begin
   $display ("Simulation Result : PASSED");
 end
 else begin
   $display ("Simulation Result : FAILED");
 end
 $display ("###################################################");
 #1 $finish;
end

event reset_done;

initial
forever begin
 @ (reset_enable);
 @ (negedge clk)
 $display ("Applying reset");
   reset = 1;
 @ (negedge clk)
   reset = 0;
 $display ("Came out of Reset");
 -> reset_done;
end

initial begin
  #10 -> reset_enable;
  @ (reset_done);
  @ (negedge clk);
  enable = 1;
  repeat (5)
  begin
   @ (negedge clk);
  end
  enable = 0;
  #5 -> terminate_sim;
end

reg [3:0] count_compare;

always @ (posedge clk)
if (reset == 1'b1)
 count_compare <= 0;
else if ( enable == 1'b1)
 count_compare <= count_compare + 1;

always @ (negedge clk)
if (count_compare != count) begin
  $display ("DUT ERROR AT TIME%d",$time);
  $display ("Expected value %d, Got Value %d", count_compare, count);
  dut_error = 1;
  #5 -> terminate_sim;
end
endmodule


分享到:
来顶一下
返回首页
返回首页
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
栏目导航->EDA技术
  • 电子应用基础
  • 电源技术
  • 无线传输技术
  • 信号处理
  • PCB设计
  • EDA技术
  • 单片机学习
  • 电子工具设备
  • 技术文章
  • 精彩拆解欣赏
  • 推荐资讯
    使用普通运放的仪表放大器
    使用普通运放的仪表放
    3V与5V混合系统中逻辑器接口问题
    3V与5V混合系统中逻辑
    数字PID控制及其改进算法的应用
    数字PID控制及其改进
    恶劣环境下的高性价比AD信号处理数据采集系统
    恶劣环境下的高性价比
    栏目更新
    栏目热门