Verilog testbench编写进阶(3)–$strobe,$write

原文网站: Verilog testbench编写进阶(3)–$strobe,$write – 芯片天地

在前面的几节课程中, 我们介绍了$display,$monitor 系统任务,本文介绍的$strobe任务也是激励文件中经常使用的系统任务,它可以很好的帮助我们观察运行结果,定位运行中出现的问题。需要注意的是$strobe任务只能用在仿真程序中,是不可综合的任务,因此不能在实体程序中使用。$strobe 任务的使用方法和$display非常类似,但是他们之间还是有些不同的。两者的区别在于:$strobe命令会在当前时间结束时执行;而$display是只要仿真器看到就会立即执行。

1.$strobe

$strobe系统任务和$display 系统任务的语法基本上是相同的。$strobe 也是在控制台窗口下,打印输出。 它是在当前的时间点结束时执行,而不是解析到当前的$strobe 立即执行。

$strobe(“字符区” ,表达式1,表达式2,...);

例1:首先,我们使用$display 做一个仿真程序

`timescale 1ns / 1ps

module tb_dis ();
 
reg [3:0] a,b;
wire [4:0] y = a + b;

initial begin
    a = 3;
    b = 2;
    $display("$display: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 4;
    $display("$display: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    b = 5;
    $display("$display: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 3;
    b = 7;
    $display("$display: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 2;
    b = 6;
    $display("$display: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
end

endmodule

在modelsim transcript 窗口列表显示如下:

# $display: time =  0, a= 3, b= 2, y= x 
# $display: time = 10, a= 4, b= 2, y= 5 
# $display: time = 10, a= 4, b= 5, y= 5 
# $display: time = 20, a= 3, b= 7, y= 9 
# $display: time = 30, a= 2, b= 6, y= 10  

我们会发现,仿真程序中在10ns 的位置使用$display 打印输出了两次,第一次时,a = 4,b的值保持0ns 的值; 第二次时,a = 4,b = 5值;这说明$display 对已经执行过的赋值都能正确打印出来,但对于 y = a+b 并没有将其计算的结果输出出来 。

例2:使用$strobe 测试阻塞赋值

`timescale 1ns / 1ps

module tb_dis ();
 
reg [3:0] a,b;
wire [4:0] y = a + b;

initial begin
    a = 3;
    b = 2;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 4;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    b = 5;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 3;
    b = 7;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 2;
    b = 6;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
end

endmodule

测试结果如下:

# $strobe: time =  0, a= 3, b= 2, y= 5 
# $strobe: time = 10, a= 4, b= 5, y= 9 
# $strobe: time = 10, a= 4, b= 5, y= 9 
# $strobe: time = 20, a= 3, b= 7, y= 10 
# $strobe: time = 30, a= 2, b= 6, y= 8

同样,我们只是改造上面的仿真程序, 将$display 替换为 $strobe 任务, 发现在10ns 位置也是打印两次, 这两次打印的结果相同。表明 当10ns结束时,$strobe 才进行的打印,这时: a = 4, b =5 ,同时将 y = a + b 的值也是计算完后,才打印输出的。

例2:使用$strobe 任务测试非阻塞赋值

`timescale 1ns / 1ps

module tb_dis ();
 
reg [3:0] a,b;
wire [4:0] y = a + b;

initial begin
    a <= 3;
    b <= 2;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a <= 4;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    b <= 5;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a <= 3;
    b <= 7;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a <= 2;
    b <= 6;
    $strobe("$strobe: time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
end

endmodule

控制台输出结果:

# $strobe: time =  0, a= 3, b= 2, y= 5 
# $strobe: time = 10, a= 4, b= 5, y= 9 
# $strobe: time = 10, a= 4, b= 5, y= 9 
# $strobe: time = 20, a= 3, b= 7, y= 10 
# $strobe: time = 30, a= 2, b= 6, y= 8 

同样, 我们会发现: 不论是阻塞赋值还是非阻塞赋值, $strobe 都是在当前时间点结束时,打印输出结果。

从上面演示的例子可以看出,当打印输出连续赋值语句或module例化的输出结果时,在当前的时间点内,$display无法输出当前运算结果,但 $strobe却可以显示组合逻辑结果。因此, 如果希望在当前时间点内打印连续赋值语句或module例化的输出结果推荐使用$strobe, 而其他情况下使用$display可以显示更多的细节。

2.$write

$write系统任务和$display 系统任务的语法基本上是相同的。$write和$display 的区别是$write 在打印输出时,没有换行的操作。

$write(“字符区” ,表达式1,表达式2,...);

例4:将例1 改造为$write 打印输出:

`timescale 1ns / 1ps

module tb_dis ();
 
reg [3:0] a,b;
wire [4:0] y = a + b;

initial begin
    a = 3;
    b = 2;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 4;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    b = 5;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 3;
    b = 7;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
    #10
 
    a = 2;
    b = 6;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d ",$time ,a, b, y);
end

endmodule

控制台输出的结果为:

$write: time = 0, a= 3, b= 2, y= x $write: time = 10, a= 4, b= 2, y= 5 $write: time = 10, a= 4, b= 5, y= 5 $write: time = 20, a= 3, b= 7, y= 9 $write: time = 30, a= 2, b= 6, y= 10  

这里我们看到使用$write 任务打印输出时,没有回车,换行的操作,在同一行内打印所有输出结果。

例5:将例1 改造为$write 任务 (手工添加换行)打印输出:

`timescale 1ns / 1ps

module tb_dis ();
 
reg [3:0] a,b;
wire [4:0] y = a + b;

initial begin
    a = 3;
    b = 2;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d \n",$time ,a, b, y);
    #10
 
    a = 4;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d \n",$time ,a, b, y);
    b = 5;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d \n",$time ,a, b, y);
    #10
 
    a = 3;
    b = 7;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d \n",$time ,a, b, y);
    #10
 
    a = 2;
    b = 6;
    $write ("$write : time =%05d, a= %d, b=%d, y= %d \n",$time ,a, b, y);
end

endmodule

控制台输出的结果为:

# $write: time =  0, a= 3, b= 2, y= x 
# $write: time = 10, a= 4, b= 2, y= 5 
# $write: time = 10, a= 4, b= 5, y= 5 
# $write: time = 20, a= 3, b= 7, y= 9 
# $write: time = 30, a= 2, b= 6, y= 10 

当手工添加\n后, 打印输出的结果和$display相同了。

3.格式化输出列表

%h或%H以十六进制的形式输出
%d或%D以十进制的形式输出
%o或%O以八进制的形式输出
%b或%B以二进制的形式输出
%c或%C以ASCII码字符的形式输出
%s或%S以字符串的形式输出
%t或%T以当前的时间格式的形式输出
%e或%E以指数的形式输出实型数
%f或%F以十进制的形式输出实型数
%g或%G以指数或者十进制的形式输出实型数,无论何种格式都以较短的结果输出
%x十六进制
%u十六进制
\n换行
\t相当于按一个Tab键
\\反斜杠字符\
\”双引号字符”
%%百分符号%

1、格式说明,由”%”和格式字符组成。它的作用是将输出的数据转换成指定的格式输出。格式说明总是由”%”字符开始的。

2、普通字符,即需要原样输出的字符。其中包括一些转义字符,下面的字符形式用于格式字符串参数中,用来显示特殊的字符。

在 Verilog 中, 转义符 一定是使用在双引号括起来的字符串中!

举例:

`timescale 1ns / 1ps

//`define VIVADO_ONLY
module tb_dis ();
 
localparam WIDTH = 8;
 
real r; 
integer i;
 
reg  [WIDTH - 1:0] a,b,c;
wire [WIDTH:0] y = a + b;

initial begin
    a = 2;
     b = 5;
     c = 9;
    $display("===> display print format testing.... <===");
     #10;

    $strobe ("$strobe: time =%05d, a= %h, b=%d, c=%o, y= %b ",$time ,a, b, c, y);
     #10;

    $strobe ("$strobe: time =%05d, a= %H, b=%D, c=%O, y= %B ",$time ,a, b, c, y);
     #10;
     

    $strobe ("$strobe: time =%05d, char = %c, char = %C  ",$time ,"M", "q");
     #10;

     $strobe ("$strobe: time =%05d, %s, %S ",$time , "Hello World !", "Hello World !");
     #10;

     $strobe ("$strobe: time =%t, %T ",$time ,$time);
     #10;
     
     r = 31415.926;
     $strobe ("$strobe: time =%05d, r = %e, r = %E ",$time ,r, r);
     #10;

     r = 31415.926;
     $strobe ("$strobe: time =%05d, r = %f, r = %F ",$time ,r, r);
     #10;

     r = 31415.926;
     $strobe ("$strobe: time =%05d, r = %g, r = %G ",$time ,r, r);
     #10;

     $strobe ("$strobe: time =%05d, a = %x",$time , r);
     #10;

     a = 33;
     b = 'o47;
     c = 8'hfe;
     i = -56;
     
     $strobe ("$strobe: time =%05d, a = %u, b = %u, c = %u",$time , a, i, c);
     #10;

     $strobe ("$strobe: time =%05d, Hello \n World !", $time);
     #10;

     $strobe ("$strobe: time =%05d, \t\t\tHello World !", $time);
     #10;

     $strobe ("$strobe: time =%05d, \\Hello World !\\", $time);
     #10;

     $strobe ("$strobe: time =%05d, \"Hello World !\"", $time);
     #10;

     $strobe ("$strobe: time =%05d, Hello World ! 100%%", $time);
     #10;
     
    $display("===> display print format test finished. <===");
     #10;
end

/*
addab  #(.WIDTH (WIDTH))
addab_inst
(
    .a (a),
    .b (b),
    .y (y)
);
*/ 
endmodule

控制台输出:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值