Verilog学习之路(10)—仿真使用的系统任务

Verilog学习之路(10)—仿真使用的系统任务

一、前言

在Verilog HDL集成电路设计过程中,设计者完成RTL级描述后需要对设计进行设计确认。设计确认是设计者检查设计中是否包含缺陷的过程。设计确认可以通过仿真和验证来完成。仿真和验证能确保设计的完整性、可靠性、时效性以及先进性。

二、display和write

$display$write是Verilog中两种主要的标准输出任务,这两个系统函数都用于将特定信息输出到标准输出设备且语法格式相同。其中不同的是,$display带有行结束字符,即自动在输出后进行换行;而$write不自动行,可以用于在一行里输出多个信息。
其中格式化字符串常用的输出格式如下所示:
在这里插入图片描述
对其中的特殊字符输出如下所示
在这里插入图片描述

三、monitor

$monitor提供了监控和输出参数参数列表中的表达式或变量值的功能,当参数列表中变量或表达式的值发生变化时,整个参数列表中变量或表达式的值都将输出显示。
编写代码如下所示

module monitor_tb;

	integer a,b;
	
	initial begin
		a = 2;
		b = 4;
		forever begin
			#5 a= a + b;
			#5 b = a -1;
		end
	end 
	
	initial begin
		$monitor($time, ": a=%3d, b=%3d", a, b);
	end 

	initial begin
		#40 $finish;
	end 

endmodule

仿真结果如下
在这里插入图片描述
另外与$monitor相关的还提供了monitoron$monitoroff两种系统任务,其描述如下所示
在这里插入图片描述

四、strobe

$strobe系统任务用于某时刻所有语句都处理完后,在时间步的结尾输出一行格式化的文本。编写代码如下所示

module strobe_tb;
	
	reg a, b;
	initial begin
		a = 0;
		$display("a by display is %0d", a);
		$strobe("a by strobe is %0d", a);
		a =1;
	end 
	
	initial begin
		b <= 0;
		$display("b by display is %d", b);
		$strobe("b by strobe is %d", b);
		#5;
		$display("after #5, b by display is %d", b);
		$strobe("after #5, b by strobe is %d", b);
		b <= 1;
	end 

endmodule

仿真结果如下
在这里插入图片描述

五、time、realtime和timeformat

使用$timerealtime这两个时间系统函数可以得到当前的仿真时刻,不同的是,$time返回一个64比特的当前仿真时刻值,而$realtime以实型数据的形式返回仿真时间。
timeformat是用来设置时间格式化输出时的格式的,其使用如下所示:

$timeformat(units_number, precision_number, suffix_string, minimum_field_wdith);
  • units_number 是 0 到-15 之间的整数值,表示打印的时间值的单位:0 表示秒,-3 表示毫秒,-6 表示微秒,-9 表示纳秒, -12 表示皮秒, -15 表示飞秒;中间值也可以使用:例如-10表示以100ps为单位。其默认值为`timescalse所设置的仿真时间单位。
  • precision_number 是在打印时间值时,小数点后保留的位数。其默认值为0。
  • suffix_string 是在时间值后面打印的一个后缀字符串。其默认值为空字符串。
  • MinFieldWidth 是时间值字符串与后缀字符串合起来的这部分字符串的最小长度,若这部分字符串不足这个长度,则在这部分字符串之前补空格。其默认值为20。

编写代码如下所示:

`timescale 1ns/1ps

module time_tb;
	reg ts;
	
	initial begin
		$timeformat(-9, 3, "ns", 8);
		#2.1 ts = 1;
		$display("@$time:     %0t, ts = %d", $time, ts);
		$display("@$realtime: %0t, ts = %d", $realtime, ts);
		#2.1 ts = 0;
		$display("@$time:     %0t, ts = %d", $time, ts);
		$display("@$realtime: %0t, ts = %d", $realtime, ts);
		#2.1 ts = 1;
		$display("@$time:     %0t, ts = %d", $time, ts);
		$display("@$realtime: %0t, ts = %d", $realtime, ts);
		#2.1 ts = 0;
		$display("@$time:     %0t, ts = %d", $time, ts);	
		$display("@$realtime: %0t, ts = %d", $realtime, ts);
	end 

endmodule

仿真结果如下
在这里插入图片描述

六、finish和stop

系统任务$finish$stop用于对仿真过程的控制,分别表示结束仿真和中断仿真,其语法格式分别如下:

$finish;
$finish(n);
$stop;
$stop(n);

其中,n是参数,可以取0、1或2几个值,含义如下所示:
在这里插入图片描述

七、readmemh和readmemb

系统任务$readmemb$readmemh用来从文件中读取数据到存储器中,这两个任务可以在仿真的任何时刻被执行使用,其语法格式如下所示:

$readmemb("<file_name>", <memory_name>);
$readmemb("<file_name>", <memory_name>, <start_addr>);
$readmemb("<file_name>", <memory_name>, <start_addr>, <finish_addr>);
$readmemh("<file_name>", <memory_name>);
$readmemh("<file_name>", <memory_name>, <start_addr>);
$readmemh("<file_name>", <memory_name>, <start_addr>, <finish_addr>);

在这两个系统任务中,被读取的数据文件的内容只能包含空白位置(空格、换行符、制表符(tab)和换页符(form-feeds)、注释行(//形式的和/* … */的都可以)、二进制或十六进制的数字。
编写代码如下所示

module readmem_tb;
	reg [7:0] memory_b [0:7];
	reg [31:0] memory_h [0:31];
	integer i;
	
	initial begin
		// 把数据文件init_b.txt读入存储器中的给定地址
		$readmemb("init_b.txt", memory_b);
		// 把数据文件init_h.txt读入存储器中的给定地址
		$readmemh("init_h.txt", memory_h);
		// 显示初始化后的存储器内容
		for(i=0; i<8; i=i+1) begin
			$display("memory_b[%0d] = %b", i, memory_b[i]);
		end 
		for(i=0; i<8; i=i+1) begin
			$display("memory_h[%0h] = %h", i, memory_h[i]);
		end 
	end 

endmodule

任何编写init_b.txtinit_h.txt文件如下所示,可以用@<address在数据文件中指定地址,
init_b.txt如下所示:


11111111 01010101
00000000 10101010
@006
1111zzzz 00001111

init_h.txt如下所示:

@001
0 11
0 111
0 1111
0 11111

仿真结果如下
在这里插入图片描述

八、random

$random是产生随机数的系统函数,每次调用该函数将返回一个32位的带符号的整形随机数。$random的一般用法如下所示:

$random % b

其中,b为一常数且要求大于零,这样即可得到一个范围在-b+1b-1之间的随机数。
利用操作符{ }可以将函数$random返回的有符号整数变换为无符号数,其用法如下:

{$random} % b

其中,b为一常数且要求大于零,这样即可得到一个范围在0b-1之间的随机数。
编写代码如下所示

module random_tb;

	integer i;
	initial begin
		for(i=0; i < 8; i=i+1) begin
			$display("@%0d times, $random %% 10 = %d", i, $random%10);
		end
		for(i=0; i < 8; i=i+1) begin
			$display("@%0d times, {$random} %% 10 = %d", i, {$random}%10);
		end		
	end 

endmodule

仿真结果如下
在这里插入图片描述

九、附录

上一篇:Verilog学习之路(9)—计数器和移位寄存器
下一篇:

  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 学习verilog语言对于想从事数字电路设计和FPGA编程的人来说非常重要。Verilog是一种硬件描述语言,用于描述数字电路的行为和结构。它可用于设计和验证数字电路,以及实现FPGA和ASIC。 学习verilog语言需要具备一定的数字电路基础和编程基础。熟悉基本逻辑门以及其它数字电路原理如时序分析、时钟域、时钟树等等都是必须的。 在掌握数字电路基础知识之后,可以通过参考相应的书本或者官方文档来学习verilog语言。verilog学习过程主要包括语法基础、硬件建模和仿真验证等几个方面。 在语法基础方面,verilog的语法结构较为简单,主要包括模块、端口、信号和语句等等。在硬件建模方面,可以通过将数字电路的行为和结构转换为verilog代码的方式来描述数字电路。在仿真验证方面,可以通过工具如ModelSim等来验证代码的正确性。 总之,学习verilog语言是非常重要的,尤其对于数字电路的研究和硬件开发等领域的从业人员来说。通过学习verilog语言,可以更加深入地理解数字电路的行为和结构,同时也能够为个人职业发展带来很多机遇和挑战。 ### 回答2: 学习Verilog语言主要是为了能够熟练设计数字电路,尤其是数字集成电路。在学习Verilog语言之前,需要先了解数字电路的设计原理和基本构件以及Verilog语言的基本语法和特性。 在学习Verilog语言的过程中,需要通过学习Verilog语言的语法规则、数据类型、运算符、逻辑门等基本构件,掌握Verilog语言的基本使用方法。此外,还需要学习Verilog语言的模块化设计方法,以及如何实现并、非、或、异或等主要逻辑门。 在实际应用中,需要根据具体的设计任务,选择合适的模块、逻辑门和数据类型进行设计,并进行仿真和验证。学习Verilog语言需要注重练习和实践,通过不断地实践和调试,深入理解Verilog语言的特性和应用。此外,可以参考相关文献、教材和网络资源,加强自己的学习效果。 综合来说,学习Verilog语言是一个相对较为复杂的过程,需要耐心、细心和不断地实践。只有通过不断实践,才能够真正掌握Verilog语言的应用方法,并能够设计出有效的数字电路。 ### 回答3: Verilog是硬件描述语言之一,用于描述数字电路的行为和结构。学习Verilog语言对于从事数字系统设计、ASIC设计、FPGA设计及验证等领域的人员非常重要。 学习Verilog语言的过程中,首先需要了解其基本语法和数据类型,如模块、端口、电平、模拟时钟等。其次,需要理解Verilog的模块层次结构和实例化的概念,能够构建简单的数字电路和模块,并对其进行调试和仿真。 在学习过程中,需要掌握Verilog的基本操作,如数据类型转换、位运算和赋值运算等,并掌握常用的控制语句和循环语句的使用方法。此外,还需要学习并掌握如何使用Verilog进行模块和测试的验证,以及设计数字系统的方法。 学习Verilog语言需要有一定的数字电路基础和计算机科学背景,同时需要进行实际的练习和项目实践,通过实践掌握Verilog的应用技巧和调试方法。 总之,学习Verilog语言是一项非常重要的技能,一旦掌握了它,可以应用于各种数字电路设计和验证的领域,让我们更好地掌握数字系统开发和设计。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值