Download presentation
Presentation is loading. Please wait.
Published byἸάειρος Πανταζής Modified 5年之前
1
TestBench的书写 TestBench的目标 TestBench的基本框架 书写TestBench的几种主要方法 HDL调试的主要方式
提高模拟验证效率的主要方法 综合前后模拟验证结果一致性的确定
2
TestBench的目标 测试、验证HDL代码的正确性; 测试、验证Design的功能、时序正确性; 待测试、验证的模块加载到模拟验证环境;
产生模拟验证所需的输入激励; 对输入激励码,构造出其对应的正确输出结果; 提供一种机制,自动判断Design的正确性
3
DUT (Design Under Test ) 输入激励产生 待模拟、验证的 Design 输出结果 比较 预期输出结果构造 模拟结果 正确性判断
4
The Simulation Environment
This is a simplified picture of the overall simulation environment. This section concentrates on testbench development strategies. design source model libraries testbench source simulator compile file input: stimulus,response simulate file output: test pats,reports
5
HDL代码调试 HDL代码 TestBench 逻辑模拟 修改HDL代码 综合
6
输入激励码的产生方式 由其它硬件/软模型产生待验证模块所需的输入激励码; 用HDL代码生成(On-the-fly);
事先产生所需的输入激励码并存于相应的文件中,使用时从文件中读取
7
软、硬件合作模拟 主要用于系统模拟验证 待模拟、验证的 设计模块 硬件 软模型 模拟、验证 结果评测 利用硬件的软模型 进行模拟验证
8
由其它硬件/软模型产生 待验证模块所需的输入激励码
优点: 能较全面模拟、验证Design在各种情形下的正确性; 自动产生待验证模块的输入激励码 易于管理、验证速度快 缺点: 必须有相应模块的硬件/软件模型支持; 必须有专门的验证环境支持; 代价昂贵 使用领域: 模型(Protocol)验证、系统模拟、设计投片前的确认。
9
用HDL代码生成DUT的输入激励码 注意事项: 将时钟信号、置/复位信号与其它信号分开并分别加以处理; 注意各种(各组)输入信号的时序关系;
注意所采用的延时表示方式(绝对延时/相对延时); 注意各种输入激励与时钟信号的关系
10
用HDL代码生成DUT的输入激励码 输入激励码产生方式: 用单独的always语句或assign赋值语句产生时钟信号;
用简单的initial语句块产生置/复位信号的激励; 在initial语句块中用循环语句块产生按一定规律变化的信号的激励码; 用Task过程产生特殊信号的输入激励; 用三态buffer产生或监控Bidirectional信号的激励; 必要时预估DUT的输出变化情形并加以比较
11
用HDL代码生成DUT的输入激励码 parameter Period = 10 ;
assign #(Period/2) clk = ~clk; 在输入激励产生过程中,可用fork/join 形式表示绝对时间 parameter Period = 10 ; always #(Period/2) clk = ~clk ; parameter Period = 10 ; always begin #(0.4*Period) clk = ~clk; #(0.6*Period) clk = ~clk; end parameter Period = 10 ; always fork #(0.4*Period) clk = ~clk; #Period clk = ~clk; join 时钟信号必须用initial语句赋初值
12
用HDL代码生成DUT的输入激励码 用initial语句块中的顺序过程语句描述一般信号 的输入变化情形 可采用绝对延时或相对延时表示方式;
优点: 直接、简洁,易于理解; 只需要列出输入信号的变化情形; 可用于各种输入信号(不包括时钟信号)激励的描述; 应用面广,适合于DUT的初始功能验证。 缺点: 难以管理; 难于过程化处理。
13
用HDL代码生成DUT的输入激励码 在initial语句块中用循环结构描述具有一定变化规则的输入激励信号 reg [7:0] A, B;
integer I; …… initial begin for (I=0;I<1024; I=I+1) A = $random %256; B = $random % 256; #Period; end 描述简单、明了、代码紧凑、易于管理 在initial语句块中存在
14
用HDL代码生成DUT的输入激励码 DUT 实例语句; 用一个或多个initial语句块产生DUT的 模拟激励向量;
module TestBench_Name ; 参数说明; 寄存器、线网类型变量的定义、说明; DUT 实例语句; 时钟信号定义、赋初值; 定义置/复位信号的变化情形; 用一个或多个initial语句块产生DUT的 模拟激励向量; 用Task、function定义DUT外部时序接口; endmodule 产生激励码的方式灵活、 容易产生中、小模块的激励码 不易管理
15
将模块不同功能的调测试输入激励码置于不同的HDL代码段,存于不同的文件中,使用时再用`include “文件名”形式调入
用HDL代码生成DUT的输入激励码 module TestBench_Name ; 参数说明; 寄存器、线网类型变量的定义、说明; DUT 实例语句; 时钟信号定义、赋初值; 定义置/复位信号的变化情形; `include “产生输入激励码的HDL代码段” ; endmodule 将模块不同功能的调测试输入激励码置于不同的HDL代码段,存于不同的文件中,使用时再用`include “文件名”形式调入
16
Using Verilog Tasks Use Verilog tasks in your testbench to encapsulate repeated operations. clk data_valid data_read data_read task cpu_read; begin #30 data_valid = 1; wait (data_read = = 1); #20 cpu_data = data_in; wait (data_read = = 0); #20 cpu_data = 8`hzz; #30 data_valid = 0; end endtask
17
Using Concurrent Statements
Use fork-join blocks in your testbench to concurrently activate parallel tasks. monitor initialize fork join execute module inline_tb; //declare variables //instantiate designs initial begin initialize_design; fork monitor_data; monitor_error; monitor_timeout; run_test; join end endmodule
18
Applying Stimulus Some common stimulus application techniques include:
In-line stimulus,applied from an initial block Stimulus applied from a loop or always block Stimulus applied from an array of vectors or integers Stimulus that is recorded during one simulation and played back in another simulation
19
In-Line Stimulus In-line stimulus has the following characteristics:
You list the variables only when their values change You can easily define complex timing relationships between signals The testbench can become very long for tests of real designs module inline_tb; wire [7:0] results; reg [7:0] data_bus,addr; DUT u1 (results,data_bus,addr); initial fork #10 addr = 8`h01; #10 data_bus = 8`h23; #20 data_bus = 8`h45; #30 addr = 8`h67; #30 data_bus = 8`h89; #40 data_bus = 8`hAB; #45 $finish; join endmodule
20
Stimulus From Loops Stimulus applied from a loop has the following characteristics: For each iteration you assign a new stimulus vector The timing relationships between signals are regular in nature The testbench is compact module loop_tb; wrie [7:0] response; reg [7:0] stimulus; reg clk; integer i; DUT u1 (response,stimulus); inititial clk = 0; always begin #10 clk = 1; #10 clk = 0; end initial begin for (i = 0;i <= 255;i=i + 1) @(negedge clk) stimulus = i; #20 $finish; endmodule
21
预设输入激励码向量方式 方法: 将所需的输入激励码用一定形式的向量表示; 输入激励码向量预存于文件中;
使用时从文件中按一定的时序节拍读入文件中的输入激励码向量
22
module multiplier8(A, B, Clk, Start, Mul, Done);
input [7:0] A, B; input Start; input Clk; output [15:0] Mul; output Done; reg [15:0] Mul; reg Done; Functional Description Stms; …… endmodule 1、从给定的输入激励码文件中读入输入A、B、Start的激励码及相应的预期输出结果Mul、Done; 2、TestBench预设一类向量以便读取输入激励码文件中的数据 3、输入激励码、预期的输出结果预存于文件中
23
Verilog HDL提供的支持 Verilog HDL提供了几个系统任务支持从文件中直接读取输入激励码向量
$readmemb(“File_Name”, Test_Vector); 从文件中读取二进制输入激励码向量 $readmemh(“File_Name”, Test_Vector);
24
二进制表示的输入激励码及其输出预期结果表示
输入激励码文件Test_Fixed.v //Start A[7:0] B[7:0] Done Mul[15:0] …….. 二进制表示的输入激励码及其输出预期结果表示 TestBench作相应的定义: Reg [7:0] A, B; Reg Start; …… Reg [33:0] Vector, Test_Vector[0:Test_Length]; ……. $readmemb(“Test_Fixed.v”, Test_Vector); For (I=0; I<Test_Length; I = I+1) 按一定时序将Test_Vector[I]送入Vector并送入A、B、Start;
25
十六进制表示的输入激励码及其输出预期结果表示
输入激励码文件Test_Fixed.v 十六进制表示的输入激励码及其输出预期结果表示 //Start A[7:0] B[7:0] Done Mul[15:0] 0004E0000 409D00000 …….. TestBench作相应的定义: Reg [7:0] A, B; Reg Start; …… Reg [33:0] Vector, Test_Vector[0:Test_Length]; ……. $readmemh(“Test_Fixed.v”, Test_Vector); For (I=0; I<Test_Length; I = I+1) 按一定时序将Test_Vector[I]送入Vector并送入A、B、Start;
26
Stimulus From Arrays Stimulus applied from an array has the following characteristics: You can load the stimulus from a data file directly into the array For each iteration you read a new stimulus vector from the array module array_tb; wire [7:0] response; reg [7:0] stimulus,stim_array[0:15]; integer i; DUT u1 (response,stimulus); initial begin $readmemb(“datafile”,stim_array); for (i = 0;i <= 15;i = i + 1); #20 stimulus = stim_array[i]; #20 $finish; end endmodule
27
Vector Capture and Playback
You can capture manufacturing test vectors at the boundary of a device model. parameter period = 20 wire [7:0] response; reg [7:0] stimulus; DUT u1 (response,stimulus); always apply (stimulus); always verify (response); task capture_tb; integer MCDR,MCDS; begin MCDR = $fopen(“response.dat”);if (!MCDR) $finish; MCDS = $fopen(“stimulus.dat”);if (!MCDS) $finish; clk) #(period - 1) begin $fdisplayb (MCDR, “ %b”,response); $fdisplayb (MCDS, “ %b”,stimulus); end endtask
28
Vector Capture and Playback
You can play back the saved stimulus and response vectors. parameter MAX_VECTOR = 255; wire [7:0] response; reg [7:0] stimulus,stim_array[0:255],resp_arry[0:255]; DUT u1 (response,stimulus); task playback_tb; integer MCDR,MCDS,i; begin $readmemb(“response.dat”,resp_array); $readmemb(“stimulus.dat”,stim_array); @(negedge clk) //synchronize to inactive clock stimulus = stim_array[0]; //apply 1st stimulus for (i = 0;i <=MAX_VECTOR;i = i + clk) begin if (response != = resp_array[i]) begin //check response $display(“ERROR:response is %b,should be %b”, response,resp_array[i], “\nTEST FALLED”); $finish; end if (i = = MAX_VECTOR) begin $display(“TEST PASSED”);$finish; end stimulus = stim_array[i + 1]; //apply next stimulus end endtask
29
Forcing Stimulus You can make two types of procedural continuous assignments: You can assign and deassign a register assign <lvalue> = <expression> This overrides any procedural assignment to the register initial begin #10 assign top.dut.fsm1.state_reg = `init_state; #20 deassign top.dut.fsm1.state_reg; end You can force and release a register or net This overrides all drivers of the signal #10 force top.dut.counter.scan_reg.q = 0; #20 release top.dut.counter.scan_reg.q;
30
HDL代码调试 HDL代码 TestBench 逻辑模拟 修改HDL代码 综合
31
HDL代码调试 HDL代码调试手段 逻辑模拟过程中,查看模拟波形,判断HDL描述的正确性; 逻辑模拟验证过程中加入相关的监控措施;
Verilog HDL语言中提供了下列系统任务可供使用: $display $fdisplay $monitor $time $write $strobe $fopen $fclose $dump $finish $stop 利用虚拟原型、估计综合及后设计的结果;
32
HDL代码调试 逻辑模拟验证 在TestBench中加入$strobe系统任务,记录、探测所关心的信号波形;
在逻辑模拟验证前,利用模拟器提供的功能,选择需要观察的信号并加以记录; 在TestBench中增加模拟结果与预期的正确结果的比较,检测不正确的HDL代码
33
Reporting Warnings and Errors
Use file output system tasks to report errors and warnings. A more sophisticated testbench would: Report an error to a centralized error handler Modify the test flow,depending upon the errors encountered Maintain error statistics,and report them at the end of the test task par_err_task; par_err) err_handle_task (`NONFATAL,`PARITY); endtask task cor_err_task; cor_err) err_handle_task (`NONFATAL,`CORRECTABLE);
34
逻辑模拟工具及逻辑模拟方法 Verilog-XL :Cadence 业界的“黄金模拟器”, SignOff的Foundry产家最多;
解释执行,与用户的交互性能好,但模拟速度较慢; 适合对小模块的HDL描述进行模拟验证; 调用方式: verilog +gui –s –f run.f 从Cadence的Composer界面启动,适合于对逻辑图进行模拟验证
35
逻辑模拟工具及逻辑模拟方法 NC-Verilog :Cadence 业界的“黄金模拟器”, SignOff的Foundry产家较多;
本征码编译,与用户的交互性能好,模拟速度快; 适合对大的设计进行模拟验证; 调用方式: ncxlmode +gui –s –f run.f 从Cadence的Composer界面启动,适合于对逻辑图进行模拟验证
36
逻辑模拟工具及逻辑模拟方法 VCS :Synopsys 本征码编译,与用户的交互性能好,模拟速度快; 适合对大的设计进行模拟验证;
提供了一整套Verilog HDL代码调试手段 调用方式: vcs +gui –s –f run.f
37
逻辑模拟工具及逻辑模拟方法 VSS :Synopsys 的VHDL模拟器 速度慢; 适合对小的VHDL代码进行模拟验证; 调用方式复杂
38
提高模拟验证效率的手段 在具体的模块HDL编码前,应有一整套模块的模拟、验证、测试的计划;
进程的敏感信号表中不能存在冗余的信号; 在系统模拟验证中,采用比较模拟验证法代替波形观察法,以提高效率; 在模块/系统功能模拟时,采用零延时或路径延时的模拟验证方式。
39
逻辑模拟中的延时考虑 延时方式: 零延时 路径延时 单元延时 最大/最小延时 动态延时
40
Run.f 的组织 Run.f文件中所包含的内容: 逻辑模拟方式 延时计算的控制方式 待模拟验证的模块的Verilog描述文件
单元库文件的读取方式 单元库文件所在的目录
41
/export/home/HDL/src/mult16.v /export/home/HDL/src/adder16.v ………..
+gui -s testfixture.verilog /export/home/HDL/src/mult16.v /export/home/HDL/src/adder16.v ……….. +libext+.v+ -y library_path ……. 模拟界面控制 TestBench 库文件 单元库所存的路径 单元库文件的读取方式控制
42
逻辑模拟结果一致性的确定 在TestBench中加入预期结果比较 利用波形比较工具检测逻辑模拟波形的一致性
Similar presentations