Verilog 任务
function
旨在对输入进行一些处理并返回单个值,而 task
更通用,可以计算多个结果值并使用 output 返回它们 和 inout 类型参数。任务可以包含模拟耗时的元素,例如 @ , 摆姿势 和别的。
语法
任务不需要在端口列表中有一组参数,在这种情况下它可以保持为空。
// Style 1
task [name];
input [port_list];
inout [port_list];
output [port_list];
begin
[statements]
end
endtask
// Style 2
task [name] (input [port_list], inout [port_list], output [port_list]);
begin
[statements]
end
endtask
// Empty port list
task [name] ();
begin
[statements]
end
endtask
静态任务
如果一个任务是静态的,那么它的所有成员变量将在同一个任务的不同调用之间共享,该任务已经启动并发运行
task sum (input [7:0] a, b, output [7:0] c);
begin
c = a + b;
end
endtask
// or
task sum;
input [7:0] a, b;
output [7:0] c;
begin
c = a + b;
end
endtask
initial begin
reg [7:0] x, y , z;
sum (x, y, z);
end
任务启用参数 (x, y, z) 对应于任务定义的参数 (a, b, c)。由于a 和b 是输入,x 的值 和 y 将被放置在 a 和b 分别。因为 c 被声明为输出并与 z 连接 在调用期间,总和将自动传递给变量 z 来自 c .
自动任务
关键字 automatic
将使任务可重入,否则默认为静态。 自动内的所有项目 任务是为每次调用动态分配的,而不是在同时运行的同一任务的调用之间共享。注意 automatic
分层引用无法访问任务项。
为了说明,考虑 static 从不同的initial
调用的任务显示 并发运行的块。在这种情况下,任务中声明的整数变量在任务的所有调用中共享,因此每次调用时显示的值应该递增。
module tb;
initial display();
initial display();
initial display();
initial display();
// This is a static task
task display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
模拟日志xcelium> run i=1 i=2 i=3 i=4 xmsim: *W,RNQUIE: Simulation is complete.
如果任务是自动的,则任务的每次调用都会在模拟内存中分配不同的空间并且行为不同。
module tb;
initial display();
initial display();
initial display();
initial display();
// Note that the task is now automatic
task automatic display();
integer i = 0;
i = i + 1;
$display("i=%0d", i);
endtask
endmodule
模拟日志xcelium> run i=1 i=1 i=1 i=1 xmsim: *W,RNQUIE: Simulation is complete.
全局任务
在所有模块之外声明的任务称为 global 任务,因为它们具有全局范围,可以在任何模块中调用。
// This task is outside all modules
task display();
$display("Hello World !");
endtask
module des;
initial begin
display();
end
endmodule
模拟日志xcelium> run Hello World ! xmsim: *W,RNQUIE: Simulation is complete.
如果任务是在模块 des 中声明的,则必须引用模块实例名称来调用它。
module tb;
des u0();
initial begin
u0.display(); // Task is not visible in the module 'tb'
end
endmodule
module des;
initial begin
display(); // Task definition is local to the module
end
task display();
$display("Hello World");
endtask
endmodule
模拟日志xcelium> run Hello World Hello World xmsim: *W,RNQUIE: Simulation is complete.
function
的区别 和 task
尽管 Verilog 函数和任务的用途相似,但它们之间存在一些显着差异。
函数 | 任务 |
---|---|
不能有时间控制语句/延迟,因此在相同的仿真时间单元中执行 | 可以包含时间控制语句/延迟,并且只能在其他时间完成 |
由于上述规则,无法启用任务 | 可以启用其他任务和功能 |
应该有至少一个输入参数,不能有输出或输入参数 | 可以有零个或多个任意类型的参数 |
只能返回一个值 | 不能返回值,但使用输出参数可以达到同样的效果 |
当函数尝试调用 task
或者包含耗时语句,编译器报错。
module tb;
reg signal;
initial wait_for_1(signal);
function wait_for_1(reg signal);
#10;
endfunction
endmodule
模拟日志#10; | xmvlog: *E,BADFCN (testbench.sv,7|4): illegal time/event control statement within a function or final block or analog initial block [10.3.4(IEEE)].
禁用任务
可以使用 disable
禁用任务 关键字。
module tb;
initial display();
initial begin
// After 50 time units, disable a particular named
// block T_DISPLAY inside the task called '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
当显示 任务由第一个 initial
启动 块,当时间达到 50 个单位时,T_DISPLAY 开始并被禁用。下一个块 S_DISPLAY 立即启动并运行了 80 个单位。
xcelium> run [0] T_Task started [60] S_Task started [80] S_Task ended xmsim: *W,RNQUIE: Simulation is complete.
Verilog