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

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

image.png


一、写在前面


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

image.png


二、系统函数 $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

image.png


Figure2

image.png


六、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文本编辑器使用实录

image.png


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


  • 多维数组:灭霸打个响指的功夫,看懂Verilog多维数组
  • clog2系统函数: 关于Verilog自动计算位宽的系统函数$clog2,这些是你不得不知道的
  • UDP用户原语:玩转UDP用户原语,这篇文章就够了
  • $monitor系统函数:放学前的最后几分钟,看懂Verilog中的monitor系统函数
  • generate语句:一把王者的时间,学会Verilog中的generate语句
  • parameter常量:玩转parameter与localparameter,这篇文章就够了
  • inout双向端口:通俗易懂的带你解读inout双向端口
  • task与function区别:芯片人必会的task与function区别详解


相关文章
|
6月前
|
数据采集 编解码 芯片
LabVIEW编程LabVIEW开发高级数据采集技术 计数器定时器的操作 例程与相关资料
LabVIEW编程LabVIEW开发高级数据采集技术 计数器定时器的操作 例程与相关资料
71 11
|
C++ Windows
[笔记]Windows核心编程《番外篇》几种常见的执行命令行方法
[笔记]Windows核心编程《番外篇》几种常见的执行命令行方法
102 0
|
6月前
|
Shell Linux C语言
【Shell 命令集合 系统设置 内置命令】⭐⭐Linux 测量程序的执行时间和资源使用情况 time命令 使用指南
【Shell 命令集合 系统设置 内置命令】⭐⭐Linux 测量程序的执行时间和资源使用情况 time命令 使用指南
71 0
|
Shell Linux Go
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
《Linux操作系统编程》第八章 Shell程序设计: shell 语言结构,包括测试、分支、循环、跳转、函数、语句组
117 0
一把王者的时间,学会generate语句【Verilog高级教程】
一把王者的时间,学会generate语句【Verilog高级教程】
一把王者的时间,学会generate语句【Verilog高级教程】
|
开发工具 git
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
593 0
STM32:定时器定时中断软件篇(内含:1.实验现象+2.代码编写思路+3.代码部分+4.定时器常用库函数详解)
|
XML JavaScript 前端开发
在FreeSWITCH中执行长期运行的嵌入式脚本–Lua语言例子
众所周知,FreeSWITCH中可以使用嵌入式的脚本语言javascript、lua等来控制呼叫流程。而更复杂一点操作可能就需要使用Event Socket了。其实不然,嵌入式的脚本也可以一直运行,并可以监听所有的Event,就像使用Event Socket起一个单独的Daemon一样。
|
存储 机器学习/深度学习 Unix