module tb;
reg clk,a,b;
reg c;
reg d;
initial begin
clk=0;
a=1;
b=0;
fork
begin
$display("___________________",$time);
repeat (2) @(posedge clk);
data_a(a,b,d);
end
begin
$display("********************",$time);
repeat (2) @(posedge clk);
data_b(a,b,c);
end
join
end
always #5 clk=~clk;
task data_a(input aa,input bb,output cc );
begin :block_1
reg test_signal;
begin
@(posedge clk)
test_signal<=0; $display("block_1--1------%d",test_signal); $display($time);
d<=aa;
@(posedge clk)
test_signal<=1; $display("block_1--2--------%d",test_signal); $display($time);
d<=bb;
@(posedge clk)
test_signal<=0; $display("block_1--3--------%d",test_signal); $display($time);
d<=bb+aa;
@(posedge clk)
test_signal<=1; $display("block_1--4--------%d",test_signal); $display($time);
d<=aa-bb;
end
end
endtask
task data_b(input aa,input bb,output cc );
begin :block_2
reg test_signal;
begin
@(posedge clk)
test_signal<=0;
cc<=aa; $display("block_2--1--------%d",cc); $display($time);
@(posedge clk)
test_signal<=1;
cc<=bb; $display("block_2--2--------%d",cc); $display($time);
@(posedge clk)
test_signal<=0;
cc<=bb+aa; $display("block_2--3--------%d",cc); $display($time);
@(posedge clk)
test_signal<=1;
cc<=aa-bb; $display("block_2--4--------%d",cc); $display($time);
end
end
endtask
endmodule
通过对上述的task进行分析,总结如下:
(1)task声明必须以task-endtask关键字包围,任务体必须以begin-end关键字包围;
(2)task中除了声明input、output 、inout等信号,如果在内部声明wire、reg变量,任务体必须有名字,也就是在第一个begin关键字后加冒号和块名 ;如果没有内部声明wire、reg变量,可以不加块名;
(3)task中声明为output的信号,认为是reg变量,在task中可以直接使用阻塞赋值或者非阻塞赋值;而且在调用task时,与output相对应的必须是reg变量,如data_a(a,b,d)中,d是reg变量;
(4)如果在task中对全局变量赋值,那么赋值结束后,全局变量就会立即改变;但是如果在task中对端口信号或者内部的变量进行赋值,则只有在任务结束之后,才将最后一次对端口信号或者内部变量的赋值传递到外部;例如data_a任务中,变量d是reg型全局变量,在data_a中对d的赋值会立即传递给d;而在data_b中,c 是任务声明的端口信号,只有对c的最后一次赋值才会传递到外部(reg c)。仿真波形如下: