【Verilog设计—Testbench仿真】基础知识,应知应会

一、testbench基本结构

通常,testbench没有输入与输出端口,应包括信号或变量定义、产生激励波形语句、例化设计模块以及监控和比较响应输出语句。

module test_bench;   
    //信号或变量定义声明
    //使用initial或always语句来产生激励波形
    //例化设计模块
    //监控和比较输出响应
endmodule

二、常用产生激励描述方式

(1)产生时钟的几种方式

  1. initial,产生占空比为50%的时钟
    initial
        begin
            clk = 0;
            #delay;
            forever
            #(period/2) clk = ~ clk;
        end
    
  2. always,产生占空比为50%的时钟
    initial
    	clk = 0;
    always
    	#(period/2) clk = ~ clk;
    
  3. repeat,产生确定数目的时钟脉冲
    initial
        begin
            clk = 0;
            repeat(6)
            #(period/2) clk = ~ clk;
        end
    
  4. 产生占空比非50%的时钟
    initial
    	clk = 0;
    always
        begin
            #3  clk = ~ clk;
            #2  clk = ~ clk;
        end
    

(2)产生复位信号的几种方式

  1. 异步复位
    initial
        begin
            rst = 1; 
            #100;            
            rst = 0;
            #500;
            rst = 1;
        end
    
  2. 同步复位①
    initial
        begin
    	    rst = 1; 
    	    @(negedge clk);  //等待时钟下降沿          
    	    rst = 0;
    	    #30;
    	    @(negedge clk);  //等待时钟下降沿
    	    rst = 1;
        end
    
  3. 同步复位②
    initial
        begin
    	    rst = 1; 
    	    @(negedge clk);  	     //等待时钟下降沿          
    	    repeat(3) @(negedge clk);  //经过3个时钟下降沿
    	    rst = 1;
        end
    

三、常用的Verilog调试语句

(1)两种调试信息打印语句——$display与$monitor

/*在终端上打印信号的ASCII值*/
initial 
    begin
        $timeformat (-9,1, “ns”,12);           //设置输出时钟格式
        $display(“stime clk rst pause ms_h ms_l s_h s_l m_h m_l”); //显示输入的字符串
        $monitor(“%t %b %b %b %b %b %b %b %b”,    //设置输出信号格式
        $realtime,clock,reset,pause,ms_h,ms_l,s_h,s_l,m_h,m_l);     //指定输出的信号
    end
  • $display:将函数内部双引号中的字符串输出在终端上,而$monitor则不同,它的输出是事件驱动的

上例代码中,$monitor信号列表中$realtime信号的变化会触发终端显示事件的发生,每次$monitor的触发将会把信号列表中的信号值显示在终端中。

  • $monitor:语句中的“%”用于定义信号列表中信号的输出格式。

例如,%t将信号按照时间格式输出,%b将信号按照二进制格式输出。另外Verilog HDL语言还提供了其它的输出格式,比如%h:十六进制、%d:十进制、%o:八进制等。

add wave  -hex /pulse_out_top_inst/Act_x   //Act_x的波形数据将会以十六进制的方式显示

add wave  -decimal /pulse_out_top_inst/Act_y  //Act_y的波形数据将会以十进制的方式显示

(2)timescales

'timescale 1ns/1ps                 //度量参考为1ns,精度为1ps

module testbench;
	…
    initial 
        begin
            #10 rst = 1;    //10个仿真时间延时,相当于10x1ns=10ns的仿真时间
	…
        end
    initial 
        begin
            //display语句将在每一个仿真推进布进中执行,也就是1ps执行一次
            $display (''%d, rst = %b"m $time, rst);
        end
endmodule
'timescale    reference_time / precision

其中,reference_time是单位时间的度量,precision决定了仿真的推进延迟精度,同时也要设置仿真的推进步进单位。

# 是延迟的意思,而#号后面的数字是延迟的数量,延迟的单位由`timescale控制

比如有:当代码指定`timescale 1ns/1ps,那么,#10就是延迟10ns的意思

PS:在同步时序数字逻辑电路的verilog代码中,是不能加入“#”进行延迟,这不是代码编写阶段能决定的。

(3)force与release

module	testbench;

    initial 
        begin
            rst = 1;           //在仿真时间零点将rst赋值1
            force data = 101;   //在仿真时间零点强制使data为101,并保持
            #30 rst = 0;      //在仿真绝对时间30将rst赋值0
            #50 release data;  //在仿真绝对时间80释放
		                       //data值将保持直到下一个对它的赋值语句
        end
endmodule

force与release语句可以用来强制对执行过程中的reg或wire型信号量赋值。

这两条语句共同完成一个强制赋值的过程。当一个被force的信号被release以后,这个信号将会保持当时的状态直到下一个赋值语句产生为止。

(4)assign/deassign

module	testbench;
	...
	initial 
        begin
            rst = 1;           //在仿真时间零点将rst赋值1
            force data = 101;
            #30 rst = 0;        //在仿真绝对时间30将rst赋值0
            #30 release data;
            ...
		end
	initial 
        begin
		#20 assign rst = 1;  //此条语句覆盖之前的赋值语句(即绝对时间零点的赋值)
		#30 rst = 0;        //绝对时间50对rst赋值0
		#50 release rst;     //绝对时间100释放rst信号
endmodule

PS:assign/deassign语句与force/release语句相类似,不过assign/deassign语句只能对设计中的reg型信号赋值。它们常常用来设置输入值。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章