Systemverilog中static、automatic区别

一、静态变量、动态变量说明:Systemverilog绿皮书P60。补充说明如下:

  • Verilog早期版本仅有静态生命周期的概念,同一个function或者task无论你调用多少次内部的变量都是分配的同一个地址,没有调用堆栈的操作;
  • 在Verilog-2001标准中引入了动态生命周期的概念,task或func中变量可以定义为automatic;
  • automatic主要用来描述在测试程序、抽象系统级、transaction级或总线功能模型中的验证程序。automatic也可以用来编写可重入的任务;
    • 重入:当一个任务的前一次调用仍在进行时,可以再次调用,递归就是重入的一种;

二、Example1:program中默认变量都为static,如下代码中变量和函func都是static类型。其执行结果为:

  • 0 factorial=1       1 factorial=1                                                        //正确结果
  • 2 factorial=1       3 factorial=1       4 factorial=1        5 factorial=1  //error
    • 分析:以n=5为例,下面每一行A值总是和传给func的参数保持一致,是因为A是static变量,只有一个存储地址,每次传入新值会覆盖之前的旧值;
      • f(5)=f(A)               //此时A=5
      •      =f(4)*A            //此时A=4
      •      =f(3)*A*A        //此时A=3
      •      =f(2)*A*A*A    //此时A=2
      •      =f(1)*A*A*A*A//此时A=1
      •      =1
    • 想要得到正确的阶乘func,在test()前增加automatic即可:program automatic test()
Example1:
`timescale 1ns/1ps
program test();
    //---define the function
    function integer factorial (input [31:0] operand);
        if (operand >= 2)
            factorial = factorial (operand - 1) * operand;
        else
            factorial = 1;
    endfunction: factorial

    //---test the function
    integer result;
    initial begin
        for (int n = 0; n <= 5; n++) begin
            result = factorial(n);
            $display("%0d factorial=%0d", n, result);
        end
    end
endprogram

三、static变量、automatic变量的区别:

  • 初始化:
    • static初始化不可综合,automatic初始化可以综合
    • static初始化实在仿真前,automatic初始化是在被调用时发生的
    • static在下次调用时保持上次调用后的值,automatic在下次调用时会开辟新的存储空间并重新初始化
  • 使用原则:
    • always和initial中,需要内嵌初始化就声明为automatic,不需要则用static:因为static只初始化一次,automatic每调用一次初始化一次
    • 如果task或func是可重入的,应设置被automatic的,其内的变量也应是automatic的
    • 如果task或func用来描述独立的硬件部分,且不可重入,应该设置为static,其内的变量也应为static
  • 关于以上“初始化”、“使用原则”可以看以下link例子;
    • “第三种”结果解释补充:代码count_ones中count=0只执行了一次;在主函数第二次调用count_ones(15)时,首先count_ones中count=0不执行,然后for循环中static中count为上一次主函数调用结果(3);即static变量的内嵌初始化只调用一次;

Systemverilog 静态变量 (static) 与 动态变量(automatic) 区别_小羊肖恩想的博客-CSDN博客_automatic变量

四、重点:Systemverilog中某些结构中默认static,某些结构中默认是automatic,具体如下:

  • 在module中声明的变量必须是静态变量;
  • module、program、function、task、begin...end、fork...join都默认是静态的,除module外剩下的可以使用automatic声明为动态变量;
  • class中的默认是动态的;

五、理解static、automatic需要引入堆、栈的概念,这里对其进行简单说明:

  • 堆-Heap与栈-Stack是开发人员必须面对的两个概念,在理解这两个概念时,需要放到具体的场景下,因为不同场景下,堆与栈代表不同的含义。一般情况下,有两层含义:
    • 程序内存布局场景下,堆与栈表示两种内存管理方式;
    • 数据结构场景下,堆与栈表示两种常用的数据结构。

Systemverilog中static、automatic区别_第1张图片

  • 如上图,以下堆、栈基础概念是基于程序内存方面的描述:
    • 堆-heap:由下向上,先进先出;
    • 栈-stack:有上向下,先进后出;
    • heap的空间远大于stack;
    • 软件代码中使用new(delete)、malloc(free)、allow申请空间的地方都是在heap;
    • Stack的空间是变化的,程序的压入(pop)导致栈变大(使用的是未分配空间),当程序出栈后,栈变小,使用空间返回给P区,即栈的空间大小非固定;

六、使用

  • 程序申请为automatic方式:
//申请为automatic之后,该task中所有申请的变量都是automatic类型
task automatic count_one(input bit[3:0] i_data);

//automatic需要放在void之前
function automatic void cal_freq(........);
  • Systemverilog中可以将将force封装为一个function、task,支持有或无输入参数,但是需注意输入的参数必须是static变量,因为force是一直生效的,如果是automatic,封装function、task退出之后,变量会被清除掉,不符合force使用原则:
    • 具体使用规则:
      • 直接force某个值,比如0/1/a之类的,可以在class中直接force;
      • force某个变量的值,比如 force dut.timer=timer,如果timer是一个动态变量的话,编译会报错“ Class data is not allowed in non-procedural context.”,简单的解法是把timer定义成static类型;
      • 如果2中不能简单定义成static类型的话,可以借用interface/bind module来实现......
      • 综上,就是force dut信号的右端一定要是静态的值
//本task实现内容是将clken_para中的参数force到dut内,此种方式属于白盒测试
//注意这里的w_clken_para内定义的参数都需要申请为static类型
task clken_force(input w_clken_para clken_para);

  • 在function、task中使用字符串为参数:
//func定义
function void w_std_clk_mux(input string sel_neme);// 这里的sel_name是形参
    case(sel_name)
        “core_clk”:begin ........................... end
        “temp_clk”:begin ........................... end
    endcase
    cal_freq(sel_name);//这里的cal_freq也是一个func,但是这里sel_name不能加""
endfunction

//func调用
w_std_clk_mux(“core_clk”);//这里的core_clk是实参

你可能感兴趣的:(SystemVerilog,经验分享)