LRM読解(Chap.11)

2008/12/10 Verilog::文法import

11. 名前つきblockとtaskの無効化 ~ Disabling of named blocks and tasks

'disable'文は,Verilog HDLの手続き上の記述の構造化された本質を維持している間,併発してアクティブな手続きの実行(activity)を終了することに関する能力を与えます.

disable文は,taskの命令を全て実行する前に終了させることや,loop文からのbreakすることや,loop文のほかの反復とともに連続するため命令をスキップすること,のメカニズムを与えます.ハードウェア割込みやglobal resetのような例外状態をハンドリングするのに有用です.

disable_statement ::= (From Annex A - A.6.5)
    disable hierarchical_task_identifier ;
  | disable hierarchical_block_identifier ;

それぞれの様式のdisable文は,taskまたは名前付けされたブロックを終了します.処理は,blockに続く命令から,または,後のtask enabling文により再開します.また,名前つきblock内や,task内で有効になった,全ての活動(activities)は,終えられるものとします.

task enable文がネストしていて(1つのtaskがほかのtaskをenableにするような場合),一方が他方をまだenbaleにしていないならば,連鎖の中でtaskをdisableにすることは,下位の連鎖全てのtaskをdisableにすることである.

If task enable statements are nested that is, one task enables another,
 and that one enables yet another
  then disabling a task within the chain
   shall disable all tasks downward on the chain.

taskが1回以上enableにされるならば,そのようなtaskを無効にすることは,そのtaskの全ての起動が無効にされるものとします.(disableのqueingされたものが全て消える,という意味かしら??)

If a task is enabled more than once, then disabling such a task shall disable all activations of the task.

taskがdisableにされるなら,taskによって開始されるかもしれない以下の活動(activities)の結果は定義されません:

  • output引数とinout引数の結果
  • スケジューリングされたけれども実行されていないノンブロッキング代入
  • 手続き型連続代入(assign文とforce文)

disbale文は,disable文に含まれる,特殊なblockやtaskをdisableするのに,blockとtask内で使えます.disbale文は,function内の名前つきblockをdisableにすることができます.function内のdisable文があるところでは,blockかtaskをdisableにします.この挙動は未定義です.

automatic task中に,automatic taskまたはblockを無効化することは,タスクのすべての同時発生の実行のための通常のタスクのように続きます.(意味わからん)

Disabling an automatic task or a block inside an automatic task 
It proceeds as for regular tasks for all concurrent executions of the task.

例1) 本例は,blockが自身をdisableする方法を示します.

begin : block_name
  rega = regb;
  disable block_name;
  regc = rega; // この代入は実行されることはない.
end

例2) 本例は,disable文を,名前つきblockで,前方goto文と似たように使うことを示します(意訳).disable文の後の,次の命令文は,名前つきblockに続くものとなります.

begin : block_name
  ...
  ...
  if (a == 0)
    disable block_name;
  ...
end // 名前つきblockの終端
// 名前つきblockの後のコードから継続実行する
  ...

例3) この例は,taskからの早期returnのように使うdisable文を示します.しかし,diable文を使ってtask自身をdisableにすることは,プログラミング言語で見つけるようなreturn文のための速記(short-hand)ではありません.

task proc_a;
begin
  ...
  ...
  if (a == 0)
    disable proc_a; // trueであれば返る.
  ...
  ...
end
endtask

例4) この例は,C言語のcontinue/break文の2つと同じように使うdisable文を示します.例は,名前つきblockが,ループカウンタがnに達するまで繰り返すか,変数aがbの値にセットされるまで実行される,制御コードを示します.名前つきブロック"break"は,a==bになるまで実行するようなコードを含んでいます.このポイントでは,"disable break;"文が,blockの実行を終了します.名前つきブロック"continue"は,for loopのそれぞれの繰り返しを実行するコードを含んでいます.毎回,このコードは"disable continue;"命令をh実行し,"continue"blockを終了します.そして,次のfor loopの反復処理へ移ります.

"continue"blockの反復制御には,命令文セットは,a!=0であれば実行する.他の命令セットは,a!=bであれば実行する.(訳注:要はこの文だけ.)

begin : break
  for (i = 0; i < n; i = i+1) begin : continue
    @clk
      if (a == 0) // "continue" loop
        disable continue;
      <statements>
      <statements>
    @clk
      if (a == b) // "break" from loop
        disable break;
      <statements>
      <statements>
  end
end

例5) この例は,resetイベントが起きたときの,タイミング制御とtask"action"を同時実行を無効にするdisable文を示します.? being used to disable concurrently a sequence of timing controls and the task action, when the reset event occurs.

例は,"event_expr"と名づけられたシーケンシャルブロックと,イベント"reset"の発生を待つdisable文とから成るfork/join blockを示します.シーケンシャルブロックと,reset待ちとは,並行して実行します."event_expr"ブロックは,イベント"ev1"とイベント"trig"の三回の発生を待ちます.これら4つのイベントが生じて,さらに'd'時間単位経過したときに,task"action"が実行します.イベント"reset"がおきたとき,シーケンシャルブロック内のイベントにかかわらず,task"action"を含めて,fork/joinブロックは終了します.

fork
  begin : event_expr
    @ev1;
    repeat (3) @trig;
    #d action (areg, breg);
  end
  @reset disable event_expr;
join

例6) 次の例は,再トリガ可能な単安定のビヘイビア記述の例です.名前がつけられた"retrig"イベントは,単安定時間周期で再開します."retrig"が,250時間単位以内で起こり続けていると,Qは1となります.

always begin : monostable
  #250 q = 0;
end

always @retrig begin
  disable monostable;
  q = 1;
end


(個人的まとめ)
diable/continue文は,シミュレーションモデルで使うと効果的かもしれない.ハードウェア記述で使うのはナンセンスだろう.(合成できるかどうかも怪しいか. パラメータを使ってコンパイル時にのみインスタンスを複数生成することなんかには使えそう.)

LRM読解(Chap.11)

2008/11/28 Verilog::文法import

11. 名前つきblockとtaskの無効化 ~ Disabling of named blocks and tasks 'disable'文は,Verilog HDLの手続き上の記述の構造化された本質を維持している間,併発してアクティブな手続きの実行(activity)を終了することに関する能力を与えます.

disable文は,taskの命令を全て実行する前に終了させることや,loop文からのbreakすることや,loop文のほかの反復とともに連続するため命令をスキップすること,のメカニズムを与えます.ハードウェア割込みやglobal resetのような例外状態をハンドリングするのに有用です.

disable_statement ::= (From Annex A - A.6.5)
    disable hierarchical_task_identifier ;
  | disable hierarchical_block_identifier ;

それぞれの様式のdisable文は,taskまたは名前付けされたブロックを終了します.処理は,blockに続く命令から,または,後のtask enabling文により再開します.また,名前つきblock内や,task内で有効になった,全ての活動(activities)は,終えられるものとします.

task enable文がネストしていて(1つのtaskがほかのtaskをenableにするような場合),一方が他方をまだenbaleにしていないならば,連鎖の中でtaskをdisableにすることは,下位の連鎖全てのtaskをdisableにすることである.

If task enable statements are nested that is, one task enables another,
 and that one enables yet another
  then disabling a task within the chain
   shall disable all tasks downward on the chain.

taskが1回以上enableにされるならば,そのようなtaskを無効にすることは,そのtaskの全ての起動が無効にされるものとします.(disableのqueingされたものが全て消える,という意味かしら??)

If a task is enabled more than once, then disabling such a task shall disable all activations of the task.

taskがdisableにされるなら,taskによって開始されるかもしれない以下の活動(activities)の結果は定義されません:

  • output引数とinout引数の結果
  • スケジューリングされたけれども実行されていないノンブロッキング代入
  • 手続き型連続代入(assign文とforce文)

disbale文は,disable文に含まれる,特殊なblockやtaskをdisableするのに,blockとtask内で使えます.disbale文は,function内の名前つきblockをdisableにすることができます.function内のdisable文があるところでは,blockかtaskをdisableにします.この挙動は未定義です.

automatic task中に,automatic taskまたはblockを無効化することは,タスクのすべての同時発生の実行のための通常のタスクのように続きます.(意味わからん)

Disabling an automatic task or a block inside an automatic task 
It proceeds as for regular tasks for all concurrent executions of the task.

例1) 本例は,blockが自身をdisableする方法を示します.

begin : block_name
  rega = regb;
  disable block_name;
  regc = rega; // この代入は実行されることはない.
end

例2) 本例は,disable文を,名前つきblockで,前方goto文と似たように使うことを示します(意訳).disable文の後の,次の命令文は,名前つきblockに続くものとなります.

begin : block_name
  ...
  ...
  if (a == 0)
    disable block_name;
  ...
end // 名前つきblockの終端
// 名前つきblockの後のコードから継続実行する
  ...

例3) この例は,taskからの早期returnのように使うdisable文を示します.しかし,diable文を使ってtask自身をdisableにすることは,プログラミング言語で見つけるようなreturn文のための速記(short-hand)ではありません.

task proc_a;
begin
  ...
  ...
  if (a == 0)
    disable proc_a; // trueであれば返る.
  ...
  ...
end
endtask

例4) この例は,C言語のcontinue/break文の2つと同じように使うdisable文を示します.例は,名前つきblockが,ループカウンタがnに達するまで繰り返すか,変数aがbの値にセットされるまで実行される,制御コードを示します.名前つきブロック"break"は,a==bになるまで実行するようなコードを含んでいます.このポイントでは,"disable break;"文が,blockの実行を終了します.名前つきブロック"continue"は,for loopのそれぞれの繰り返しを実行するコードを含んでいます.毎回,このコードは"disable continue;"命令をh実行し,"continue"blockを終了します.そして,次のfor loopの反復処理へ移ります.

"continue"blockの反復制御には,命令文セットは,a!=0であれば実行する.他の命令セットは,a!=bであれば実行する.(訳注:要はこの文だけ.)

begin : break
  for (i = 0; i < n; i = i+1) begin : continue
    @clk
      if (a == 0) // "continue" loop
        disable continue;
      <statements>
      <statements>
    @clk
      if (a == b) // "break" from loop
        disable break;
      <statements>
      <statements>
  end
end

例5) この例は,resetイベントが起きたときの,タイミング制御とtask"action"を同時実行を無効にするdisable文を示します.? being used to disable concurrently a sequence of timing controls and the task action, when the reset event occurs.

例は,"event_expr"と名づけられたシーケンシャルブロックと,イベント"reset"の発生を待つdisable文とから成るfork/join blockを示します.シーケンシャルブロックと,reset待ちとは,並行して実行します."event_expr"ブロックは,イベント"ev1"とイベント"trig"の三回の発生を待ちます.これら4つのイベントが生じて,さらに'd'時間単位経過したときに,task"action"が実行します.イベント"reset"がおきたとき,シーケンシャルブロック内のイベントにかかわらず,task"action"を含めて,fork/joinブロックは終了します.

fork
  begin : event_expr
    @ev1;
    repeat (3) @trig;
    #d action (areg, breg);
  end
  @reset disable event_expr;
join

例6) 次の例は,再トリガ可能な単安定のビヘイビア記述の例です.名前がつけられた"retrig"イベントは,単安定時間周期で再開します."retrig"が,250時間単位以内で起こり続けていると,Qは1となります.

always begin : monostable
  #250 q = 0;
end

always @retrig begin
  disable monostable;
  q = 1;
end


(個人的まとめ)
diable/continue文は,シミュレーションモデルで使うと効果的かもしれない.ハードウェア記述で使うのはナンセンスだろう.(合成できるかどうかも怪しいか. パラメータを使ってコンパイル時にのみインスタンスを複数生成することなんかには使えそう.)

LRM読解(Chap.10-3)

2008/11/05 Verilog::文法import

10.3 Functions と function呼び出し ~ Functions and function calling functionの目的は,式中で使用するための値を返すことです.この節では,functionの定義の仕方と使い方について解説します.


10.3.1 Function宣言

syntax

function_declaration ::= (From Annex A - A.2.6)
    function [ automatic ] [ signed ] [ range_or_type ]
      function_identifier ;
      function_item_declaration { function_item_declaration }
      function_statement
    endfunction
  |
    function [ automatic ] [ signed ] [ range_or_type ]
      function_identifier ( function_port_list ) ;
      block_item_declaration { block_item_declaration }
      function_statement
    endfunction

function_item_declaration ::=
    block_item_declaration
  | tf_input_declaration ;

function_port_list ::=
  { attribute_instance } tf_input_declaration
  { , { attribute_instance }tf_input_declaration }

tf_input_declaration ::=
    input [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | input [ task_port_type ] list_of_port_identifiers

range_or_type ::=
  range | integer | real | realtime | time

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 }

function定義は,'function'キーワードで始まり,オプショナルで'automatic'が続き,符号('signed')指定,rangeや関数の戻り値の型,function名と続いてから,セミコロン,または親で閉じたfunction port listにセミコロンとなり,'endfunction'で終わります.

'range_or_type shall'の使用はオプションです.'range'や'type'なしで定義されたfunctionは,戻り値はデフォルトで1bit reg型になります.もし使われたならば,'range_or_type'は,real型,integer型,time型,realtime型,[n:m] bit幅指定の値となるfunctionの戻り値を与えます.


A function shall have at least one input declared. functionは,たった一つの入力宣言を持ちます.keyworf 'automatic'は,各再帰呼び出しのために動的に確保される再帰可能なfunctionを宣言します.

  • automatic functionのitemは,階層参照('hierarchical references')によるアクセスができません.
  • automatic functionは,階層名('hierarchical name')を使うことで,起動することができます.

function入力は,2つの方法のうちの1つで宣言されます.

1つ目の方法は,セミコロンに続いてfunction名を持ちます.セミコロンのあと,1つ以上のオプション的な入力は,後述するblock item宣言と混ざって宣言します.function item宣言のあと,ビヘイビア文とendfunction keywordがあります.

2つ目の方法は,function名のあと,開き丸括弧と1つ以上の入力宣言をコンマ区切りで持ちます.全ての入力宣言のあと,閉じ丸括弧とセミコロンがあります.セミコロンのあと,0以上のblock itemが宣言され,続けてビヘイビア文,endfunction keywordとなります.


例:
以下の例は,'range'定義を使った,getbyteという名のfunctinoを定義します.

function [7:0] getbyte;
  input [15:0] address;
  begin
  // code to extract low-order byte from addressed word
  . . .
  getbyte = result_expression;
  end
endfunction

function宣言の2つ目の様式を使って,以下のように定義することができます.

function [7:0] getbyte (input [15:0] address);
  begin
    // code to extract low-order byte from addressed word
    . . .
    getbyte = result_expression;
  end
endfunction


10.3.2 関数からの戻り値 ~ Returning a value from a function

function定義は,暗黙的にfunctionと同じ名前で,関数内部の宣言をするものとします.この変数は,デフォルトで1bit reg変数か,function宣言中のtypeで与えられる型と同様になります.function定義は,function戻り値をfunction名と同じ名前の内部変数への代入によって,関数からの戻り値を初期化します.

function宣言と同じscopeにおいて,function名と同じ名前のobjectを宣言することはイリーガルです.関数内において,function内の式で使われる,function名の暗黙的な変数があります.これはまた,function内のscopeにおいても,function名と同じ名前のobjectを宣言することはイリーガルです.

以下のLRM 10.3.1の例の行は,このコンセプトを示します.

getbyte = result_expression;


10.3.3 function呼び出し ~ Calling a function

function呼び出しは,式中のオペランドです.function呼び出しは,以下の様式です.

function_call ::= (From Annex A - A.8.2)
  hierarchical_function_identifier{ attribute_instance } ( expression { , expression } )

function呼び出しへの,引数の評価順序は,未定義です.

例)
以下の例は,LRM 10.3.1で定義されたgetbyte functionを2回呼び出した結果を結合して,wordを作ります.

  word = control ? {getbyte(msbyte), getbyte(lsbyte)}:0;


10.3.4 functionルール ~ Function rules

functionはtaskよりも多くの制約があります.以下の6つのルールが,使用法を抑制します.a) function定義は,時間制御文(time-controlled statements,'#','@',"wait")を含んではならない.b) functionはtaskをenableにしてはならない.c) function定義は,少なくとも1つの入力引数を含みます.d) function定義は,output/inoutと宣言された引数を持ちません.e) function定義は,function名と同じ名称の内部変数への代入による戻り値の代入を含みます.f) functionは,ノンブロッキング代入を持ちません.A function shall not have any non blocking assignments.


例)
この例は,integer値を返す"factorial"と呼ばれるfunctionを定義します.この"factorial" functionは,反復して呼び出され,戻り値を表示します.

module tryfact;
  // define the function
  function automatic integer factorial;
    input [31:0] operand;
    integer i;
    if (operand >= 2)
      factorial = factorial (operand - 1) * operand;
    else
      factorial = 1;
  endfunction

  // test the function
  integer result;
  integer n;

  initial begin
    for (n = 0; n <= 7; n = n+1) begin
      result = factorial(n);
      $display("%0d factorial=%0d", n, result);
    end
  end
endmodule // tryfact

The simulation results are as follows:

0 factorial=1
1 factorial=1
2 factorial=2
3 factorial=6
4 factorial=24
5 factorial=120
6 factorial=720
7 factorial=5040


10.3.5 constant functionの使い方 ~ Use of constant functions

"Constant function calls"は,"elaboration"時(LRM 12.1.3)において,複雑な値の計算の構築のサポート使われます."Constant function call"は,functionへの引数が定数式("constant expressions")である,呼び出しモジュールへのローカルな"constant function"のfunction起動です."Constant function call"は,以下の制約を満足する,通常のVerilog functionsのサブセットです.

  • 階層的な参照を含まない
  • constant functionの中で呼び出されたどんなfunctionも,current moduleへの局所的なconstant functionになります.(Any function invoked within a constant function shall be a constant function local to the current module.)
  • System functions は呼び出されないこと.
  • "constant function"の中のすべての"system tasks"が無視されるものとします。
  • "constant function"の中の"system function"は,イリーガルになります.(All system functions within a constant function shall be illegal.)
  • 呼び出す"system task"は"$display"で,"elaboration time"において呼び出されたときは無視されます.(The only system task that may be invoked is $display, and it shall be ignored when invoked at elaboration time.)
  • 関数内で使われている全てのparameter値は,"constant function"呼び出しを使う前に定義されるべき.

    i.e. "constant function"呼び出しの評価で使われるどんな"parameter"も,
    元の"constant function"呼び出し位置で,その"parameter"の使用を構成する.(適用する?)
    
  • "parameter"でもなく,"function"でもない全ての識別子は,current functionへ局所的として宣言されるべき.それら(they:functions?)が,defparam文(LRM 12.2.1)によって,直接的・間接的に影響を受ける"parameter"を使うならば,結果は未定義です.これは,errorを提供できるか,または,"constant function"が不定値を返すことができます.
  • "generate"scope内で宣言されない
  • 定数式を要求するあらゆるコンテキスト内で,"constant function"自身を使わない.(They shall not themselves use constant functions in any context requiring a constant expression.)

"constant function call"は,"elaboration"("綿密な仕上げ"の意)の時に評価されます."elaboration"実行は,simulation時やelaboration時の複数の関数呼び出し間で使われる,変数の初期値に影響を与えない.これらの場合において,その変数は,通常のsimulationのために初期化されます.

例)
This example defines a function called clogb2 that returns an integer which has the value of the ceiling of the log base 2.

module ram_model (address, write, chip_select, data);
  parameter data_width = 8;
  parameter ram_depth = 256;
  localparam adder_width = clogb2(ram_depth);   //(訳コメント)定数項に対してfunctionを使う,てことですね.. やっと意味がわかった..

  input [adder_width - 1:0] address;
  input write, chip_select;
  inout [data_width - 1:0] data;

  //define the clogb2 function
  function integer clogb2;
    input depth;
    integer i,result;
    begin
      for (i = 0; 2 ** i < depth; i = i + 1)
        result = i + 1;
      clogb2 = result;
    end
  endfunction
reg [data_width - 1:0] data_store[0:ram_depth - 1];
//the rest to the ram model

An instance of this ram_model with parameters assigned:

ram_model #(32,421) ram_a0(a_addr,a_wr,a_cs,a_data);

LRM読解(Chap.10-2)

2008/11/05 Verilog::文法import

10.2 Tasks and task enabling

taskは,taskに渡される変数の引数を定義して,結果を受ける変数定義の構文からenableにされます.

制御は,taskが完了した後で,processを有効に戻します.したがって,taskがタイミング制御を有した場合,taskをenableにした時刻と,制御が戻った時刻に差異が生じえます.taskは他のtaskをenableにすることができ,さらにそのtaskが別のtaskをenableにする数に上限は無いです.

どれだけのtaskがenableになろうとも,制御はすべてのenableにされたtaskが完了するまで返ってきません.



10.2.1 Task declarations

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"は,それらの階層的な名前を使うことで,起動されます.



10.2.2 Task enabling and argument passing

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.


10.2.3 Task memory usage and concurrent activation

タスクは,同時に1つ以上enableにされるかもしれません.automaticタスクの全ての変数は,その実施に特定の状態を保存するために,それぞれの同時発生のタスク実施で複製されるものとします.

staticタスクの全ての変数は,タスクの同時発生の起動の数にかかわらず,静的になるでしょう.なぜならば,モジュールインスタンスそれぞれで宣言している局所変数に対応するただ一つの変数があるので.しかし,モジュールインスタンスの異なるstaticタスクは,互いからの別々の格納場所があるものとします.


staticタスクで宣言された変数は,呼び出し間でそれらの値を保有するものとします.staticタスクで宣言された変数は,LRM 3.2.2で記述するように,デフォルト初期値に初期化されます.automaticタスクで宣言された変数は,変数のスコープに入ったときに,デフォルト初期値に初期化される.なぜならば,automaticタスクで宣言された変数は,task起動の終了時に,de-allocateされるので,変数はその後の場所では参照される所望の構造で使われない.*1

automatic taskのlocal variableに対してやってはいけないことを以下に示す.

  • ノンブロッキング代入文や手続き型連続代入文を使って,値の代入をしないこと.
  • 手続き型代入文や手続き型force文で参照されないこと.
  • ノンブロッキング代入文のintra代入イベント制御で参照されないこと.
  • $monitorや$dumpvarsのようなシステムタスクでトレースされないこと.

*1 : 訳がテキトウだ.auto変数は scopeを外れると揮発する,ということで把握しておくとよいだろう,

LRM読解(Chap.10-1)

2008/11/05 Verilog::文法import

TITLE: 10. Tasks and functions taskとfunctionは,記述中のあらゆる場所からの共通の手続きを実行するアビリティを提供する.ソースコードの可読性・デバッグ性を容易にするために,大きな手続きを小さな手続きに分解することも提供する(意訳).この節は,taskとfunctionの間の差異について議論し,taskとfunctionの定義の仕方と起動の仕方について記述し,それぞれの例を提供します.

10.1 taskとfunctionとの差異 ~ Distinctions between tasks and functions

以下の規則は,funtionとtaskとを区別します.

  • functionは,1シミュレーション時間ごとに実行される.taskは,時間制御文を含むことができる.
  • functionはtaskを有効にできない.taskは他のtaskおよびfunctionを有効にできる.
  • functionは,最低1つのinput型の引数を持ち,output型やinout型の引数を持たない.taskは0以上の任意の型の引数を持つことができる.
  • functionは1つの値を返す.taskは値を返せない.

functionの目的は,1つの値を返すことによって,入力の値に対する応答をすることです.taskは複数のゴールをサポートすることができ,複数の返り値を計算することができます.しかし,outputまたはinput型の引数のみが,taskの呼び出しから返り値を渡すことができます.*1 functionは,式のオペランドのように使われます.オペランドの値は,関数による返り値です.

Example
taskまたはfunctionは,16bit wordを交換することとして定義することができます.taskは交換後のwordをoutput引数で返します.switch_bytesと呼ぶtaskを有効にするためのソースコードは,下記の例のように見えます.

switch_bytes (old_word, new_word);

task:switch_bytesは,old_wordにbytesをとり,byte orderを入れ替えて,new_wordにおきます.word-switching functionは,functionの返り値として入れ替え後の値を返します.なので,function:switch_bytesの関数呼び出しは,下記の例のように見えます.

new_word = switch_bytes (old_word);

*1 : 訳注:関数のように返り値を持たない.例を参照のこと.

OK キャンセル 確認 その他