SV打印部分


持续更新中

工作或学习中遇到的类似知识点会及时补充至此。


一、基础转义知识

字符说明
\n换行符
\t空一个TAB的距离
%h or %H or %x or %X以十六进制形式打印
%d or %D以十进制形式打印
%o or %O以八进制形式打印
%b or %B以二进制形式打印
%c or %C以ASCII码形式打印
%p or %P用于打印聚合表达式,如结构体、数组等
%s or %S以字符串形式打印
%t or %T打印当前时间
%e or %E以指数格式显示实数
%f or %F以小数形式打印,默认保留小数点后6位

二、$sformatf / $sformat (File I/O tasks and functions)

SV用户手册解释如下:
在这里插入图片描述
直接看代码:

module tb;
initial begin
		string	LP_str;
		string	LP_str1;
		
//--------$sformat方法--------
		$sformat(LP_str,"value is = %0d",5);
		$display("[$sformat method] xxx %s",LP_str);

//--------$sformatf方法--------
		LP_str1 = $sformatf("value is = %0d",5);
		$display("[$sformatf method] xxx %s",LP_str1);

//--------简写形式--------
		$display($sformatf("[$sformatf method] xxx value is = %0d",5));
end
endmodule

打印数据如下:
在这里插入图片描述

  • $sformat (最终输出变量,“字符串”,参数列表);
  • $sformatf (“字符串”,参数列表);

可以看出 $ sformat( ) 相对于$ sformatf( )多出一个“最终输出变量”,若想用其字符串,直接把它的“最终输出变量”拿去使用即可;而对于 $ sformatf( ) 若想使用它的字符串,则需要将它整体拿走。

思考:如果我们将代码中的 %s 全部换成 %p 的形式,打印内容是否有变化呢?
打印数据如下:
在这里插入图片描述
从上图可看出,%s是会将双引号内的字符串打印出,而%p则是将双引号与其内部字符串当作整体合并打印出!
注:这两个函数并不具备打印的功能,只是负责整理字符串,真正打印的应是$display( )函数。


三、$display / $write (Display tasks)

SV用户手册解释如下:
在这里插入图片描述

$display / $write (参数列表);

但我们经常为了显示打印信息的具体解释,通常会这么做:

$display / $write (“需要打印的数据信息”,参数列表);

1、$display

直接看代码:

module tb;
	initial begin
		parameter YEAR = 2022;
		$display("[testcase] This year is %0d ",YEAR);
		$display("[testcase] This year is %d ",YEAR);	
		$display("[testcase] This year is %h ",YEAR);		
		$display("[testcase] This year is %b ",YEAR);		
		$display("[testcase] This year is %o ",YEAR);				
	end
endmodule

打印数据如下:
在这里插入图片描述
注:%d是指输出与系统默认位宽一致的整数,位宽不足时,前面用空格补齐;而%0d是根据实际位宽的整数来显示,不用空格补齐。

2、$write

直接看代码:

module tb;
	initial begin
		parameter YEAR = 2022;
		$write("[testcase] This year is %0d ",YEAR);
		$write("[testcase] This year is %d ",YEAR);	
		$write("[testcase] This year is %h ",YEAR);		
		$write("[testcase] This year is %b ",YEAR);		
		$write("[testcase] This year is %o ",YEAR);				
	end
endmodule

打印数据如下:
在这里插入图片描述
对比一下以上两个函数会发现:
$write系统任务和 $display系统任务的打印信息是相同的。但其区别是 $write 在打印输出时,没有换行的操作!
因此添加 “\n” 会使它们变得相同。

module tb;
	initial begin
		parameter YEAR = 2022;
		$write("[testcase] This year is %0d\n ",YEAR);
		$write("[testcase] This year is %d\n ",YEAR);	
		$write("[testcase] This year is %h\n ",YEAR);		
		$write("[testcase] This year is %b\n ",YEAR);		
		$write("[testcase] This year is %o\n ",YEAR);				
	end
endmodule

打印数据如下:
在这里插入图片描述
这印证了SV用户手册的描述
在这里插入图片描述

3、$displayb / $displayo / $displayh / $writeb / $writeh / $writeh

$displayb / $displayo / $displayh 为例,$writeb / $writeh / $writeh 类同。

形如 $display 中代码描述的那样,若我们想将10进制的 2022 打印为用16进制形式表示的 000007e6 ,我们需在 “需要打印的数据信息” 中指定其为 %h 才可以。
但如果使用 $displayb / $displayo / $displayh ,就会省去这一步骤:

module tb;
	initial begin
		parameter YEAR = 2022;
		$displayh("[testcase] This year is  ",YEAR);						
		$displayo("[testcase] This year is  ",YEAR);						
		$displayb("[testcase] This year is  ",YEAR);						
	end
endmodule

打印信息如下:
在这里插入图片描述
$writeb / $writeh / $writeh 则不再赘述。


四、$fopen / $fclose/ $fwrite / $fscanf / $feof (File I/O tasks and functions)

SV用户手册对于 $ fopen$ fclose 解释如下:在这里插入图片描述

从上图可看出 $ fopen 为文件 打开 函数;

从上图可看出 $ fclose 为文件 关闭 函数。

DV过程中,当我们在编写测试用例 (TestCase) 时,有时会需要从DUT的输出端口获得大量数据,如果将数据全部打印至 .log 文件中或显示在命令行里,均可能会与要打印的其它类型的数据掺杂在一起,显得冗余度较高、杂乱无章,因此将这些同一种类的数据打印至属于各自单独的文件中,则显得美观且易于查看。

当接收来自DUT的数据时,此时意味着要对该文件进行 操作。在此之前,首先应对文件进行 打开(open) 操作,根据上图可知,需要使用到的表达式如下:

fd = $fopen (filename , type);

【fd 指 file_desc,为该文件的句柄。若该句柄为0,则打开文件失败,反之成功)。filename
为该文件的名称。需注意:1.该文件必须放在仿真工程的目录中;2.若在TestCase中调用该函数,须用“/”来定位该文件具体存在的路径。type 指以什么样的形式打开此文件。例如想在TestCase同级的out目录下生成名称为pengpengpeng的 .txt 形式的文件,即写为 fd1 = $fopen ("./out/pengpengpeng.txt",“w”) ; 即可)】

其中 type 类型部分说明如下表所示:

type类型说明
w打开新的ASCII文本文件,只写文件
r打开已存在的ASCII文本文件,只读文件
r+打开已存在的ASCII文本文件,读写文件
a打开ASCII文本文件,在打开的文件结尾处 继续添加内容
ab打开Binary二进制文本文件,在打开的文件结尾处 继续添加内容

打开文件后,需对文件进行 操作,因此选用 $ fwrite 函数将从DUT输出的数据写入至该文件中,SV用户手册对于 $ fwrite 解释如下:

在这里插入图片描述
从以上两图结合前文对 $fopen 的解释,遂转义如下所示:

$ fwrite (文件句柄,“以什么进制与格式写入”,参数列表);

因此 整个数据 写入 文件 的流程应为:

`timescale 1ns/1ps
module tb;
	integer		fd1		;//声明句柄
	reg	[7:0]	data1	;//DUT输出数据
//---打开文件---	
	initial begin
		fd1 = $fopen("./out/pengpengpeng.txt","w");
	end
//---写入数据---
	always @(posedge sysclk)begin
		$write(fd1,"%h\n",data1);
	end
endmodule

当需要从文件中读取DUT的数据时,此时意味着要对该文件进行 操作。在此之前,首先应对写入完毕的文件进行 关闭(close) 操作,只有进行了关闭操作后,文件才会被写入并保存,根据上图可知,需要使用到的表达式如下:

$fclose (fd);

【fd 指 file_desc,为该文件的句柄。若该句柄为0,则打开文件失败,反之成功)例如想关闭句柄为 fd1 的文件,即写为 $fclose (fd1) ; 即可)】

关闭文件后,需对该文件进行 操作,首先应对文件进行 打开操作 ,然后调用 $ feof 函数判断文件是否被系统读取完,最后调用 $ fscanf 函数将数据从文件中读取出,SV用户手册对于 $ feof$ fscanf 解释如下:
在这里插入图片描述
举个例子:
在这里插入图片描述
在这里插入图片描述
举个例子:
在这里插入图片描述

从以上四张图片遂转义如下所示:

$ feof (文件句柄);
$ fscanf (文件句柄,“以什么进制与格式读出”,参数);

因此 整个从文件 读取 数据 的流程应为:

`timescale 1ns/1ps
module tb;
	integer		fd2		;//声明句柄
	integer 	C1		;//声明句柄(可省略)
	reg	[7:0]	data2	;
	initial begin
//---先关闭写入好的文件---
		$fclose(fd1);
//---打开要读的文件,且变为 r---
		fd2 = $fopen("./out/pengpengpeng.txt","r");
//---判断系统是否已读取完毕
		while(!$feof(fd2))begin
//---开始读取数据
			C1 = $fscanf(fd2,"%h\n",data2)
		end
	end
endmodule

注意:如需要将所读取到的数据打印出,依旧需选择$display ( )函数!


五、$time / $realtime / $stime (Simulation time functions)

SV用户手册解释如下:
在这里插入图片描述

1、$time

在这里插入图片描述

简言之:$time 返回的是 64bits整数 (四舍五入取整)

举个例子:

`timescale 1ns/100ps
module tb;
	logic [4:0] L;
	parameter p1 = 1.43;
	parameter p2 = 1.44;
	initial begin
		#p1  L = 6;
		$display($time,"\n L value is %d",L); 
		#p2  L = 8;
		$display($time,"\n L value is %d",L);		
	end	
endmodule

打印出的数据为:
在这里插入图片描述
再来看一组:

`timescale 1ns/100ps
module tb;
	logic [4:0] L;
	parameter p1 = 1.47;
	parameter p2 = 1.49;
	initial begin
		#p1  L = 6;
		$display($time,"\n L value is %d",L); 
		#p2  L = 8;
		$display($time,"\n L value is %d",L);		
	end	
endmodule

打印出的数据为:
在这里插入图片描述
综上两组可以看出:
第一次打印的时间取决于 `timescale 1ns/100ps 中的 时间单位 (1ns) !不管是 1.43四舍五入到1 还是 1.47四舍五入到2 都是围绕着时间单位1ns来转换的;
第二次打印的时间 = 第一次延时的时间 + 第二次延时的时间的值,即 1.43ns + 1.44ns = 2.87ns ≈ 3ns / 1.47ns + 1.49ns = 2.96ns ≈ 3ns。

2、$stime

在这里插入图片描述

简言之:$stime 返回的是 32bits整数 时间单位 (四舍五入取整)

举个例子:

`timescale 1ns/100ps
module tb;
	logic L;
	parameter  p = 1.63;
	initial begin
		#p    L = 6;
		$display($stime,"L value is %d",L);	
		#p    L = 8;
		$display($stime,"L value is %d",L);	
	end
endmodule

打印出的数据为:
在这里插入图片描述
可以看出第一次打印的时间为2ns (因为时间单位为1ns,且必须为整数,所以四舍五入最后得出);
可以看出第二次打印的时间为3ns (1.63ns+1.63ns=3.26ns,四舍五入且为整数最后得出);
$stime 相对于 $time 从打印的数据中可以看出,表示时间的数值前的空格数减少了一半,这也是它们之间 唯一的区别返回的整数位宽,一个为64bits,另一个则为32bits

3、$realtime

在这里插入图片描述

简言之:$realtime 返回的是 实数

举个例子:

`timescale 1ns/100ps
module tb;
	logic L;
	parameter  p = 1.67;
	initial begin
		#p    L = 6;
		$display($realtime,"L value is %d",L);	
		#p    L = 8;
		$display($realtime,"L value is %d",L);	
	end
endmodule

打印出的数据为:
在这里插入图片描述
再来看一组:

`timescale 1ns/100ps
module tb;
	logic [4:0] L;
	parameter p1 = 1.87;
	parameter p2 = 1.47;
	initial begin
		#p1  L = 6;
		$display($realtime,"\n L value is %d",L);
		#p2  L = 8;
		$display($realtime,"\n L value is %d",L);		
	end	
endmodule

打印出的数据为:
在这里插入图片描述

综上两组可以看出:
第一次打印的时间取决于 `timescale 1ns/100ps 中的 时间精度 (100ps) ! 都是在0.1ns,也就是100ps的精度上实现了四舍五入的进位操作;
第二次打印的时间相对于 $ time$ stime的计算有着 显著差异!即第二次打印出的时间 = 第一次延时的进位操作后的值 + 第二次延时的进位操作后的值,即 1.7ns + 1.7ns = 3.4ns / 1.9ns + 1.4ns = 3.4ns。


六、$finish / $stop / $exit (Simulation control tasks)

SV用户手册解释如下:
在这里插入图片描述

1、$finish

SV用户手册关于 $finish 解释如下:
在这里插入图片描述

简言之:该函数会直接导致模拟器的 退出

当仿真遇到 $finish 时,会提示如下对话框:

在这里插入图片描述
如果选“是”,会直接退出Questasim;如果选“否”,指令行会出现代码是在哪一行执行了 $finish
在这里插入图片描述

2、$stop

SV用户手册关于 $stop 解释如下:
在这里插入图片描述

简言之:该函数会直接导致模拟器的 暂停

暂停后若想继续跑仿真,点击“continuerun”就完事了:

在这里插入图片描述

3、$exit

SV用户手册关于 $exit 解释如下:

在这里插入图片描述

简言之:在一个或多个 program 块中,当所有program中最后一个 initial 块结束的时候,仿真实际也默认结束了,就像执行了 $finish 一样。若其中一个 initial 中包含 forever 语句,则意味着仿真永远不会停下,但我们又想让其强行停下之后继续其他未完成的 initial 块或 program 块操作时,就必须调用 $exit

未完待续~


  • 26
    点赞
  • 218
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

进击的隼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值