SystemVerilog(2):function和task、变量生命周期

1、function和task

1.1 构成

function [返回值类型] [名称]( [参数] );
task [名称]( [参数] );

1.2 返回值

  • 如果不需要返回值,那么返回值类型可以写为 void ,或者 省略不写
  • 如果需要返回值,需要使用关键字 return a,那么调用该 function,得到的就是 a 的值;
  • task 没有返回值,但可以用 return; 来打断 task 的运行;

1.3 参数

  • 参数可以为空,此时括号 ( ) 可以省略;
  • 参数可以是结构体,可以在括号内进行结构体声明;
  • 参数可以是数组,建议用关键字 ref 引入,以获取最佳性能;
    •  ref  端口是对变量(不能是net)的引用,它的值是该变量最后一次赋的值。 
    • 如果不希望调用函数时改变该数组的值,可以用关键字 const ref
  • 参数可以写明变量初始值,调用时未写参数则采用该初始值;
    • 参数未写明变量初始值,调用时未写参数则编译报错;
  • 参数一般会写明类型,如 int、bit,未写明则默认为 logic;
  • 参数一般会写明方向,如 input、output,未写明则默认为 input ;

1.4 其他

  • begin...end 不是必须的,在 SV 中可以省略;
  • function 内不能有耗时语句,而 task 可以,如 @、wait、#等;
    • 因此一般来说 function 不能调用 task,除非在由 fork...join_none 语句生成的线程中调用;
    • 可以这样记:task 的开头字母 t 表示 time,因此可以有耗时语句,而 function 不行;

2、变量声明周期

在 SV 中,数据可以分为局部变量和全局变量,它们的生命周期对应为动态生命周期(automatic)和静态生命周期(static)。

  • 动态生命周期(automatic):局部变量的生命周期同其所在域共存亡。
    • 例如 function/task 中声明 automatic 使用的临时变量。
    • 如果数据变量被声明为 automatic,那么进入该进程/方法后,automatic变量会被创建,离开该进程/方法后,automatic变量会被销毁。
  • 静态生命周期(static):全局变量即伴随着程序执行开始到结束一直存在。
    • 例如module中的变量默认情况下全部为全局变量。
    • 如果数据变量不特意声明为automatic或者声明为static,那么static变量在仿真开始时会被创建,在离开进程/方法后,static变量不会被销毁,且可以被多个进程和方法所共享。
module xxx

    //动态函数auto_cnt,变量cnt默认也是动态
    function automatic int auto_cnt(input a);
        int cnt = 0;
        cnt += a;
        return cnt;
    endfunction
    
    //静态函数static_cnt,变量cnt默认也是静态
    function static int static_cnt(input a);
        int cnt = 0;
        cnt += a;
        return cnt;
    endfunction
    
    //函数default_cnt默认属于静态,变量cnt跟着默认也是静态
    function int default_cnt(input a);
        static int cnt = 0; //static可以省略
        cnt += a;
        return cnt;
    endfunction

initial begin
    $display("@1 auto_cnt = %0d", auto_cnt(1));
    $display("@2 auto_cnt = %0d", auto_cnt(1));
    $display("@3 static_cnt = %0d", static_cnt(1));
    $display("@4 static_cnt = %0d", static_cnt(1));
    $display("@5 default_cnt = %0d", default_cnt(1));
    $display("@6 default_cnt = %0d", default_cnt(1));
end

endmodule
/* 输出结果
# @1 auto_cnt = 1
# @2 auto_cnt = 1
# @3 static_cnt = 1
# @4 static_cnt = 2
# @5 default_cnt = 1
# @6 default_cnt = 2
*/
  • 对于 static 变量,在声明时应该进行初始化,这只会伴随它的生命周期发生一次,不会随着被调用而被多次初始化。
  • 在 module、program、interface中定义的 task/function 默认都是 static 类型,其内变量也默认为 static。
    • 这些变量可以单独声明类型,即被显式声明为 automatic 或者 static。

 

参考资料:

[1] 路科验证V2教程

[2] 绿皮书:《SystemVerilog验证 测试平台编写指南》第2版

posted @ 2022-07-09 13:40  咸鱼IC  阅读(1612)  评论(0编辑  收藏  举报