原文网站:Verilog testbench编写进阶(1)–$display – 芯片天地
在仿真程序中我们可以利用modelsim或Vivado 自带的仿真程序设置和观察波形,但有时候利用数据列表、报告文件等会得到更好的效果。本文介绍的$display函数是激励文件中经常使用的系统函数,它可以很好的帮助我们观察运行结果,定位运行中出现的问题。需要注意的是$display函数只能用在仿真程序中,是不可综合的函数,因此不能在实体程序中使用。
1.$display 函数
$display函数系统任务的作用是用来在控制台输出信息。注意在控制台直接输出字符时,在没有其它控制字符的控制显示格式的情况下,字符串原封不动的显示在屏幕上。 如:
$display("the code is running...");
在终端屏幕上显示如下:
the code is running...
- 格式字符输出,如输出以10进制显示还是16进制显示等。这些格式是由%引导,后面紧跟表示进制的字符标识,如2进制为%b,8进制为%o,16进制为%h,10进制为%d等。其格式如下:
$display(“字符区” ,表达式1,表达式2,…);
表达式可是各种运算符组成的表达式,也可以是变量或常数,见例1:
例:
$display("data0= %b;data1= %o ; data2= %d; data3= %h",4, 6 ,12,13);
显示如下:
data0= 100;data1= 6 ; data2= 12; data3= d
- 换行
上例中所有的数据在终端上都显示在一行中,为了清晰需要每笔数占用一行,需要换行控制。换行是由\n实现的,如上例可以改写如下:
$display(" data0= %b; \ndata1= %o; \ndata2= %d; \ndata3= %h; \n", 4, 6 ,12,13);
显示如下:
data0= 100; data1= 6; data2= 12; data3= d;
- 显示系统时间,系统是时间是由$time标识,系统时间是指系统开始运行到目前为止消耗(或累积)的时间,例:
initial begin $display("simulation time= %t ; \n", $time); #10 $display("simulation time= %t ; \n", $time); #20 $display("simulation time = %t ; \n", $time); end
显示结果为:
simulation time=0; simulation time=10000; simulation time=30000;
例1:列表显示0到100的累加值
`timescale 1 ns / 1 ps
module tb_dis ();
integer i;
reg [12:0] acc;
initial
begin
acc = 0;
$display(" running time =%t ; acc value= %d " ,$time, acc);
for(i = 0; i < 101; i = i + 1)
begin
#10
acc = acc + i;
$display(" running time =%t ; i= %d ; acc value= %d " ,$time, i, acc);
end
#10;
$stop;
end
endmodule
在modelsim transcript 窗口列表显示如下:
.
.
.
Modelsim的仿真波形如下:
图1:
在对例化的模块输出显示时,一定要对$display函数适当的延时才能输出正确结果。观察例2的结果,就会知道,$display显示有一个Δ延时,如果没有一个适当的延迟,不会把上次的结果显示出来。
例2:$display 函数延时显示
module addab
(
input [3:0] a, b,
output [4:0] y
);
assign y = a + b;
endmodule
仿真程序:
module tb_dis ();
reg [3:0] a,b;
wire [4:0] y;
initial begin
a = 3;
b = 5;
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
#10
a = 4;
b = 5;
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
#10
a = 3;
b = 7;
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
#10
a = 2;
b = 6;
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
end
addab addab_inst
(
.a (a),
.b (b),
.y (y)
);
endmodule
从上面的结果看,对于例化的模块提供输入,紧接着调用$display,会显示上次结果。修改仿真程序如下:
module tb_dis ();
reg [3:0] a,b;
wire [4:0] y;
initial begin
a = 3;
b = 5;
#10
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
a = 4;
b = 5;
#10
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
a = 3;
b = 7;
#10
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
a = 2;
b = 6;
#10
$display("time =%t, a= %d, b=%d, y= %d ",$time ,a, b, y);
end
addab addab_inst
(
.a (a),
.b (b),
.y (y)
);
endmodule
修改后,显示结果就正常了。