放学前的最后几分钟,看懂monitor系统函数【Verilog高级教程】

芯片设计验证社区·芯片爱好者聚集地·硬件相关讨论社区·数字verifier星球
四社区联合力荐!近500篇数字IC精品文章收录
【数字IC精品文章收录】学习路线·基础知识·总线·脚本语言·芯片求职·EDA工具·低功耗设计Verilog·STA·设计·验证·FPGA·架构·AMBA·书籍

在这里插入图片描述

一、写在前面

本专栏为作者在 【数字IC手撕代码】 【数字IC笔试面经分享】 【数字IC工具解析】 以外开设的第四个独立专栏,旨在学习并提供有关Verilog硬件描述语言中非基础性的高阶语法特性知识,因本身专栏的独特定位,因此作者并不会涉及基础Verilog语言如阻塞式非阻塞赋值,过程块,数据类型等内容;同时受限于作者知识有限,本专栏也不会涉及System Verilog的相关内容,若按照IEEE的相关标准来看,本专栏将会聚焦Verilog-2005,即“IEEE Std 1364™-2005”以及之前的有关内容,提供相关的IC设计领域语法特性。以下为Verilog的进阶框图,有更多学习需求的读者可以检索相关英文标准进行学习。
在这里插入图片描述

二、系统函数 $monitor 是什么

$monitor 是一个内嵌在verilog标准中的系统函数,它的作用是持续的监视和显示任何变量、表达式的值

三、$monitor的使用方法

$monitor (“format_string”, parameter1, parameter2, … );

这里的format_string指的是表达式,parameter指的是变量名,跳转到monitor实例一看就知道怎么使用了

四、$monitor $display $strobe的区别

这三个内嵌的系统函数在verilog的standard中执行相同的功能,即打印相关的数据,但是他们之间也存在细微区别,理论解释和案例分析如下

  • $display 是打印当前值
  • $strobe 是打印当前时间step结束时的值(这里的step与`timescale的声明有关)
  • $monitor 是假如任何值发生更改,则在当前时间步的末尾打印值。同时 $monitor 只能调用一次顺序调用将覆盖前一个

我们将通过如下的例子进行简要解析

reg [3:0] a,b;
integer i;
initial begin
  $monitor("monitor a:%h b:%h @ %0t", a, b, $time);
  for(i=0; i<4; i=i+1) begin
    $strobe("strobe  a:%h b:%h @ %0t", a, b, $time);
    $display("display a:%h b:%h @ %0t", a, b, $time);
    case(i)
      0 : a = 4;
      1 : b = 1;
      2 : begin end // do nothing
      3 : {
    
    a,b} = 9;
    endcase
    $display("display a:%h b:%h @ %0t", a, b, $time);
    #1;
  end
end
display a:x b:x @ 0
display a:4 b:x @ 0
monitor a:4 b:x @ 0
strobe a:4 b:x @ 0
display a:4 b:x @ 1
display a:4 b:1 @ 1
monitor a:4 b:1 @ 1
strobe a:4 b:1 @ 1
display a:4 b:1 @ 2
display a:4 b:1 @ 2
strobe a:4 b:1 @ 2
display a:4 b:1 @ 3
display a:0 b:9 @ 3
monitor a:0 b:9 @ 3
strobe a:0 b:9 @ 3

这是一个摘自stackoverflow的案例,这里我们可以看出来monitor,display和strobe的区别,假如这里的timestep是1的话,strobe的打印时间是每个timestep的末尾执行

即使在testbench中打印strobe的语句在display的上面,但是实际执行时,strobe实在display的下面执行打印

同样的,我们也能发现内嵌在verilog standard中的有关monitor和display之间的逻辑

虽然在testbench中的monitor在仿真的#0时刻就打开了,但是实际打印过程中monitor也是出现在display的下面

五、$monitor 和 $fmonitor的区别

这两个系统函数也是我们需要进行区分的对象,其实区分起来也很简单,即fmonitor需要往文件里面写,假如我们simv-gui调用出可视化窗口进行仿真,monitor的监控数据会出现Figure1的位置处,假如用fopen去打开一个txt文件并想往里面写仿真结果,那么就需要使用fmonitor的函数了,他的结果会出现Figure2的文件中

Figure1
在这里插入图片描述
Figure2
在这里插入图片描述

六、monitor实例

博主写这篇文章的时候,上一篇手撕代码的是写的伪随机数生成器,索性直接把这个例子拿来用一下,具体这个RTL是要实现个啥,请读者们自行查阅前文内容
【数字IC手撕代码】Verilog伪随机数生成器|线性反馈移位寄存器|题目|原理|设计|仿真

我们将testbench修改如下

`timescale 1ns / 1ps
module LSFR_Tb();

reg clk;
reg rst_n;
wire out;

LSFR u1(.clk(clk),.rst_n(rst_n),.out(out));

always #5 clk = ~clk;

initial

begin
$monitor("t=%d ,out=%d",$time,out);
clk = 0;
rst_n=1;

#4
rst_n = 0;
#25
rst_n = 1;
#40;
#1000
$stop;

end
endmodule

再进行仿真, $monitor (“format_string”, parameter1, parameter2, … ) 的语句会对应在如下的打印中,每一次out的改变monitor都会打印相关的数据这是一个很简单的例子,假如在一个很复杂的设计中,我们通过fmonitor将大量的数据打印出来,可能就需要使用脚本语言和正则变换去对数据举行清洗和抓取了,vim编辑器其实也可以使用正则变换式,具体怎么用,可以参考这里,tcl,perl,python脚本语言怎么用,不在这里赘述了
【Vim】IC芯片设计/验证工程师的Vim文本编辑器使用实录
在这里插入图片描述

七、往期【Verilog】高级教程文章

猜你喜欢

转载自blog.csdn.net/weixin_43698385/article/details/123434647