LRM読解(Chap.9-2 Behavioral/case,loop)

2008/10/04Verilog::文法import

Behavioral modeling~その2



9.5 case文 ~ Case statement

case文は,式が多くの他の式の1つとマッチするか,分岐するかどうかに関係なくテストする,複数判断命令文です.

case_statement ::= (From Annex A - A.6.7)
    case ( expression )
      case_item { case_item } endcase
  | casez ( expression )
      case_item { case_item } endcase
  | casex ( expression )
      case_item { case_item } endcase

case_item ::=
    expression { , expression } : statement_or_null
  | default [ : ] statement_or_null

function_case_statement ::=
    case ( expression )
      function_case_item { function_case_item } endcase
  | casez ( expression )
      function_case_item { function_case_item } endcase
  | casex ( expression )
      function_case_item { function_case_item } endcase

function_case_item ::=
    expression { , expression } : function_statement_or_null
  | default [ : ] function_statement_or_null

default文は,オプションです.1つのcase文で複数のdefault文を使うのは不当です.
The case expression and the case item expression can be computed at runtime; neither expression is required to be a constant expression. case式とcase item式は,実行時に計算されます.どちらの式も,定数式になるには必要ではありません.

(例)

case-item式は,与えられた順に性格に,評価・比較されます.
線形探索において,case item式のひとつが,丸括弧(parentheses)で与えられたcase式にマッチするならば,case-itemに対応する命令文が実行されます.
全ての比較が失敗し,default-itemが与えられているならば,default-itemの命令文が実行されます.
もし,default文が無くて,全ての比較が失敗したならば,どのcase-item文も実行されません.構文は別として,case文はif-else-if構造に比べて2つの重要な違いがあります.

  • if-else-if構造の状態式のほうが,case文のように1つの式をその他と比較するよりも一般的(general)です.
  • case文は,式中の'x'や'z'が存在する時に,決定的な結果を提供します.

case式の比較において,比較は,各ビットが値'0', '1', 'x', 'z'に関して厳密にマッチするときにのみ成功します.
結果として,case文中の式を与えることには,注意が必要です.
全ての式のbit長は,正確なbit-wiseマッチングができるように,等しくなるでしょう.
全てのcase-item式の長さと丸括弧のcase式は,case式とcase-item式の最長のものと等しくするものとします.


注意
'x'と'z'のデフォルトの長さは,integerのデフォルト長と同じです.

'x'と'z'の値をハンドリングするようなcase式比較を提供する理由は,そのような値を検出し,それらの(値の)存在によって発生する悲観主義(pessimism)を減少させるためのメカニズムを提供するためです.


9.5.1 "don't care"ありのcase文 ~ Case statement with don't-cares

2つの種類の異なるcase文は,case比較演算子中のdon't case状態のハンドリングを提供する.1つは,ハイインピーダンス(z)をdon't careとして扱い,他方はハイインピーダンス(z)と不定(x)とをdon't careとして扱う.
これらのcase文は,慣例的なcase文と同じように使うことができる.しかし,それら(z,zxをdon't careとして扱うcase文)はそれぞれcasezとcasexで始まる.
case式かcase itemのどんなbitの中のdon't care値(casezではz, casexではz/x)は,比較演算時にdon't care状態として扱われ,考慮されないでしょう.
case式のdon't care状態は,どんなときでも比較すべきビットを動的に制御することに使えるでしょう.
字句構文は,case文中のzをクエスチョンマーク'?'に置き換えて使うことができる.これは,case文中でdon't care bitを与えるために,便利な書式を提供します.

例1. casez文の例を以下に示す.
殿タスクを呼ぶべきかをMSBの値が選択する,命令デコーダのデモです.irのMSBが1ならば,irのほかのbitに関係なくtask instruction1が呼ばれます.

reg [7:0] ir;
casez (ir)
  8’b1???????: instruction1(ir);
  8’b01??????: instruction2(ir);
  8’b00010???: instruction3(ir);
  8’b000001??: instruction4(ir);
endcase

例2. casex文の例を以下に示す.
この例の場合,r=8'b01100110であれば,task stat2が呼ばれます.(不定値演算は不定のままになりそうだけれど.)

reg [7:0] r, mask;
mask = 8’bx0x0x0x0;
casex (r ^ mask)
  8’b001100xx: stat1;
  8’b1100xx00: stat2;
  8’b00xx0011: stat3;
  8’bxx010100: stat4;
endcase

01100110 x0x0x0x0

  • 0-1-0-=
  • 1-0-=-0
  • 0-=-0-1
  • =-1-1-0

# stat1,3がぶつかりそうな気がするのだけれど.8'x0x1x0x1 のとき,どっちにもあたるよな?


9.5.2 case文での定数式 ~ Constant expression in case statement

定数式をcase式として使えます.定数式の値は,case item式に対して比較されます.


以下の例は,3bit priority encoderのモデリングを例示します.

reg [2:0] encode ;
case (1)
  encode[2] : $display(“Select Line 2”) ;
  encode[1] : $display(“Select Line 1”) ;
  encode[0] : $display(“Select Line 0”) ;
  default $display(“Error: One of the bits expected ON”);
endcase

Note注意
case式は定数式(1)です.case itemは,式(bit-select)で,定数式に対して一致が比較されます.


9.6 ループ構文 ~ Looping statements

ループ文として4種類あります(下表に示す).これらの命令文は,0,1,それ以上の命令の実行を制御する手段をを提供する.

forever命令文を継続的に実行する.
repeat固定回数だけ命令文を実行する.もし,式が不定かハイインピーダンスと評価されたなら,ゼロとして扱われ,命令文は実行されない.
while式がfalseになるまで,命令文を実行する.もし式がfalseで始まるならば,命令文はまったく実行されません.
for{以下のように3段階の手順で,関連する命令の実行を制御します.

a) 一般的には,ループの実行回数を制御する変数の初期化に使われる代入を実行します.b) 式評価し,結果がゼロであれば forループを終了し,ゼロでなければ関係する命令を実行してstep cへ進む.もし式が不定またはハイインピーダンスと評価されれば,ゼロとして扱う(ループを抜ける).c) 通常,ループ制御変数の値を更新するための代入に用いる.その後,step bへ戻る.}|

function_loop_statement ::= (From Annex A - A.6.8)
    forever function_statement
  | repeat ( expression ) function_statement
  | while ( expression ) function_statement
  | for ( variable_assignment ; expression ; variable_assignment ) function_statement

loop_statement ::=
    forever statement
  | repeat ( expression ) statement
  | while ( expression ) statement
  | for ( variable_assignment ; expression ; variable_assignment ) statement

The rest of this clause presents examples for three of the looping statements.この節の残りでは,ループ文の3つの例を挙げます.The forever loop should be used /in conjunction with/ the timing controls or the disable statement, therefore, this example is presented in 9.7.2.

foreverループは,タイミング制御かdisable命令と同時に使われます.それ故,その例は9.7.2で紹介します.

例1
: Repeat文: 以下repeatループの例は,addとshift演算が乗算器を実装する例です.

parameter size = 8, longsize = 16;
reg [size:1] opa, opb;
reg [longsize:1] result;

begin : mult
  reg [longsize:1] shift_opa, shift_opb;
  shift_opa = opa;
  shift_opb = opb;
  result = 0;

  repeat (size) begin
    if (shift_opb[1])
      result = result + shift_opa;
    shift_opa = shift_opa << 1;
    shift_opb = shift_opb >> 1;
  end
end

例2
While文: 以下の例は,rega内の論理1の値を数えます.

begin : count1s
  reg [7:0] tempreg;
  count = 0;
  tempreg = rega;
  while (tempreg) begin
    if (tempreg[0])
      count = count + 1;
    tempreg = tempreg >> 1;
  end
end

例3
For 文: for命令は,whileループを基にした下記の擬似命令のような同じ結果を成し遂げる.

begin
  initial_assignment;
  while (condition) begin
    statement
    step_assignment;
  end
end

forループは,以下に示すような擬似命令で,たった2行を使うだけでこのロジックを実装します.

for (initial_assignment; condition; step_assignment)
  statement

LRM読解(Chap.9-1 Behavioral modeling)

2008/10/04Verilog::文法import

Behavioral modeling~その1

今までのところ導入されている言語構造は,ハードウェアが比較的詳細なレベルで説明されるのを許容します.ロジックゲートと常時代入による回路モデリングは,モデル化される回路の論理構造をとてもきっちりと反映します.しかし,この構文は,システムの複雑なハイレベルの様相/方向について説明するのに必要な抽象化能力を提供しません.

この章で記される手続き型構文は,マイクロプロセッサを記述したり,複雑なタイミングチェックを実装するような問題に取り組むのに,とても適している.

この章は,Verilog HDLで,ビヘイビア文のいくらかの種類の文脈を提供するビヘイビアモデルの概要から始まります.



9.1 Behavioral model overview

Verilogビヘイビアモデルは,シミュレーションを制御したり,前述したデータ型の変数の値を操作する,手続き文を含みます.この命令文は,手続きに含まれています.各手続きは,それに関する能動的な(activity)フローを持ちます.

その活動(activity)は,制御構文 initial と always で始まります.それぞれのinitial文やalways文は,分割された能動的な(activity)フローを始めます.全ての能動的な(activity)フローは,ハードウェアで固有の並行性をモデル化することにおいて同時発生的です.
この構造は LRM9.9で正式に記述されます.以下の例は,完全なVerilgoビヘイビアモデルをあらわします.

module behave;
reg [1:0] a, b;
  initial begin
    a = ’b1;
    b = ’b0;
  end

  always begin
    #50 a = ~a;
  end
  always begin
    #100 b = ~b;
  end
endmodule

このモデルのシミュレーションにおいて,initial文とalways文によって記述された全てのフローは,シミュレーション時刻0から開始されます.
initial文は一度だけ実行し,always文は繰り返し実行します.

このモデルでは,シミュレーション時刻0において,reg変数 a,b は,それぞれ1,0に初期化されます.
initial文は,それで完了し,このシミュレーション実行中は再び実行しません.このinitial文は,begin - end block命令文(シーケンシャルブロック(sequential block)とも呼ばれます)を含みます.
begin-end block内では,最初にaが初期化され,続いてbが初期化されます.

always文も時刻0に開始されますが,変数の値は,遅延制御で与えられた時間('#'で示される)が経過するまで変化しません.
したがって,reg aは50単位時間後に反転し,reg bは100単位時間後に反転する.always文は繰り返すので,このモデルは2つの矩形波を提供するでしょう.
reg aは100単位時間周期でトグルし,reg bは200単位時間周期でトグルします.2つのalways文は,全体のシミュレーション走行の間中,並行に続きます.



9.2 Procedural assignments

As described in Clause 6, 6節で述べたように,手続き型代入は,以下のデータ型を更新するのに用いられる.

  • reg
  • integer
  • time
  • real
  • realtime
  • memory

手続き型代入と常時代入の間には,以下のようにとても大きな違いがあります.

常時代入は,netを駆動し,評価され,入力オペランドの値が変わらないときでも更新されます.
手続き型代入は,それら(代入文?)を取り囲む手続き上の流れの制御下で,変数の値を更新する.

手続き型代入の右辺は,値として評価されるどのような式でもなれる.左辺は,右辺からの代入を受け取る変数となるでしょう.手続き型代入の左辺は,以下の様式をとることができます.

|*RHS-type |* LHS constraint? |
|reg, integer, real, realtime, or time data type | これらのデータ型の1つの名前参照への代入 |
|Bit-select of a reg, integer, or time data type | その他の触らないビットを残して,1ビットへの代入	|
|Part-select of a reg, integer, or time data type| 残りの触らないビットを残して,1異常の連続したビットの部分選択 |
|Memory word | 	memoryの1ワード |
|Concatenation of any of the above | 前の4つのフォームの,いずれかの連結を指定できます.(左辺は)連結した一部なので,ので,右辺の式の結果を分割し,分割した部分を代入します.|

注意:
右辺のビット長が左辺のビット長より短い場合,右辺が符号あり(LRM 4.5参照)であれば,左辺の大きさは符号拡張されるでしょう.

Verilog HDLは,以下の2種類の手続き型代入文を有します.

  • ブロッキング代入文
  • ノンブロッキング代入文

ブロッキング・ノンブロッキング代入文は,シーケンシャルブロックにおいて異なる手続き上のフローを与えます.


9.2.1 Blocking procedural assignments

ブロッキング代入文は,シーケンシャルブロック(9.8.1参照)中の後続の命令文を実行する前に,処理されます.
ブロッキング代入文は,パラレルブロック(9.8.2参照)中では,後続の命令文を実行するのは妨げない.

blocking_assignment ::= (From Annex A - A.6.2)
  variable_lvalue = [ delay_or_event_control ] expression

delay_control ::= (From Annex A - A.6.5)
  # delay_value
  | # ( mintypmax_expression )

delay_or_event_control ::=
  delay_control
  | event_control
  | repeat ( expression ) event_control

event_control ::=
  @ event_identifier
  | @ ( event_expression )
  | @*
  | @ (*)

event_expression ::=
  expression
  | hierarchical_identifier
  | posedge expression
  | negedge expression
  | event_expression or event_expression
  | event_expression , event_expression

variable_lvalue ::= (From Annex A - A.8.5)
  hierarchical_variable_identifier
  | hierarchical_variable_identifier [ expression ] { [ expression ] }
  | hierarchical_variable_identifier [ expression ] { [ expression ] } [ range_expression ]
  | hierarchical_variable_identifier [ range_expression ]
  | variable_concatenation

この文法について;

reg_lvalue手続き型代入文に使えるデータ型
'='代入演算子
delay_or_event_control補助的な,内部代入(intra-assignment)タイミング制御
expression左辺に代入される右辺の値

制御(delay_or_event_control)は,delay_control(例えば "#6") またはevent_control(例えば "@(posedge clk)")をとり得ます.
もし,reg_lvalueが評価を要するならば,内部代入(intra-assignment)タイミング制御に与えられた時間に評価されます.
ブロッキング手続き型代入で用いられる'='演算子は,手続き型常時代入と常時代入にも使われます.


9.2.2 The non blocking procedural assignment

ノンブロッキング手続き代入は,手続き的なフローを妨げることなく,代入処理のスケジューリングを許容する.
ノンブロッキング手続き代入文は,同じ時間ステップに代入されるあらゆる変数が,互いに独立に,または順序に関係ないときに用いる.

nonblocking_assignment ::= (From Annex A - A.6.2)
  variable_lvalue <= [ delay_or_event_control ] expression

delay_control ::= (From Annex A - A.6.5)
    # delay_value
  | # ( mintypmax_expression )

delay_or_event_control ::=
    delay_control
  | event_control
  | repeat ( expression ) event_control

event_control ::=
    @ event_identifier
  | @ ( event_expression )
  | @*
  | @ (*)

event_expression ::=
    expression
  | hierarchical_identifier
  | posedge expression
  | negedge expression
  | event_expression or event_expression
  | event_expression , event_expression

variable_lvalue ::= (From Annex A - A.8.5)
    hierarchical_variable_identifier
  | hierarchical_variable_identifier [ expression ] { [ expression ] }
  | hierarchical_variable_identifier [ expression ] { [ expression ] } [ range_expression ]
  | hierarchical_variable_identifier [ range_expression ]
  | variable_concatenation

In this syntax

reg_lvalue手続き型代入文に使えるデータ型
'<='ノンブロッキング代入演算子
delay_or_event_control補助的な,内部代入(intra-assignment)タイミング制御
expression左辺に代入される右辺の値

もし,reg_lvalue が評価を要するならば,右辺の式が評価されるのと同じ時刻に評価されるでしょう.
もし,タイミング制御が支持されていなければ,reg_lvalueと右辺の式の評価順序は未定義です.

ノンブロッキング代入演算子は,関係演算子"小なりまたは等しい(<=)"と同じです.解釈は "<="が現れる文脈から決められるものとします.
式中に "<="が使われているとき,関係演算子と解釈され,ノンブロッキング手続き代入で使われているときは,代入演算子と解釈されるでしょう.

ノンブロッキング手続き代入は,5節で議論したように2段階で評価されるでしょう.
2つのステップについては,以下の例中に示します.

(例を省略します)



9.3 Procedural continuous assignments

assign文 や force文を使った 手続き型常時代入は,変数かネットを連続的に駆動する式を許容する手続き命令文です.

net_assignment ::= (From Annex A - A.6.1)
  net_lvalue = expression

procedural_continuous_assignments ::= (From Annex A - A.6.2)
    assign variable_assignment
  | deassign variable_lvalue
  | force variable_assignment
  | force net_assignment
  | release variable_lvalue
  | release net_lvalue

variable_assignment ::= (From Annex A - A.6.3)
  variable_lvalue = expression

net_lvalue ::= (From Annex A - A.8.5)
    hierarchical_net_identifier
  | hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] }
  | hierarchical_net_identifier [ constant_expression ] { [ constant_expression ] } [ constant_range_expression ]
  | hierarchical_net_identifier [ constant_range_expression ]
  | net_concatenation

variable_lvalue ::=
    hierarchical_variable_identifier
  | hierarchical_variable_identifier [ expression ] { [ expression ] }
  | hierarchical_variable_identifier [ expression ] { [ expression ] } [ range_expression ]
  | hierarchical_variable_identifier [ range_expression ]
  | variable_concatenation

assign文の式の左辺は,変数参照か,変数の連結になるでしょう.メモリの1ワード(配列参照) や ビット選択 や 変数の部分選択にはならないでしょう.

対照的に,force文の代入式の左辺は,変数参照かネット参照になりえます.前述の連結にもできます.
ヴェクタ変数の,ビットセレクトや部分選択は許可されません.


9.3.1 The assign and deassign procedural statements

assign 手続き型常時代入分は,全ての変数への手続き型代入を上書きします.deassign手続き文は,変数への手続き型常時代入を終わるでしょう.変数の値は,手続き型代入または手続き型常時代入によってregに新しい値が代入されるまで同じ値を残すでしょう.

assignとdeassign手続き文は,例えば,エッジトリガ型D-FFの非同期クリア・プリセットのモデリングを許容します.というのも,クリアまたはプリセットがアクティブになったときに,クロックを抑制します.
キーワード"assign"が,すでに手続き型常時代入されている変数に適用されるならば,この新しい手続き型常時代入は,新しい手続き型常時代入を作る前に,変数のdeassignを行うでしょう.

以下の例は,プリセット・クリアつきD-FFのビヘイビア記述中での,assign文とdeassign文の使い方を示します.

module dff (q, d, clear, preset, clock);
output q;
input d, clear, preset, clock;
reg q;
  always @(clear or preset)
    if (!clear)
      assign q = 0;
    else if (!preset)
      assign q = 1;
    else
      deassign q;

  always @(posedge clock)
    q = d;
endmodule

clear または preset がlowならば,出力qは固有の固定値を維持し,クロックの立ち上がりエッジは qに影響を与えない.
clear と preset のどちらも highのときには,qはdeassignされます.


9.3.2 The force and release procedural statements

他の手続き型常時代入の様式は,force/release手続き命令文で提供されます.
これらの命令文は,assign-deassignの組み合わせと同様の効果を持ちますが,force文はネット型に対しても変数と同様に適用することができます.
代入式の左辺は,以下とすることができる.

  • 変数
  • ネット型
  • ネット型のヴェクタのビット選択(選択域は固定)
  • ネット型のヴェクタの部分選択(選択域は固定)
  • 連結

以下はできない.

  • メモリの1ワード(配列参照)
  • 変数型のヴェクタのビット選択・部分選択

変数に対するforce文は,release手続き文が実行されるまでは,変数で行われる手続き代入または手続き常時代入を上書きするでしょう.release手続き命令が実行された後,その変数は直ちに値を変えないでしょう.(ネット型であるかのように,手続き型常時代入として代入される)force文で与えられた値は,その変数で手続き型常時代入が有効にならないケースを除いて,次の手続き型代入が行われるまでは,変数として扱われるでしょう.
net型でのforce手続き命令文は,release手続き型命令文が実行されるまでは,すべてのゲート出力・module出力・常時代入の駆動を上書き*1します.
アクティブな手続き型常時接続を持つ変数を開放することは,その代入を再接続することになるでしょう.

module test;
  reg a, b, c, d;
  wire e;
  and and1 (e, a, b, c);
  initial begin
    $monitor("%d d=%b,e=%b", $stime, d, e);
    assign d = a & b & c;
    a = 1;
    b = 0;
    c = 1;

    #10;
    force d = (a | b | c);
    force e = (a | b | c);
    #10 $stop;
    release d;
    release e;

    #10 $finish;
  end
endmodule

 Results:
   0 d=0,e=0
   10 d=1,e=1
   20 d=0,e=0

この例において,ANDゲートインスタンス 'and1'は,foce手続き文によってORゲートに修正されています.その手続き文は,強制的にその出力値を論理和入力の値にして,論理和のassign手続き命令文のように,論理積のassign手続き命令文を書き換えます.

手続き型常時接続代入またはforce文の右辺は,式になりえます.これは常時代入のように取り扱われます.というのは,何か右辺の値が変わるならば,assignまたはforceが有効な間,代入は再評価されるものとします.例えば,

force a = b + f(c) ;

このように,bまたはcが変化するならば,aは新しい式'b+f(c)'の値に強制されるでしょう.



*1 : 元の信号接続を断って,force接続のみ有効にします.

9.4 条件文 ~ Conditional statement

条件文(もしくはif-else文)は,命令文を実行するかどうかを判断するようなことに用います.一般的なSyntaxをいかに示します.

conditional_statement ::= (From Annex A - A.6.6)
  if ( expression )
    statement_or_null [ else statement_or_null ]
  | if_else_if_statement

  function_conditional_statement ::= (From Annex A - A.6.6)
    if ( expression ) function_statement_or_null
    [ else function_statement_or_null ]
  | function_if_else_if_statement

式の評価が真(true)(これは,非ゼロの値を持つことを意味します)であれば,最初の命令文が実行されます.
式の評価が偽(faluse)(これは,ゼロもしくは'x','z'を持つことを意味します),最初の命令文は実行されません.もし,else文があり,式がfalseであれば,else文が実行されます.

if式の数値がゼロになるかどうかをテストするので,ある一定のショートカットが可能です(短縮記述できる,の意).例えば,以下の2つの式は同じ論理です.

if (expression)
if (expression != 0)

if-elseのelse部分はオプションなので,elseが入れ子にされたifシーケンスから省略されるとき,混乱するでしょう.これは,常に直前のelse文を欠いたif文と結びつくelseによって解決されます.
以下の例において,else文はインデントで示したように,内側のifといきます.

if (index > 0)
  if (rega > regb)
    result = rega;
  else // else applies to preceding if
    result = regb;

もし,前述の結びつきが期待するものでなければ,以下に示すように,期待する結びつきを強制するために,begin-endブロック構文を使うべきです.

if (index > 0) begin
  if (rega > regb)
    result = rega;
end
else result = regb;

9.4.1 If-else-if construct

if_else_if_statement ::= (From Annex A - A.6.6)
  if ( expression ) statement_or_null
  { else if ( expression ) statement_or_null }
  [ else statement_or_null ]

function_if_else_if_statement ::= (From Annex A - A.6.6)
  if ( expression ) function_statement_or_null
  { else if ( expression ) function_statement_or_null }
  [ else function_statement_or_null ]

このif-else-if構造として知られているif文のシーケンスは,複数の判断を記述するもっとも一般的な方法です.式は順番に評価され,いずれかの式が真であれば,それに対応した命令文が実行されます.そして,その後に全体のチェーンを終了します.
各命令文は,1行命令かブロック文です.

if-else-if構造の最後のelse部分は,他の状態を満たすことのないnone-of-the-above または デフォルトの場合をハンドルします.
時々,デフォルトとして明示的なアクションはありません.
そのような場合,引きずられたelse文が省略されたか,想定外の状態をキャッチするエラーチェック用に使われます.

LRM読解(Chap.6 代入~Assignments)

2008/09/23Verilog::文法import

6. 代入~Assignments

代入は,netや変数に値を設定するための基本的なメカニズムです.2つの基本的な代入の書式があります.

  • netへの値代入である,常時代入(continuous assignment)
  • 変数への値代入である,手続型代入(procedural assignment)

追加の書式が2つあります.LRM9.3で記す手続型常時代入(procedural continuous assignments)と呼ばれる, assign / deassign と force / release です.代入は,等号('=')またはノンブロッキング手続型代入('<=')で分けられた,左辺(LHS)と右辺(RHS)の2つの部分で構成されます.右辺は,評価された結果,値となるどのような式にでもできます.
左辺は,右辺の値を代入するための変数を示します.
左辺は,代入が常時代入か手続型代入かに基づいて,下表に示す書式のうち1つをとることができます.

Statement typeLeft-hand side (LHS)
Continuous assignmentネット(ヴェクタorスカラ) Net (vector or scalar)
ネットのヴェクタのビットセレクト(ビット固定の場合のみ) Constant bit select of a vector net
ネットのヴェクタの部分選択(選択位置固定のみ) Constant part select of a vector net
ネットのヴェクタの要素指定(index固定) Constant indexed part select of a vector net
上記の4つのLHSのいずれかの連結 Concatenation of any of the above four LHS
Procedural assignment変数(ヴェクタorスカラ) Variables (vector or scalar)
reg/integer/time型変数のビットセレクト(ビット固定の場合) Bit-select of a vector reg, integer, or time variable
reg/integer/time型変数のヴェクタの部分選択(選択位置固定) Constant part select of a vector reg, integer, or time variable
メモリワード Memory word
reg/integer/time型変数のヴェクタの要素指定(index固定) Indexed part select of a vector reg, integer, or time variable
bit選択reg/部分選択reg/regの連結 Concatenation of regs; bit or part selects of regs

6.1 常時代入 ~ Continuous assignments

常時代入は,ヴェクタとスカラ両方のネット上を駆動します.この代入は,右辺の値が変化したときに生じます.
常時代入は,ゲートの内部接続を与えることなく,組み合わせロジックをモデル化する方法を提供します.代わりに、モデルはネットを駆動する論理式を指定します.

Syntax:

net_declaration ::= (From Annex A - A.2.1.3)
  net_type [ signed ] [ delay3 ] list_of_net_identifiers ;
  | net_type [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
  | net_type [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
  | net_type [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;
  | trireg [ charge_strength ] [ signed ] [ delay3 ] list_of_net_identifiers ;
  | trireg [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
  | trireg [ charge_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
  | trireg [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;

list_of_net_decl_assignments ::= (From Annex A - A.2.3)
  net_decl_assignment { , net_decl_assignment }

net_decl_assignment ::= (From Annex A - A.2.4)
  net_identifier = expression

continuous_assign ::= (From Annex A - A.6.1)
  assign [ drive_strength ] [ delay3 ] list_of_net_assignments ;

list_of_net_assignments ::=
  net_assignment { , net_assignment }

net_assignment ::=
  net_lvalue = expression

6.1.1 ネット宣言代入 The net declaration assignment

最初から二つのネット宣言の選択肢は LRM3.2で議論しました.
ネット宣言代入の三つ目の選択肢は,ネット宣言と同じ文中での常時代入を許可します.

例:下記は,常時代入のネット宣言記述の例です.

  wire (strong1, pull0) mynet = enable ;

注意:
ネットは一度だけ宣言できるので,唯一のネット宣言代入は,特定のネットで作られます.これは常時代入文と酷く違います.1つのネットは,常時代入記述の複数代入を可能とします.


6.1.2 The continuous assignment statement

常時代入文は,ネットデータ型の常時代入を置くものとします.
ネットは,明示的に宣言されるか,LRM 3.5で定義した暗黙的な宣言ルールにしたがって,暗黙的な宣言を継承するでしょう.
ネットにおける代入は,常時でかつ自動的です.これは,右辺式のオペランドの値が変わることを意味します.右辺全体が評価されて,もし新しい値が前の値と異なるならば,新しい値が左辺に代入されます.


6.1.3 遅延 ~ Delays

常時代入に与えられる遅延は,右辺のオペランド値の変化と,左辺への代入との間の時間間隔を指します.
左辺がスカラなネットであれば,ゲート遅延と同様に扱われるものとします.出力の立ち上がり・立下り・ハイインピへの変化時間を異なる遅延で与えることができます.(LRM 7参照)
もし左辺がヴェクタのネット型であれば,最大3つの遅延が適用できます.
以下のルールにより,どの遅延が代入を制御するのかを決定します.

  • 右辺が非ゼロからゼロへ遷移するならば,立下り遅延が使われます.
  • 右辺が'z'へ遷移するならば,ターンオフ遅延が使われます.
  • そのほかの場合,立ち上がり遅延が使われます.

ネット宣言部で,常時代入中に遅延を与えることは,ネット遅延を与えることとは異なるように扱われ,ネットへの常時代入が作られます.

以下の例のように,ネット宣言部での,遅延時間がネットへ適用されることができる.

wire #10 wireA;

このネット遅延と呼ばれる記述は,他の文からwireAに適用される値の変化が,10時間単位だけ遅延することを意味します.

宣言時に常時代入があるとき,その遅延は常時代入の一部であり,ネット遅延ではありません.
したがって,ネット上の他のドライバの遅延を加算しません.
なお,その代入がヴェクタネット型であれば,立ち上がりと立下り遅延は,宣言時に代入が含まれているならば,個々のビットには適用されません.
前の変化が左辺に伝播する時間がある前に,右辺のオペランドが変化するような場合,以下のステップがとられます.

  1. 右辺式の値が評価されます
  2. 右辺の値が,左辺への伝播が予定されていた値と異なる場合,現時刻のスケジューリングからはずします.
  3. 新しい右辺の値が,左辺の値と同じ場合,イベントはスケジューリングされません.
  4. 新しい右辺の値が,現在の左辺の値と異なる場合,遅延は,左辺の現在の値と右辺の新しく計算された値と命令文で示された値を用いて,通常の方法で計算されます.新しい伝播イベントは,未来の遅延時間単位で起きるようにスケジューリングされます.

6.1.4 強度 ~ Strength

常時代入の駆動強度(driving strength)は,ユーザにより指定されます.
以下の型のスカラネット方への代入でのみ適用されます.

wire  tri  trireg  wand  triand  tri0  wor  trior  tri1

常時代入の駆動強度は,キーワード'assign'を用いることで,ネット宣言中または単独の代入で指定できます.
強度仕様が与えられるならば,ネット型もしくはassign文の後のすぐ近くで遅延指定よりも前に無ければならない.

駆動強度仕様は,ネットに1が代入されるときに適用される1つの強さの値と,0が代入されるときに適用される2つ目の強さの値とからなる.以下のキーワードは,1の代入のための強さの値を示す.

supply1  strong1  pull1  weak1  highz1

以下のキーワードは,0の代入のための強さの値を示す.

supply0  strong0  pull0  weak0  highz0

2つの強さ指定の順序は,調停される.以下の2つのルールが駆動強度仕様の使い方を制限する.

  • 強さ定義((highz1, highz0) と (highz0, highz1))は,異常な構成(illegal constructs)として扱う.
  • 駆動強度指定がない場合は,(strong1, strong0)をデフォルトとして扱う.


6.2 手続型代入 ~ Procedural assignments

手続型代入の主な議論は LRM9.2で行う.しかし,本節では,基本思想の記述は,常時代入と手続型代入との間の違いを明らかにします.
LRM 6.1で述べらているように,常時代入は,ゲートがネットを駆動する方法と似たようなマナーでネットを駆動します.右辺式は,ネットを常時駆動するような組み合わせ回路のようなものが考えられるでしょう.
対照的に,手続型代入は変数に値を代入します.代入は期間を持ちません.変わりに,変数は,次の手続型代入まで,代入の値を保持します.

手続代入は,always文, initial文, task文, function文のような手続き中にあり,トリガ代入と考えられます.

シミュレーション中,実行の流れが手順の中で代入に達すると,トリガは現れます.条件文は,代入に達するのを制御できます.
イベント制御,遅延制御,if文,case文,ループ文は,全て代入文が評価されるかどうかの制御に使えます.LRM 9で詳細を与え,例示します.


6.2.1 変数宣言代入 ~ Variable declaration assignment

変数宣言代入は,値を変数に代入するような,手続型代入の特殊なケースです.変数宣言と同じ命令文中に,変数に初期値をおくことができます.

  • 代入は,定数式とします.
  • 代入に期間はありませんが,代わりに変数は次の代入まで値を保持します.
  • アレイ型への変数宣言代入は許可されません.
  • 変数宣言代入は,モジュールレベルにおいてのみ許されます.

例文

Example 1 Declare a 4 bit reg and assign it the value 4.
  reg[3:0] a = 4'h4;
  This is equivalent to writing:
  reg[3:0] a;
  initial a = 4'h4;

Example 2 The following example is not legal.
  reg [3:0] array [3:0] = 0;

Example 3 Declare two integers, the first is assigned the value of 0.
  integer i = 0, j;

Example 4 Declare two real variables, assigned to the values 2.5 and 300,000.
  real r1 = 2.5, n300k = 3E6;

Example 5 Declare a time variable and realtime variable with initial values.
  time t1 = 25;
  realtime rt1 = 2.5;

注意:
同じ変数が,initialブロックと変数宣言代入の両方で異なる値を代入されるとき,評価順序は未定義です.
# initial blockのしょっぱなと,変数宣言のしょっぱなは,時間的には同じで,かつシミュレーション時間のゼロからだけど,仕様上は優先順位を設けない,ということですね.(はまったきがするなぁ)
# initial blockの先頭で '#1'とかしておくと良いかも,かも,かも... (その前にmodule resetかけたほうがよいよぃょぃ...


6.2.2 Variable declaration syntax

syntax

integer_declaration ::= (From Annex A - A.2.1.3)
  integer list_of_variable_identifiers ;

real_declaration ::=
  real list_of_real_identifiers ;

realtime_declaration ::=
  realtime list_of_real_identifiers ;

reg_declaration ::=
  reg [ signed ] [ range ] list_of_variable_identifiers ;

time_declaration ::=
  time list_of_variable_identifiers ;

real_type ::= (From Annex A - A.2.2.1)
  real_identifier [ = constant_expression ]
  | real_identifier dimension { dimension }

variable_type ::=
  variable_identifier [ = constant_expression ]
  | variable_identifier dimension { dimension }

list_of_real_identifiers ::= (From Annex A - A.2.3)
  real_type { , real_type }

list_of_variable_identifiers ::=
  variable_type { , variable_type }

LRM読解(Chap.5 Scheduling semantics)

2008/09/16Verilog::文法import

LRM 5. スケジューリング意味論?(Scheduling semantics)

5.1 モデルの実行(Execution of a model)

本章では,エレメント間の振る舞いを示す.特にイベントスケジューリングと実行について.
Verilog-HDLの処理構造は,ブロックやプロセスの並列実行にあります.
そのため,処理順序の決定方法等をユーザに明確に示す必要があります.が,simulator依存です,といっているみたい...?(勝手な意訳)




5.2 イベントシミュレーション(Event simulation)

1つのデザインは,接続された実行またはプロセスのスレッドから成る.

プロセスは,以下の特徴を持つobjectである.

  • 評価されることができる
  • ステート(状態)を持てる
  • 入力の変化に対して出力を出すことができる

また,プロセスは以下を含む:

  • primitives
  • modules
  • initial procedural blocks
  • always procedural blocks
  • continuous assignments
  • asynchronous tasks
  • procedural assignment statements

命名されたイベントと同様にシミュレートされる回路の NETや変数の値の変化がアップデートイベントであると考えられます。
(自力:シミュレーション対象の回路内の,全てのnetや変数の値の変化は,update eventを考慮している.(excite翻訳のほうが正しそうだな..)プロセスは、イベントをアップデートするために敏感(sensitive)です。
アップデートイベントが実行されるとき、そのイベントに敏感なすべてのプロセスが任意のオーダーで評価されます。
また、プロセスの評価は,evaluation eventとして知られているイベントです。

イベントに加えて、シミュレータの別のキーは時間です。
"simulation time"は、それがシミュレートされる回路にかかる実際の時間をモデル化するためにシミュレータによって保持された時間の値を参照するために使用されます。

この章では,"time"は,シミュレーション時間と共に互換性を持って使用されます。(おなじっちゅうこっちゃ?)


イベントは,異なる時間に起こりえます.
イベントの動向(track)をおさえて、それらが正しいオーダーで処理されるのを確実にするために、イベントは,要求された"simulation time"まで,イベント待ち行列に保たれます。(意訳)
イベントを待ち行列(queue)に置くのは,"scheduling an event"と呼ばれます。

In order to keep track of the events and to make sure they are processed in the correct order,
the events are kept on an event queue, ordered by simulation time.



5.3 階層状のイベント待ち行列(The stratified event queue)

表形式で順序,トリガを引くやつ,負荷情報を記載すると良い.Verilogイベントキューは,論理的に5つの異なる領域に分割されています.イベントは5つのどの領域にも追加できますが,削除はアクティブな領域からのみ可能です.

event name remark
active現在の"simulation time"で起きた,順不同に処理ができる*1イベント
inactive現在の"simulation time"で起きたが,activeイベントのあとに処理ができるイベント
non blocking assign update以前の"simulation time"で評価されたが,現在の"simulation time"でassignedされるイベント.active/inactive処理は先.
monitor上の3つのイベントが終わってから処理されるイベント
future未来の"simulation time"で起こるイベント."future inactive events"と"future non blocking assignment update events"に分けられる.

※処理優先度は上位から.

すべてのアクティブなイベント処理は,"simulation cycle"と呼ばれます.
即時処理のためのあらゆるアクティブなイベントを選ぶ自由度は,Verilog HDLの「非-決定論」の不可欠の源です。
明白なゼロ遅延(#0記述)が、processの中断と,現在時刻のinactive eventとして加えられることを要求します.
そのため,processは,現在の時刻の次のシミュレーションサイクルに再開されます.

ノンブロッキング代入(9.2.2参照)は,現在または後のシミュレーション時刻にスケジューリングされた,ノンブロッキング代入更新イベントを作り出します.
$monitorと$strobeのシステムタスク(17.1参照)は,各々の引数のためにモニタイベントを作成します.
これらのイベントはあらゆる連続した時間間隔で,絶え間なく再始動(be re-enabled)にされます.
モニターイベントは,いかなる他のイベントも引き起こすことができないので,独立です.
tf_synchronize() (25.58参照) や vpi_register_cb(cb_readwrite) (27.33参照)のようなPLI関数によってスケジューリングされたcall back proceduresは,inactiveイベントとして扱われるものとします.




5.4 Verilogシミュレーションのリファレンスモデル(The Verilog simulation reference model)

前節までのまとめで,事例を示す.簡単なイベント処理フローを示し,その説明を補足している.シミュレータを作る方,HDL記述をどのように解釈されるのかを理解するのに有用であろう.

5.4.1 Determinism

begin-end blockを1単位として,イベントqueで処理の停止/再開を行う.ノンブロッキング代入で,代入先が同じ変数の場合,記述順に"ノンブロッキング代入イベント"が生成され,queueに入る.したがって,イベント処理時には,一瞬前の値が入るが,最終的には最後に記述している値を保持することになる.


5.4.2 Nondeterminism

非決定の一例は, active eventがqueueから取り出され,あらゆるオーダで実行されることにより発生する.
ビヘイビアブロック内の,時間制御制約の無い命令文が,1つのイベントで実行してはならないときに生じる(意訳)
時間制御(命令)文は,#式・@式構文である(9.7参照)
ビヘイビア文を評価しいている全ての時には,シミュレータは実行を停止し,イベントキュー上のペンディングしているactive eventのような完了したイベントをおき続けるべきである.(意訳:キューの話が意味を取り違えているかもしれない.)
この効果は,プロセス実行のインタリーブを可能にする.インタリーブ実行の順序は,非決定論者的で,ユーザ制御下にはない.




5.5 レースコンディション(Race conditions)

式評価や,ネット更新イベントの実行は,混ぜられるので,レースコンディションが起こりえる.

assign p = q;
initial begin
     q = 1;
  #1 q = 0;
     $display(p);
end

シミュレータは,1か0を表示することは正しい.
qに対する0代入は,pに対する更新イベントを有効にする.
シミュレータは,連続して,$displayタスクを実行するか,$displayタスクが後に続いたpのための更新を実行するでしょう.




5.6 Scheduling implication of assignments

代入は,以下のようにプロセスとイベントに変換される.

5.6.1 連続代入文(Continuous assignment)

連続代入文(6章参照)は,プロセスと式中のソース要素の感度(sensitive)に対応する.
式の値が変化したとき,目標を決定するため,現在の値を用いて,active update eventをイベント待ち行列に追加します.


5.6.2 手続き上の連続した代入(Procedural continuous assignment)

手続き上の連続した代入(assign文かforce代入文(9.3参照))は,式中のソース要素の感度プロセスに対応します.
式の値が変化したとき,目標を決定するため,現在の値を用いて,active update eventをイベント待ち行列に追加します.
deassign文やrelease文は,対応する代入やforce文を無効にする.


5.6.3 Blocking assignment

遅延付きブロッキング代入文(9.2.1参照)は,右辺の値を現在の値を用いて計算ます.そのあと,実行中のプロセスを中断し,未来のイベントとしてスケジューリングされます.
もし,遅延がゼロならば,そのプロセスは現在時刻のinactiveイベントとしてスケジューリングされます.
プロセスから返ってきたとき,(または,遅延指定が無かったとき,即時に返ってきたとき),そのプロセスは左辺への代入を評価し,左辺の更新に基づくイベントを有効にします.
プロセスが再開したときの値は,目標を決定するために使われる.
実行は,その後,次のシーケンシャル文か他のアクティブイベントに続くでしょう.


5.6.4 Non blocking assignment

このtime stepでdelayがゼロのときで,かつ future eventでdelayがゼロではないときのノンブロッキング代入更新イベントでは,ノンブロッキング代入文(9.2.2参照)は,常に更新された値を計算し,更新のスケジュールをします.(ごめん わからん)
更新がイベント待ち行列に置かれると,有効な値は右辺の値と左辺の目標の両方を計算するのに使用されます.

A NON BLOCKING ASSIGNMENT STATEMENT  always computes the updated value and schedules the update
as a NON BLOCKING ASSIGN UPDATE EVENT, either in this TIME STEP if the delay is zero or as a future event if the delay is nonzero.

5.6.5 Switch (transistor) processing

LRM 5.4で示すイベントドリブンシミュレーションアルゴリズムは,片方向信号のフローに依存し,各々のイベントに対して独立に処理可能です.入力が読まれ,結果が計算され,そして更新がスケジュールされます.
Verilog HDLは,ビヘイビアとゲートレベルモデリングに加えて,スイッチレベルモデリングを提供します.
スイッチは双方向信号のフローを提供し,スイッチによって接続されたノードの連携処理を必要とします.
スイッチをモデル化するVerilog HDLソース要素は,tran, tranif0, tranif1, rtran, rtranif0, and rtranif1と呼ばれる様々な形式のトランジスタです.
スイッチ処理は,入力と出力が相互作用するので,ネットの全てのノードのために適切な値を決定する前に,双方向のスイッチで接続されたネットですべてのデバイスを考えるものとします.
シミュレータは,リラクゼーションテクニックを用いることで,これを可能にします.
そのシミュレータは,どのようなときにでも,tran処理ができます.
それは他のアクティブなイベントの実行で混ぜ合わされた特定の時に,tran-connected eventのサブセットとして処理できます.(意訳あやしい. 全部怪しいけれどw)

いくつかのトランジスタにゲート値xがあると、さらなる改善が必要です。

概念的に簡単なテクニックは,完全に伝導・非伝導のトランジスタのすべての可能な組み合わせに設定した,これらのトランジスタで,繰り返してネットワークを解決することです。(意訳:スイッチON/OFFの状態組み合わせを全部見ればOKということでしょう)
すべての場合におけるユニークなロジックレベルを持っているどんなノードも,このレベルと等しい定常応答(steady-state)を持ちます.他のすべてのノードには、定常応答Xがあります.(直訳そのまま.理解できてません.>< )


5.6.6 Port connections

ポート接続手順は,暗黙の連続したassign文か,暗黙の双方向の接続で処理します.
双方向接続は,2つのネットの間で常にenableにされたtran接続に類似していますが,(信号)強度の減少を伴いません.
ポート接続ルールは,値を受け取るのが,ネットまたは構造的なネット式(structural net expression)であることを要求します.ポートは,以下に示すような接続されたオブジェクトを宣言することで,常に表すことができます.

  • input port:外側の式から,ローカルのネット(input)への連続代入(continuous assignment*2
  • output port:ローカルのoutput式から,外側のネットへの連続代入
  • inout:ローカルネットから外側のネットへの,強度減衰の無いトランジスタ接続

5.6.7 Functions and tasks

task parameterとfunction parameterは値渡しとなり,起動時にコピーインされ,リターン時にコピーアウトされます.
functionリターン時のコピーアウトは,どんなブロッキング代入のように同じ挙動で振る舞います.
※意味が通じないナ... functionの値を貰うのは,ノンブロッキング代入と同じ扱いよ,ということかな.

*1 : activeより後ろで処理できないイベント,という意味だろう

*2 : "continuous"とわざわざ着いているのはなんだろう….moduleのポート接続のことかと思ったけど違うのかな...portという型があるんだっけ(汗

LRM読解

2008/09/10Verilogimport

LRM読解

wikiコンテンツとして,Verilogの配下におきます.
気ままに翻訳・転記しているので,結構なボリュームになってきましたので,章ごとにページを分けることにします.それでも結構大きい章があるので悩みどころですが・・・.

あと,私は英語力が弱いので,誤訳も多いと思います.よろしければ指摘いただくと幸いです.あくまでもreferenceですので,使用される処理系依存となっているところもあるかと思います.そのアタリの情報も併記できると良いかな,と考えております.

Xilinx WebPack ISEであれば,言語資料が公開されているのを見た記憶があります.あとはALTERAのQuartus IIでしょうか.
個人で触れるのはそこらへんまでと思いますので,業務で御利用の場合は自社のサポート部門等をあたってください・・・.

といいいつつ,LRM追いかけている途中で力尽きるかもしれませんが..

何も順序どおりに見ていく必要は無いんだ.必要そうなところだけ,かいつまんでもいいんだ・・・(挫折気味(笑

1. 概要 ~ Overview (13)
2. 語彙規約 ~ Lexical conventions 	(14)
3. データ型 ~ Data types	(20)
4. 式 ~ Expressions 	(24)
5. スケジューリング意味ネット? ~ Scheduling semantics	(5)
6. 代入 ~ Assignments	(6)
7. gate/switchレベルモデリング ~ Gate and switch level modeling	(32)
8. ユーザ定義primitive ~ User-defined primitives (UDPs) 	(11)
9. ビヘイビアモデリング ~ Behavioral modeling	(33)
10. taskとfunction ~ Tasks and functions	(11)
11. 名前つきブロックとタスクの無効化 ~ Disabling of named blocks and tasks	(3)
12. 階層構造 ~ Hierarchical structures 	(34)
13. 設計コンテンツのコンフィギュレーション ~ Configuring the contents of a design	(12)
14. Specifyブロック ~ Specify blocks	(26)
15. タイミングチェック ~ Timing checks	(32)
16. SDFを使ったバックアノテーション ~ Backannotation using the Standard Delay Format (SDF)	(8)
17. システムtaskとシステムfunction ~ System tasks and functions 	(47)
18.  ~ Value change dump (VCD) files	(26)
19. コンパイラディレクティブ ~ Compiler directives	(11)

20.  ~ PLI overview	(3)
21.  ~ PLI TF and ACC interface mechanism	(4)
22.  ~ Using ACC routines	(35)
23.  ~ ACC routine definitions	(161)
24.  ~ Using TF routines 	(4)
25.  ~ TF routine definitions 	(55)

26.  ~ Using VPI routines	(41)
27.  ~ VPI routine definitions	(47)

Annex A (normative) Formal syntax definition	(25)
Annex B (normative) List of keywords 	(2)
Annex C (informative) System tasks and functions 	(7)
Annex D (informative) Compiler directives 	(2)
Annex E (normative) acc_user.h	(9)
Annex F (normative) veriuser.h	(8)
Annex G (normative) vpi_user.h 	(14)
Annex H (informative) Bibliography	(1)