LRM読解(Chap.9-1 Behavioral modeling)
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)'の値に強制されるでしょう.
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文が省略されたか,想定外の状態をキャッチするエラーチェック用に使われます.