在RTL代码编写结束后,需要对其编写testbench完成对待测设计的例化,测试代码的封装,生成输入激励,收集输出相应,决定对错和衡量进度。
1. 验证平台结构
如图模仿设计的整个运行环境,虚线框为testbench。testbench是对DUT进行测试的方案描述文件,因此模块没有输入输出,用到的语句也是不可综合的,主要包含激励发生器,DUT,参考模型,监视器,比较器等。
2. 语法
本文介绍的testbench将以systemverilog和verilog语句为主,关于两种语言的具体语法参见:
systemverilog:IC验证——SystemVerilog学习_KGback的博客-CSDN博客_systemverilog验证
verilog:IC设计——Verilog HDL学习笔记_KGback的博客-CSDN博客
(1)结构说明语句
- always
包含verilog语法中always的用法。
- initial
仿真时对变量初始化,过程语句块,对clk,reset等输入信号初始化
- 不需要触发条件,仿真开始即执行
- 一个initial块执行一次,多个initial块并行执行
- task
执行消耗时间的电路,测试文件中主要的测试任务内容。通常用在需要耗时的信号采样或驱动场景中。
task apb_write(input [31:0] addr, input [31:0] wdata );
… //无需begin-end
endtask
- function
函数功能,function和task都是描述功能块,但function无时序控制,即不消耗时间,通常做一些声明,创建或纯粹的数字和逻辑运算的操作。因此用于调试的子程序都用过被定义成function而不是任务。
默认的数据类型是logic
function 类型 name(); //int void等
…
return 类型值; //缺省的返回值是与函数名name同名的变量值;void无return
endfunction
(2)语句
- fork…join / join_any / join_none
fork引导的并行块,其特点:
(1)并行块中所有语句同时执行。join是当按时间时序排序在最后的语句执行完或者执行disable语句时,程序流程跳出程序块;join_any当任意语句执行完后,程序跳出;join_none是fork块和外部程序同时执行
(2)块内每条语句的执行时间是相对于程序流程进入到块内的仿真时间的
(3)延时时间是用来给赋值语句提供执行时序的
(4)若fork…join中存在begin…end语句,则begin…end内语句为顺序执行
fork
块内声明语句 //块内声明语句可以是参数说明语句、 reg型变量声明语句、 integer型变量声明语句、
//real型变量声明语句、time型变量声明语句、事件(event)说明语句。
......
join
wait_fork; //等待所有fork进程执行完毕
disable_fork; //中断所有fork进程
- repeat
重复操作语句块
repeat(常数) begin
……
end
- `timescale
描述时间精度
`timescale 10ns/1ns //模块test的时间单位为10ns、 时间精度为1ns
parameter d=1.55; //根据时间精度,参数d值被从1.55取整为1.6。
#10 creg = areg; //在两条赋值语句间延迟10个时间单位。
- 系统任务
用于仿真、调试和验证,观察仿真执行的结果。该语句不可综合,在设计代码中不能存在,只能在调试阶段用。
- $display()
打印信息,可以放在initial和always模块中。
$display(“%d\n”, 10); //以10进制打印10后换行,同理 h(同x,16进制),o(八进制),b(二进制),
//c(ASCII字符),s(字符串),t(时间格式)
//一些特殊字符:\n(换行),\t(相当于tab键),\\(反斜杠),%%(百分符号)
$display(“@%0t a=%0d, b=%0d”, $time, a, b); //输出当前仿真时间,变量数值,例:@10 a=2, b=9
$display会自动换行,即$display(“”)和¥display(“\n”)意义一样 - $monitor($time, “a = %b, b = %h”, a, b)
一般是initial块的第一句,表示打开监控器,打印次数可以有很多次。
当信号a或b的值发生变化时,系统任务$monito显示当前仿真时间,信号a值(二进制), 信号b值(16进制)。 - $finish和$stop
Verilog仿真中即使DUT的输入激励已经执行完毕,仿真也会一直执行下去。
$finish结束仿真;$stop暂停仿真 - $time和$realtime
$time返回一个根据所在模块的时间精度要求进行舍入的64bit整数
$realtime返回一个带小数部分的完整实数 - $clog2(a)
类似于算式log2,即计算a的位宽
- 字符串操作
- $sformatf
字符串拼接
- 文件操作
- $fopen
打开文件,然后将原来文件清空
$fopen(“switch.txt”, “r”); //只读打开一个文件,只允许读数据 - $feof
判断文件是否结束,通常是通过$fread()和$fscanf()来识别 - $readmemh()和$readmemb()
将文件中的数据读到存储器中,h要求16进制,b要求2进制,文件中的数据按定义的位宽用空格间隔。
reg [31:0] memory [1023:0]; //1K word字长的存储单元
$readmemh(“file1”, memory); //把file1中的内容读1K word到memory中去详细使用可参考:
Verilog中的文件操作 – 与非网
verilog中$readmemb和$readmemh的使用_m0_38037810的博客-CSDN博客
- event 触发事件
event A, B; //声明
#10 ->A; //触发A
@(A); //等待A触发,触发信号为冲击信号,
wait( A.triggered ); //触发时会形成一小段电平信号
wait_order(A, B); //触发顺序A>B
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/82508.html