SV 过程块

过程块

scope: 域

  • 硬件域:例化硬件的空间
    • module ... endmodule
    • interface ... endinterface
  • 软件域:定义软件变量的空间
    • program ... endprogram
    • class ...  endclass

always

  • 用来描述硬件时序电路和组合电路的正确打开方式,因此只能在module或者interface中使用
  • 用法: always @(敏感信号列表)

initial

  • 只执行一次
  • initial和always一样,无法被延迟执行,在仿真一开始都会同时执行
  • initial和always之间在执行顺序上没有顺序可言
  • initial 不可综合,用于测试
  • initial 过程块可以在module、interface和program中使用
  • 使用begin ... end包裹

function

  • 可以在参数列表中指定输入参数(input)、输出参数(output)、输入输出参数(inout)、或者引用参数(ref)
  • 可以返回数值或者不返回数值(void);如果返回,使用关键字return
  • 默认的数据类型是logic,例如input [7:0] addr
  • 数组可以作为形式参数传递
  • 只有数据变量可以在形式参数列表中被生命ref类型,线网类型不能
  • 在使用ref时,有时候为了保护数据对象只被读取而不被写入。可以使用const的方式来限定ref声明的参数
  • 支持默认值
function int double_f0(int a);
  return 2*a;
endfunction

function void double_f1(input int a, output int b);
  b = 2*a;
endfunction

function void double_f2(inout int a);
  a = 2*a;
endfunction

function automatic void double_f3(ref int a);
  a = 2*a;
endfunction

initial begin: 
  int v1, v2;
  
  v1 = 10;
  v2 = double_f0(v1);
  $display("v1 = %0d, double function result is %0d", v1, v2);

  v1 = 10;
  double_f1(v1, v2);
  $display("v1 = %0d, double function result is %0d", v1, v2);

  v1 = 10;
  $display("v1 is %0d before calling double_f2(v1)", v1);
  double_f2(v1);
  $display("v1 is %0d (result) after calling double_f2(v1)", v1);

  v1 = 10;
  $display("v1 is %0d before calling double_f3(v1)", v1);
  double_f3(v1);
  $display("v1 is %0d (result) after calling double_f3(v1)", v1);
end

task

  • task无法通过return返回结果,只能通过output,inout 或ref的参数返回
  • task内可以置入耗时语句,而function不能;常见的耗时语句包括,@event、wait event、#delay等
  • task 中可以调用 task 和 function, 而 function 只能调用function
task double_t1(input int a, output int b);
  b = 2*a;
endtask

task double_t2(inout int a);
  a = 2*a;
endtask

task automatic double_t3(ref int a);
  a = 2*a;
endtask

task double_t2_delay(inout int a);
  a = 2*a;
  #10ns;
endtask

task automatic double_t3_delay(ref int a);
  a = 2*a;
  #10ns;
endtask

initial begin: 
  int v1, v2;
  
  v1 = 10;
  double_t1(v1, v2);
  $display("v1 = %0d, double task result is %0d", v1, v2);

  v1 = 10;
  $display("v1 is %0d before calling double_t2(v1)", v1);
  double_t2(v1);
  $display("v1 is %0d (result) after calling double_t2(v1)", v1);

  v1 = 10;
  $display("v1 is %0d before calling double_t3(v1)", v1);
  double_t3(v1);
  $display("v1 is %0d (result) after calling double_t3(v1)", v1);
end

inout vs  ref

initial begin: inout_vs_ref
  int v1, v2;
  v1 = 10;
  $display("v1 is %0d before calling double_t2_delay(v1)", v1);
  fork
    double_t2_delay(v1);
    begin #5ns; $display("@%0t v1 = %0d in task call double_t2_delay(v1)", $time, v1); end
  join
  $display("v1 is %0d (result) after calling double_t2_delay(v1)", v1);

  v1 = 10;
  $display("v1 is %0d before calling double_t3_delay(v1)", v1);
  fork
    double_t3_delay(v1);
    begin #5ns; $display("@%0t v1 = %0d in task call double_t3_delay(v1)", $time, v1); end
  join
  $display("v1 is %0d (result) after calling double_t3_delay(v1)", v1);
end

变量生命周期

动态: automatic

  • 如果数据变量被声明为automatic,那么进入该进程或方法后,automatic变量会被创建,离开进程或方法后被销毁

静态:static

  • 全局变量伴随程序执行开始到结束,module中的变量默认情况下全部为全局变量

  • static变量在仿真开始时会被创建,在进程或方法执行过程中,可以被多个京城和方法共享

static vs automatic

  • 对于automatic方法,其内部变量默认也是automatic,伴随automatic方法的声明周期建立和销毁
  • 对于static方法,其内部的所有变量默认为static类型
  • 无论是automatic或者static方法,可以对其内部定义的变量做单个声明。使其类型被显式声明为automatic或static
  • 对于static变量用户在声明是应该对齐做初始化,而初始化只会伴随他的生命周期发生一次,并不会随着方法调用被多次初始化
module tb1;

    function automatic int auto_cnt(input a);
        int cnt =0;
        cnt +=a;
        return cnt;
    endfunction

    function static int static_cnt(input a);
        int cnt=0;
        cnt += a;
        return cnt;
    endfunction

    function int def_cnt(input a);
        int cnt=0;
        cnt += a;
           return cnt;
    endfunction

    function int def_cnt_a(input a);
        automatic int cnt=0;
        cnt += a;
        return cnt;
    endfunction

    initial begin
        $display("@1  auto_cnt=%0d",   auto_cnt(1));
        $display("@2  auto_cnt=%0d",   auto_cnt(1));
        $display("@1  static_cnt=%0d", static_cnt(1));
        $display("@2  static_cnt=%0d", static_cnt(1));
        $display("@1  def_cnt=%0d",    def_cnt(1));
        $display("@2  def_cnt=%0d",    def_cnt(1));
        $display("@1  def_cnt_a=%0d",  def_cnt_a(1));
        $display("@2  def_cnt_a=%0d",  def_cnt_a(1));
    end
endmodule

/*
result
@1  auto_cnt=1
@2  auto_cnt=1
@1  static_cnt=1
@2  static_cnt=2
@1  def_cnt=1
@2  def_cnt=2
@1  def_cnt_a=1
@2  def_cnt_a=1
*/

原文地址:https://www.cnblogs.com/gareth-yu/p/14610793.html