taskは,taskに渡される変数の引数を定義して,結果を受ける変数定義の構文からenableにされます.
制御は,taskが完了した後で,processを有効に戻します.したがって,taskがタイミング制御を有した場合,taskをenableにした時刻と,制御が戻った時刻に差異が生じえます.taskは他のtaskをenableにすることができ,さらにそのtaskが別のtaskをenableにする数に上限は無いです.
どれだけのtaskがenableになろうとも,制御はすべてのenableにされたtaskが完了するまで返ってきません.
task_declaration ::= (From Annex A - A.2.7)
task [ automatic ] task_identifier ;
{ task_item_declaration }
statement
endtask
| task [ automatic ] task_identifier ( task_port_list ) ;
{ block_item_declaration }
statement
endtask
task_item_declaration ::=
block_item_declaration
| { attribute_instance } tf_ input_declaration ;
| { attribute_instance } tf_output_declaration ;
| { attribute_instance } tf_inout_declaration ;
task_port_list ::=
task_port_item { , task_port_item }
task_port_item ::=
{ attribute_instance } tf_input_declaration
| { attribute_instance } tf_output_declaration
| { attribute_instance } tf_inout_declaration
tf_input_declaration ::=
input [ reg ] [ signed ] [ range ] list_of_port_identifiers
| input [ task_port_type ] list_of_port_identifiers
tf_output_declaration ::=
output [ reg ] [ signed ] [ range ] list_of_port_identifiers
| output [ task_port_type ] list_of_port_identifiers
tf_inout_declaration ::=
inout [ reg ] [ signed ] [ range ] list_of_port_identifiers
| inout [ task_port_type ] list_of_port_identifiers
task_port_type ::=
time | real | realtime | integer
block_item_declaration ::= (From Annex A - A.2.8)
{ attribute_instance } block_reg_declaration
| { attribute_instance } event_declaration
| { attribute_instance } integer_declaration
| { attribute_instance } local_parameter_declaration
| { attribute_instance } parameter_declaration
| { attribute_instance } real_declaration
| { attribute_instance } realtime_declaration
| { attribute_instance } time_declaration
block_reg_declaration ::=
reg [ signed ] [ range ]
list_of_block_variable_identifiers ;
list_of_block_variable_identifiers ::=
block_variable_type { , block_variable_type }
block_variable_type ::=
variable_identifier
| variable_identifier dimension { dimension }
There are two alternate task declaration syntaxes.
2種類のtask宣言書式があります.
1つ目の書式は,"task"キーワードから始まり,オプション"automatic"やタスク名とセミコロンが続きます.そして,"endtask"で終わります."automatic"キーワードは,"automatic task"を宣言します.それは,ダイナミックにそれぞれの同時発生のタスクエントリーに割り当てられた,すべてのタスク宣言について再代入可能です.
"task item"宣言は,以下のように定義できます.
- Input 型引数
- Output 型引数
- Inout 型引数
- 手続きブロックで宣言可能な全ての型
2つめの書式は,"task",続いて"task名",丸括弧で閉じた"task_port_list"で始まります."task_port_list"は,0以上のコンマ区切りの"task_port_items"です.丸括弧を閉じたあとにセミコロンがあります."task body"が続き,そして"endtask"がきます.
どちらの書式においても,ポート宣言は,"tf_input_declaration","tf_output_declaration","tf_inout_declaration"で定義されるように同じ書式です.
オプション"automatic"キーワードのないタスクは,"static task"で,全ての宣言されたアイテムは静的に確保されます.これらのitemは,同時実行する全てのtaskの使い方間で共有されます.
オプションキーワード"automatic"のあるtaskは,"automatic tasks"です."automatic task"内の全てのアイテムは,それぞれの呼び出しに対して動的に確保されます."automatic task"のアイテムは,階層的な参照によりアクセスされます."automatic task"は,それらの階層的な名前を使うことで,起動されます.
taskを有効にする書式は,丸カッコ内のコンマ区切りの式リストのような引数を渡すことです.正式な書式を以下に示す.
task_enable ::= (From Annex A - A.6.9)
hierarchical_task_identifier [ ( expression { , expression } ) ] ;
task enableing書式のための引数リストは,オプショナルです.もし,引数リストが与えられるならば,そのリストは式のリスト順が,タスク定義内の引数リストの並び順と一致する必要があります.
タスクの引数がinputとして宣言された場合,関連する式はどのような式にもなれます.引数内の式評価順序は未定義です.タスクの引数がoutputまたはinoutとして宣言された場合は,厳密に手続き型代入(LRM9.2)の左辺として正しい式です.以下のitemsは,この要求を満たします.
- reg型,integer型,real型,realtime型,time型
- Memory references
Concatenations of reg, integer, real, realtime and time variables
- Concatenations of memory references
Bit-selects and part-selects of reg, integer, and time variables
task enabling構文の実行は,enabling構文でリストされた式から,task内で定義された引数へ,入力値が渡されます.
taskからの返り処理は,task output型とinput型の引数から,task enabling構文内の相当する変数へ,値が渡されます.
All arguments to the task shall be passed by value rather than by reference (that is, a pointer to the value).
taskへの全ての引数は,参照(値へのポインタ)よりも値渡しのほうがよい.
例1) 以下の例は,5つの引数を持つタスク宣言の基本構造を表します.
task my_task;
input a, b;
inout c;
output d, e;
begin
. . . // statements that perform the work of the task
. . .
c = foo1; // the assignments that initialize result regs
d = foo2;
e = foo3;
end
endtask
2つ目のタスク宣言様式を使うと,以下のように定義できます.
task my_task (input a, b, inout c, output d, e);
begin
. . . // statements that perform the work of the task
. . .
c = foo1; // the assignments that initialize result regs
d = foo2;
e = foo3;
end
endtask
以下の分はtaskをenableにします.
my_task (v, w, x, y, z);
task enabling引数 (v,w,x,y,z) は,タスク宣言時の(a,b,c,d,e)に相当します.task enablingの時刻において,inoput,inout型の引数(a,b,c)は,(v,w,x)で渡された値を受け取ります.例えば,task enablingの実行は,有効に以下の代入の原因を呼びます.
a = v;
b = w;
c = x;
task処理の一部のように,my_taskのためのtask定義は,c,d,eへ計算結果をおきます.task完了時,計算値をprocessを呼び出した元へ返すための以下の代入が適用されます.
x = c;
y = d;
z = e;
例2) 以下の例は,"traffic light sequencer"の記述をtsakを使って表します.
module traffic_lights;
reg clock, red, amber, green;
parameter on = 1, off = 0, red_tics = 350,
amber_tics = 30, green_tics = 200;
// initialize colors.
initial red = off;
initial amber = off;
initial green = off;
always begin // ライト制御用のシーケンス
red = on; // 赤色on
light(red, red_tics); // wait
green = on; // 緑色on
light(green, green_tics); // wait.
amber = on; // 琥珀色on
light(amber, amber_tics); // wait.
end
// task : 立ち上がりエッヂを'tics'回待って,'color'ライトをオフにする.
task light;
output color;
input [31:0] tics;
begin
repeat (tics) @ (posedge clock);
color = off; // ライトオフ
end
endtask
always begin // クロック波形
#100 clock = 0;
#100 clock = 1;
end
endmodule // traffic_lights.
タスクは,同時に1つ以上enableにされるかもしれません.automaticタスクの全ての変数は,その実施に特定の状態を保存するために,それぞれの同時発生のタスク実施で複製されるものとします.
staticタスクの全ての変数は,タスクの同時発生の起動の数にかかわらず,静的になるでしょう.なぜならば,モジュールインスタンスそれぞれで宣言している局所変数に対応するただ一つの変数があるので.しかし,モジュールインスタンスの異なるstaticタスクは,互いからの別々の格納場所があるものとします.
staticタスクで宣言された変数は,呼び出し間でそれらの値を保有するものとします.staticタスクで宣言された変数は,LRM 3.2.2で記述するように,デフォルト初期値に初期化されます.automaticタスクで宣言された変数は,変数のスコープに入ったときに,デフォルト初期値に初期化される.なぜならば,automaticタスクで宣言された変数は,task起動の終了時に,de-allocateされるので,変数はその後の場所では参照される所望の構造で使われない.
automatic taskのlocal variableに対してやってはいけないことを以下に示す.
- ノンブロッキング代入文や手続き型連続代入文を使って,値の代入をしないこと.
- 手続き型代入文や手続き型force文で参照されないこと.
- ノンブロッキング代入文のintra代入イベント制御で参照されないこと.
- $monitorや$dumpvarsのようなシステムタスクでトレースされないこと.