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
    评论
`writeCommand()`和`writeData()`是Adafruit_ILI9341库中用于向MIPI屏幕写入命令和数据的函数。下面是一个示例代码,演示如何使用这些函数向屏幕发送命令和数据: ```c++ #include <Adafruit_GFX.h> #include <Adafruit_ILI9341.h> #include <Wire.h> #define TFT_CS 10 #define TFT_DC 9 #define TFT_RST 8 Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST); void setup() { Wire.begin(); tft.begin(); // Send a command to set the display orientation tft.writeCommand(0x36); tft.writeData(0x08); // Landscape mode (swap X/Y) // Send data to draw a pixel at position (50, 50) tft.writeCommand(0x2A); tft.writeData(0x00); tft.writeData(50); tft.writeData(0x00); tft.writeData(50); tft.writeCommand(0x2C); tft.writeData(0xFF); } void loop() { // Your code here } ``` 在这个例程中,我们使用了`writeCommand()`和`writeData()`函数来向屏幕发送命令和数据。在`setup()`中,我们发送了两个命令,一个用于设置屏幕方向,另一个用于绘制一个像素点。我们首先使用`writeCommand()`发送命令,然后使用`writeData()`发送命令所需的数据。在这个例程中,我们使用了一个MIPI屏幕,并假设我们已经正确地初始化了它,并使用了标准的SPI和Wire库。 请注意,您需要根据您实际使用的屏幕和控制器来修改这些命令和数据。在Adafruit_ILI9341库中,还有许多其他的函数可用于向屏幕发送不同的命令和数据。您可以查看库的文档以获取更多信息。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值