| 
												
						
						
												1#
						发表于 2015-03-29 22:34:37 
															
	" There are many ways " to code a
test case, it all depens on the creativity ot the Testbench designer.Testbench代码设计技巧 1
 1.
Clock logic设计技巧 1
 2.
Asynchronous reset设计技巧 1
 3.
System task之打印数据 2
 4.
System task之生成.vcd文件 3
 5.
System task之生成vec(vector
file)档 3
 
 1. Clock logic为方便对时钟进行修改,已经后续代码中的应用,定义为parameter或者`define更为方便,如下所示:
 //-------------------------------
 //clock units
 parameter PERIOD = 20; //20ns,50MHz
 always
 #(PERIOD/2) clk = !clk;
 2. Asynchronous reset意在设计一个异步复位的信号,故可在clk下降沿复位,同时也在clk下降沿释放。因此在testbench中我们要设计一段“释放→复位→释放”的代码。“event”是在testbench中能被触发,同时也能被监视的事件,过程如下:
 1) 释放
 2) 在某一时刻reset_trigger 触发事件
 3) 等待clk下降沿,复位
 4) 等待下一个下降沿,释放
 5) 触发reset_done_trigger事件(可在其他testbench中应用)
 代码如下所示:
 //-------------------------------
 //asynchronous reset event(low valid)
 event reset_trigger;
 event reset_done_trigger;
 initial
 begin
 forever
 begin
 @(reset_trigger);
 @(negedge clk);
 rst_n = 0;
 @(negedge clk);
 rst_n = 1;
 -> reset_done_trigger;
 end
 end
 //-------------------------------
 //asynchronous reset
 initial
 #50 -> reset_trigger;
 如上代码所示50ns后启动异步复位信号,波形如下所示。可见输出数据都为三态,知道复位开始有效。
 
  注:在时序严谨的工程中,asynchronous
reset必须同步化,言外之音,此处画龙点睛介绍此方法!
 
  1) 设计verilog代码,用触发器对异步复位信号同步化
 2) 整合例化
 3) 编译,仿真调试
 4) 在Instance中选择sync_ctrl下的sys_rst_n信号进行观察
 
  代码和波形如下所示:
 `timescale 1ns / 1ns
 module sync_ctrl
 (
 input clk,
 input rst_n,
 output sys_rst_n
 );
 //--------------------------------------
 //asynchronous rst_n synchronism
 reg     rst_nr1, rst_nr2;
 always @(posedge clk or negedge rst_n)
 begin
 if(!rst_n)
 begin
 rst_nr1 <= 1'b0;
 rst_nr2 <= 1'b0;
 end
 else
 begin
 rst_nr1 <= 1'b1;
 rst_nr2 <= rst_nr1;
 end
 end
 assign sys_rst_n = rst_nr2;
 Endmodule
 
  3. Asynchronous enable雷同以上异步reset信号,用event来完成对enable的仿真。此处异步enable信号在异步reset完成后,维持10clk,之后释放。在是能有效的时候addout自增,代码和波形如下所示:
 //-------------------------------
 //asynchronous reset & enable
 initial
 begin
 #10 -> reset_trigger; //asynchronous reset
 @(reset_done_trigger); //reset done
 @(negedge clk); //asynchronous enable
 enable = 1;
 repeat(10) //hold 10 cycles
 begin
 @(negedge clk);
 enable = 0; //asynchronous release
 end
 end
  此处
 4. Reset & enable random自然是随机的,因此极端情况下,我们也可以把异步复位和使能信号设置为随机信号,如下所示:
 //------------------------------
 //asynchronous reset & enable with random
 initial
 begin
 #10 -> reset_trigger;
 @(reset_done_trigger);
 fork
 repeat(10)
 begin
 @(negedge clk)
 enable = $random;
 end
 repeat(10)
 begin
 @(negedge clk)
 #100 rst_n = $random;
 end
 join
 End
 
  5. Simulation Terminate以上可见到,其实异步enable信号的initial到10个clk以后,test case没完,但是simulate 已经终止了。但如果有到个test case,每个case simulate完都进入terminate_sim,进行某些操作,会很方便。可在代码中稍作修改,写成terminate_sim的event,代码如下:
 //-------------------------------
 //asynchronous reset & enable
 event terminate_sim;
 initial
 begin
 #10 -> reset_trigger; //asynchronous reset
 @(reset_done_trigger); //reset done
 @(negedge clk); //asynchronous enable
 enable = 1;
 repeat(10) //hold 10 cycles
 @(negedge clk);
 enable = 0; //asynchronous release
 #10 -> terminate_sim;
 end
 //------------------------------
 //terminate state
 initial
 begin
 @(terminate_sim);
 $display("Terminating Simulation!");
 #10 $finish;
 end
 6. Task任务模块对于需要多次操作或者循环的任务,可以用task封装,方便调用。
 此处只做简单的介绍:
 //-------------------------------
 //stimulate random drive
 task din_task;
 begin
 //for()
 din1 = $random % 256;
 din2 = $random % 256;
 end
 endtask
 always@(negedge clk)
 datain_task;
  7. System task之自检Error在系统模拟验证中,采用比较模拟验证法代替波形观察法,以提高效率.
 无非是复制verilog中的内容,再写一遍,结果是不是一样,没有什么需要提的.
 8. System task之打印数据//-------------------------------
 //print the value to screen
 initial begin
 $display("\t\ttime,\tdout");
 $monitor("%d,\t4'h%x,",$time,dout);
 end
 Display: 正如C语言中的printf
 Monitor: 比print个稍微强大点,实时监测数据变化,变化的时候输出数据
 如下图所示,数据打印到screen如下(monitor检测的数据输出不能顶格很郁闷)
 
  9. System task之生成vcd文件Vcd文件即为value change dump,用固定格式保存波形数据。
 //-------------------------------
 //save the warmform
 initial begin
 $dumpfile("wave_test.vcd" );
 $dumpvars;
 End
 当本次仿真结束的时候,将波形数据保存到wave_test.vcd中,一边以后用warmform viewer查看。如下所示(不知道怎么看~~~~(>_<)~~~~ ):
 
  10. System task之生成vec文件Vec文件即为vector file矢量数据文件,用于Modelsim中保存数据的文件,在仿真测试中,相关数据测试,在必要的情况下有很大的好处。相关testbench代码如下所示,保存了仿真400ns过程中addout的变化:
 //-------------------------------
 //generate vector file
 integer openfile;
 initial
 begin
 //output to "wave_test.vec" and standard display
 openfile = $fopen("wave_test.vec");
 //generate header file of vector file
 $fdisplay(openfile,"/*------------------------------------------------------------------------");
 $fdisplay(openfile,"This confidential and proprietary software may be only
used as authorized");
 $fdisplay(openfile,"by a licensing agreement from CrazyBingo.");
 $fdisplay(openfile,"(C) COPYRIGHT 2012 CrazyBingo. ALL RIGHTS
RESERVED");
 $fdisplay(openfile,"This is the wave_test.vec vector file");
 $fdisplay(openfile,"-------------------------------------------------------------------------*/");
 $fdisplay(openfile,"\t\t\t\ttime,\taddout");
 //output all the information of node transition in the vector file
 $fmonitor(openfile,"%d,\t4'h%x",$time,addout);
 end
 生成的文件信息如下所示:
 
  11. Others$display,$fdisplay,$monitor,
 $strobe,$fopen,$fclose,$dump,$finish,
 $time,$write,$stop
 $random
 1) fork...join:并行任务
 2) integer i;for(i=0,i<256,i++) 循环
 3) $readmemb(“File_Name”, Test_Vector);  从文件中读取二进制输入激励码向量
 4) $readmemh(“File_Name”, Test_Vector); 从文件中读取二进制输入激励码向量
 5) reg [7:0] stim_array[0:15] 数组的运用
 |