SystemVerilog
基于SystemVerilog的测试程序
电路验证是确认所设计的电路功能正确性的过程,而仿真(simulation)是进行电路验证的主要手段,它可以及早发现所存在的设计问题,降低设计风险,节约设计成本。通常,仿真是通过编写测试程序(testbench)完成的。
测试程序也称为测试台,它是用于测试待测模块(Device Under Test, DUT)功能是否正确的一段SystemVerilog HDL代码,是不可综合的,由激励信号、DUT和输出响应三部分组成。
待测模块DUT:
1 | module sillyfunction(input logic a, b, c, |
测试程序示例:
1 |
|
10 表示延迟10个时间单位,$monitor, $time表示系统任务,
测试程序的模板如下:
1 | module testbench_name(); //testbench为顶层模块,不会被其他模块实例化,因此不需要任何端口 |
在SystemVerilog中,施加激励就是向DUT添加输入信号(即测试向量),主要有三种方法:
- 通过initial过程块施加(线性)激励;
- 通过always过程块施加(循环)激励,主要用于产生时钟信号;
- 通过文件施加激励。
通过initial过程块施加激励
在initial块中施加激励,每个仿真时刻只用列出值需要改变的信号。initial块只执行一次。
在一个测试程序中可以包含多个initial块,并且它们都是同时并行执行,因此需要特别注意,不要在多个initial块中,在同一个仿真时刻对同一个信号赋值,否则将产生冲突。
1 | initial begin |
1 | initial begin |
通过文件施加激励
将激励(测试向量)存放在一个文本文件中,测试程序从文件中读取激励,对DUT进行测试。
1 | module sillyfunction_tb(); |
1 | testvector.txt |
输出响应
在SystemVerilog中,输出响应是指在向DUT的输入端施加激励后,通过观察DUT输出的结果,并与预期结果进行比较,以验证电路功能是否正确。这一过程可通过观测波形图或借助SystemVerilog HDL提供的一系列系统任务显示输出结果来实现。
SystemVerilog HDL中常用的系统任务包括:
获取仿真时间:$time
显示信号值:$display, $monitor
结束/中断仿真:$finish, $stop
文件输入:$readmemb, $readmmemh
文件输出:$fopen, $fclose, $fdisplay, $fmonitor
获取仿真时间
获取仿真时间的系统任务的返回值使用由`timescale
定义的时间单位。如:
`timescale 1ns/1ps
`timescale 1ns/1ns
$time返回一个64位的整数时间值
$stime返回一个32位的整数时间值
$realtime返回一个实数时间值
如:$monitor($time,"a=%b b=%b c=%b y=%b",a,b,c,y)
显示信号值
显示信号值的系统任务包括:$display和$monitor
$display($time,"a=%b",a);
$monitor($time,"a=%b",a);
$display和$monitor的区别在于前者只有执行到该语句时才会进行显示操作,而后者是一个监视器,只要输出变量列表中的某个变量发生变化,就执行一次显示操作。后者使用更方便。
%h | %o | %d | %b | %c | %s | %t | %m |
---|---|---|---|---|---|---|---|
hexadecimal | octonary | decimal | binary | ASCII | 字符串 | 时间 | 模块名 |
结束/中断仿真
结束/中断仿真的系统任务包括:$finish和$stop,用于对仿真过程进行控制。
$finish;
$finish(n);
$stop;
$stop(n);
参数n可以取0, 1等值,”0”表示不输出任何信息,”1”表示给出仿真时间。
文件输入
在SystemVerilog HDL中文件输入不需要打开文件操作,直接读取文件即可,相关的系统任务包括:$readmemb和$readmemh,前者读取2进制数据,后者读取16进制数据。
$readmemb(“数据文件名”, 数组(存储器)名, <起始地址>, <结束地址>);
$readmemh(“数据文件名”, 数组(存储器)名, <起始地址>, <结束地址>);
起始地址和结束地址均可缺省。
文件格式:
可用”_”提高数据可读性
可包含单行或多行注释
可用空格或换行来区分单个数据
可以设定一个特定地址,规定其后的数据从该地址开始存储,格式如下:
@hex_addr
地址必须是16进制,且大小写不敏感,并且@和地址之间不允许有空格。
例如:
testmem.txt:
0000_0000
0110_0001 0011_0010
//地址3-255没有定义
@100 //hex, 256
1111_1100
//地址257-1022没有定义
@3FF
1100_0010
数组stim:
0 00000000
1 01100001
2 00110010
3
4
…
255
256 11111100
257
…
1022
1023 11000010
code:
1 | logic [7:0] stim [1023:0]; |
文件输出
在SystemVerilog HDL中文件输出需要先打开文件,相应的系统任务为$fopen,然后可以通过系统任务$fdisplay或$fmonitor将需要保存的信息输入到指定文件中。
1 | int MCD; |
$fopen打开指定文件并返回一个32位整数,若打开失败,则返回0。操作模式为w, w+, a, a+.
$fclose关闭打开的文件。
$fdisplay和$fmonitor的用法与$display和$monitor的用法一致。
自动化测试
示例:
1 | module sillyfunction_tb(); |
1 | at_vec.txt |
本文作者 : preccrep
原文链接 : https://preccrep.github.io/2021/04/01/SystemVerilog/
版权声明 : 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!