Verilogタスクの理解:関数との違い、構文、使用法
functionは入力に対して何らかの処理を行い単一の値を返すことを目的としますが、taskはより汎用的で、複数の結果値を計算し、outputおよびinoutタイプの引数でそれらを返すことができます。タスクには@、posedgeなどのシミュレーション時間を消費する要素を含めることができます。
構文
タスクはポートリストの引数セットを持つ必要はなく、その場合は空にできます。
// スタイル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
スタティックタスク
タスクがスタティックの場合、そのすべてのメンバ変数は、同時に実行されるように起動された同じタスクの異なる呼び出し間で共有されます。
task sum (input [7:0] a, b, output [7:0] c);
begin
c = a + b;
end
endtask
// または
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がoutputとして宣言され、呼び出し時にzと接続されているため、合計が自動的にcからzに渡されます。
オートマチックタスク
キーワードautomaticを指定するとタスクが再入可能になり、指定しない場合はデフォルトでスタティックになります。automaticタスク内のすべてのアイテムは、各呼び出しごとに動的に割り当てられ、同時に実行される同じタスクの呼び出し間で共有されません。automaticタスクのアイテムは階層参照でアクセスできないことに注意してください。
説明のため、異なるinitialブロックから並行して呼び出されるスタティックタスクdisplayを考えます。この場合、タスク内で宣言された整数変数はタスクのすべての呼び出し間で共有されるため、表示される値は呼び出しごとにインクリメントされるはずです。
module tb;
initial display();
initial display();
initial display();
initial display();
// これはスタティックタスク
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.
タスクをautomaticにすると、タスクの各呼び出しがシミュレーションメモリの異なる領域に割り当てられ、異なる動作をします。
module tb;
initial display();
initial display();
initial display();
initial display();
// タスクが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.
グローバルタスク
すべてのモジュールの外部で宣言されたタスクは、グローバルスコープを持ち、どのモジュール内からでも呼び出せるため、グローバルタスクと呼ばれます。
// このタスクはすべてのモジュールの外部にある
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(); // タスクはモジュール'tb'からは見えない
end
endmodule
module des;
initial begin
display(); // タスク定義はモジュールにローカル
end
task display();
$display("Hello World");
endtask
endmodule
xcelium> run Hello World Hello World xmsim: *W,RNQUIE: Simulation is complete.
functionとtaskの違い
Verilogの関数とタスクは似た目的を果たしますが、いくつかの顕著な違いがあります。
| Function | Task |
|---|---|
| 時間制御文/遅延を含められず、同じシミュレーション時間単位で実行される | 時間制御文/遅延を含められ、別の時間で完了する可能性がある |
| 上記ルールによりタスクを有効化できない | 他のタスクと関数を有効化できる |
| 少なくとも1つの入力引数が必要で、outputやinout引数は持てない | 任意のタイプの引数を0個以上持てる |
| 単一の値のみ返せる | 値を返せないが、output引数で同じ効果を得られる |
関数が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
// 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
最初のinitialブロックでdisplayタスクが起動されると、T_DISPLAYが開始し、時間が50単位に達したときに無効化されます。直ちに次のブロックS_DISPLAYが開始し、80単位で完了します。
xcelium> run [0] T_Task started [60] S_Task started [80] S_Task ended xmsim: *W,RNQUIE: Simulation is complete.
Verilog
- Verilogマスター:デジタル回路設計のための完全チュートリアル
- Verilog連結マスター:実践ガイド
- Verilog代入文の理解:種類、構文、ベストプラクティス
- Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
- Verilog関数のマスター:効率的なRTL設計のために
- Verilogタスクの理解:関数との違い、構文、使用法
- Verilog階層参照スコープのマスター:モジュールとブロックでの名前衝突回避
- Verilogクロックジェネレータ:設計と実装ガイド
- Verilog表示タスクのマスター:効率的なデバッグとログ出力
- Verilog数学関数のマスター:効率的なハードウェア設計のために
- Verilog $timeformatのマスター:精度と表示制御