4. SystemVerilog Task

## SV中的task

任务的基本语法

语法1

task [name];
  input [port_list];
  inout [port_list];
  output [port_list];
  begin
    [statements]
  end
endtask

语法2

task [name] (input [port_list], inout [port_list], output [port_list]);
  begin
    [statements]
  end
endtask

空端口列表

task [name] ();
  begin
    [statements]
  end
endtask

静态任务

Example:

module tb;
  initial display();
  initial display();
  initial display();
  initial display();
  // 这是一个静态任务
  task display();
    integer i = 0;
    i = i + 1;
    $display("i=%0d", i);
  endtask
endmodule

自动任务

Example:

module tb;
  initial display();
  initial display();
  initial display();
  initial display();
  // 注意任务现在是自动的
  task automatic display();
    integer i = 0;
    i = i + 1;
    $display("i=%0d", i);
  endtask
endmodule

全局任务

Example:

// 这个任务在所有模块之外
task display();
  $display("Hello World!");
endtask

module des;
  initial begin
    display();
  end
endmodule

如果任务是在模块内部声明的,则必须通过模块实例名来调用。

Example:

module tb;
  des u0();
  initial begin
    u0.display(); // 任务在模块 'tb' 中不可见
  end
endmodule

module des;
  initial begin
    display(); // 任务定义在模块内
  end
  task display();
    $display("Hello World");
  endtask
endmodule

函数与任务的区别

特性 函数 任务
时序控制 不能有时间控制语句/延迟 可以包含时间控制语句/延迟
任务启用 不能启用任务 可以启用其他任务和函数
参数类型 至少有一个输入参数,不能有输出或 inout 参数 可以有零个或多个任意类型的参数
返回值 只能返回一个值 不能返回值,但可以通过输出参数实现相同效果

Example:

module tb;
  reg signal;
  initial wait_for_1(signal);
  function wait_for_1(reg signal);
    #10; // 编译器会报错
  endfunction
endmodule

禁用任务

Example:

module tb;
  initial display();
  initial begin
    // 50 个时间单位后,禁用任务 'display' 中名为 T_DISPLAY 的块
    #50 disable display.T_DISPLAY;
  end
  task display();
    begin : T_DISPLAY
      $display("[%0t] T_Task started", $time);
      #100;
      $display("[%0t] T_Task ended", $time);
    end
    begin : S_DISPLAY
      #10;
      $display("[%0t] S_Task started", $time);
      #20;
      $display("[%0t] S_Task ended", $time);
    end
  endtask
endmodule