SystemVerilog 第3章 过程语句和子程序
3.1 过程语句
-
SV可以使用C中的++/–/+=运算符
-
可以在语句块或各种语法结构中添加标识符
initial begin: example
…
end: example -
continue and break
continue:用于跳出本轮循环进入下一次循环
break:直接跳出循环
3.2 void函数
- 所有用于调试的子程序都应该定义成void函数,以便被task和function调用
- 如果调用函数并且忽略其返回值,可以使用void进行结果转换
void’(函数调用语句);
3.3 任务和函数概述
- verilog中task和function的明显区别
①function中不能包含延迟;②必须有返回值且被使用(SV中可以没有return语句,也可以只调用不使用);③function不可调用task - systemverilog中function可以在fork…join_none语句中调用task
- 不带参数的子程序在定义和调用时不需要带括号()
- task…endtask/function…endfunction足以定义子程序的边界因此不用使用begin…end
3.4 子程序参数
3.4.1 C语言风格port list
可以再port list中直接声明参数 方向,类型,位宽
task mytask1 (
output logic [31:0] x,
input bit [15:0] u,v
);
3.4.2 参数方向
默认port list的参数是logic输入
3.4.3 ref参数
- verilog中无法传递数组,SV中可以以引用的方式传递数组变量,ref参数对应的变量在子程序外随时可见
- ref参数只能用在动态(automatic)的子程序中
- const ref 类型用于指定参数为不可修改的常量
function void print_checksum(
ref bit [31:0] a[],
const ref bit [31:0] b[]
);
3.4.4 参数缺省值
- 未传递的参数可以使用缺省值
function void print_checksum(
ref bit [31:0] a[],
input bit [31:0] low=0,
input int high=-1
);
3.4.5 指定名字传递参数
- SV的task和function可以采用module的port语法指定要传递的参数名
initial begin
many(.c(5));
end
3.4.6 常见代码错误
- 在缺省情况下,参数类型与前一个参数相同
- 子程序中使用了非缺省输入类型的参数,应该明确指明所有参数的方向
3.5 子程序的返回
- return用于结束子程序(task不会返回任何东西,只是控制流程)
- 从函数中返回一个数组
①定义一个数组类型返回值的函数,那么函数名就默认就是一个数组变量(会占用堆栈空间)
②ref参数传递数组变量
3.6 局部数据存储
verilog中的所有对象都是静态的,子程序和局部变量都是静态地存储在固定位置
3.6.1 动态声明
SV中module、program、task、function默认是静态的,动态声明需要用automatic关键字
program automatic test;
…
endprogram
3.6.2 变量初始化
没有声明automatic时,静态变量&局部变量都在仿真前就有初值;声明automatic时,变量则是在仿真时候声明后才分配堆栈进行初始化赋值
3.7 时间值
- 使用timeunit和timeprecision代替`timescale语句时,必须每个带有延时的module都要声明
- 使用%t打印$time或$realtime时可以采用$timeformat指定显示格式
$timeformat(时间标度,小数位数,后缀字符串,最小宽度(包含单位及空格));
module timing;
timeunit 1ns;
timeprecision 1ps;
initial begin
$timefomat(-9,3,"ns",8);
#0.1ns $display("%t",$realtime);
end
end
- 可以将时间数值赋给变量,$realtime值赋给real/realtime变量,$time值赋给time变量(数值和单位间不可有空格)