Vlsi-design-behavioural-modelling-timing-control-in-verilog

提供:Dev Guides
移動先:案内検索

Verilogの動作モデリングとタイミング

Verilogのビヘイビアモデルには、シミュレーションを制御し、データ型の変数を操作する手続き型ステートメントが含まれています。 これらのすべてのステートメントは、プロシージャ内に含まれています。 各プロシージャには、アクティビティフローが関連付けられています。

動作モデルのシミュレーション中、「always」および「initial」ステートメントで定義されたすべてのフローは、シミュレーション時間「ゼロ」で一緒に開始されます。 初期ステートメントは1回実行され、alwaysステートメントは繰り返し実行されます。 このモデルでは、レジスタ変数aおよびbは、シミュレーション時間「ゼロ」でそれぞれバイナリ1および0に初期化されます。 その後、初期ステートメントは完了し、そのシミュレーション実行中に再度実行されることはありません。 この初期ステートメントには、ステートメントの開始終了ブロック(順次ブロックとも呼ばれます)が含まれています。 このbegin-end型ブロックでは、aが最初に初期化され、次にbが初期化されます。

行動モデリングの例

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
End module

手続き割り当て

プロシージャの割り当ては、reg、integer、time、およびmemory変数を更新するためのものです。 以下に説明するように、手続き型の割り当てと連続的な割り当てには大きな違いがあります-

連続代入はネット変数を駆動し、入力オペランドが値を変更するたびに評価および更新されます。

手続き型の割り当ては、それらを囲む手続き型フロー構造の制御下でレジスタ変数の値を更新します。

手続き型割り当ての右側には、値を評価する任意の式を使用できます。 ただし、右側の部分選択には定数インデックスが必要です。 左側は、右側から割り当てを受け取る変数を示します。 手続き型の割り当ての左側は、次のいずれかの形式を取ることができます-

  • レジスタ、整数、実数、または時間変数-これらのデータ型のいずれかの名前参照への割り当て。
  • レジスタ、整数、実数、または時間変数のビット選択-他のビットに手を加えない単一ビットへの割り当て。
  • レジスタ、整数、実数、または時間変数の部分選択-残りのビットをそのままにしておく、2つ以上の連続したビットの部分選択。 一部選択フォームの場合、定数式のみが有効です。
  • メモリ要素-メモリの単一ワード。 メモリ要素参照では、ビット選択と部分選択は無効であることに注意してください。
  • 上記のいずれかの連結-前の4つの形式のいずれかの連結を指定できます。これにより、右辺式の結果が事実上分割され、連結のさまざまな部分に順番にパーティション部分が割り当てられます。

割り当ての遅延(合成ではない)

遅延割り当てでは、ステートメントが実行されて左側の割り当てが行われる前に、Δt時間単位が経過します。 割り当て内遅延では、右側がすぐに評価されますが、結果が左側の割り当てに配置される前にΔtの遅延があります。 別の手順がΔt中に右側の信号を変更しても、出力には影響しません。 遅延は合成ツールではサポートされていません。

構文

  • 手続き割り当て変数=式
  • 遅延割り当て#Δtvariable = expression;
  • 割り当て内遅延変数=#Δt式;

reg [6:0] sum; reg h, ziltch;
sum[7] = b[7] ^ c[7];//execute now.
ziltch = #15 ckz&h;/*ckz&a evaluated now; ziltch changed
after 15 time units.*/

#10 hat = b&c;/*10 units after ziltch changes, b&c is
evaluated and hat changes.*/

割り当てのブロック

ブロッキングプロシージャの割り当てステートメントは、シーケンシャルブロックで後続のステートメントを実行する前に実行する必要があります。 手続き型の割り当てステートメントをブロックしても、並列ブロックでそれに続くステートメントの実行は妨げられません。

構文

ブロック手順の割り当ての構文は次のとおりです-

<lvalue> = <timing_control> <expression>

ここで、lvalueは手続き型割り当てステートメントに有効なデータ型、=は割り当て演算子、タイミング制御はオプションの割り当て内遅延です。 タイミング制御遅延は、遅延制御(#6など)またはイベント制御(@(posedge clk)など)のいずれかです。 この式は、シミュレータが左側に割り当てる右側の値です。 手続き型割り当てのブロックで使用される=代入演算子は、手続き型連続割り当ておよび連続割り当てでも使用されます。

rega = 0;
rega[3] = 1;           //a bit-select
rega[3:5] = 7;         //a part-select
mema[address] = 8’hff; //assignment to a memory element
{carry, acc} = rega &plus; regb; //a concatenation

ノンブロッキング(RTL)割り当て

ノンブロッキングプロシージャ割り当てにより、プロシージャフローをブロックせずに割り当てをスケジュールできます。 順序や依存関係に関係なく、同じタイムステップ内で複数のレジスタ割り当てを行いたい場合はいつでも、ノンブロッキングプロシージャステートメントを使用できます。

構文

ノンブロッキング手続き型割り当ての構文は次のとおりです-

<lvalue> <= <timing_control> <expression>

ここで、左辺値は手続き型割り当てステートメントに有効なデータ型であり、⇐は非ブロッキング割り当て演算子であり、タイミング制御はオプションの割り当て内タイミング制御です。 タイミング制御遅延は、遅延制御またはイベント制御(@(posedge clk)など)のいずれかです。 この式は、シミュレータが左側に割り当てる右側の値です。 ノンブロッキング割り当て演算子は、シミュレータが同等以下の関係演算子に使用する演算子と同じです。 シミュレーターは、式で使用する場合は⇐演算子を関係演算子として解釈し、非ブロッキングの手続き型割り当て構造で使用する場合は⇐演算子を割り当て演算子として解釈します。

シミュレータが非ブロックプロシージャ割り当てを評価する方法シミュレータが非ブロックプロシージャ割り当てを検出すると、シミュレータは次の2つのステップで非ブロックプロシージャ割り当てを評価および実行します-

  • シミュレーターは右側を評価し、新しい値の割り当てが手続き型タイミング制御で指定された時間に行われるようにスケジュールします。 シミュレーターは右側を評価し、新しい値の割り当てが手続き型タイミング制御で指定された時間に行われるようにスケジュールします。
  • 与えられた遅延が終了するか、適切なイベントが発生したタイムステップの終わりに、シミュレーターは左側に値を割り当てることにより割り当てを実行します。

module evaluates2(out);
output out;
reg a, b, c;
initial

begin
   a = 0;
   b = 1;
   c = 0;
end
always c = #5 ~c;
always @(posedge c)

begin
   a <= b;
   b <= a;
end
endmodule

条件

条件付きステートメント(またはif-elseステートメント)は、ステートメントが実行されるかどうかを決定するために使用されます。

正式には、構文は次のとおりです-

<statement>
::= if ( <expression> ) <statement_or_null>
||= if ( <expression> ) <statement_or_null>
   else <statement_or_null>
<statement_or_null>

::= <statement>
||= ;

<式>が評価されます。 trueの場合(つまり、ゼロ以外の既知の値を持つ場合)、最初のステートメントが実行されます。 false(値がゼロ、または値がxまたはz)の場合、最初のステートメントは実行されません。 elseステートメントがあり、<expression>がfalseの場合、elseステートメントが実行されます。 if式の数値はゼロであることがテストされているため、特定のショートカットが可能です。

たとえば、次の2つのステートメントは同じロジックを表します-

if (expression)
if (expression != 0)

if-elseのelse部分はオプションであるため、ネストされたifシーケンスからelseが省略されると混乱する可能性があります。 これは、elseが欠けている場合、elseを常に最も近い前のものに関連付けることで解決されます。

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

If that association is not what you want, use a begin-end block statement
to force the proper association

if (index > 0)
begin

if (rega > regb)
result = rega;
end
   else
   result = regb;

構成:if- else- if

次の構成は頻繁に発生するため、簡単に個別に説明する価値があります。

if (<expression>)
   <statement>
   else if (<expression>)
   <statement>
   else if (<expression>)
   <statement>
   else
   <statement>

このifのシーケンス(if-else-ifコンストラクトとして知られています)は、多元的な決定を記述する最も一般的な方法です。 式は順番に評価されます。いずれかの式が真の場合、それに関連するステートメントが実行され、これによりチェーン全体が終了します。 各ステートメントは、単一のステートメントまたはステートメントのブロックのいずれかです。

if-else-if構造の最後のelse部分は、「上記のどれでもない」、または他の条件のいずれも満たされていないデフォルトのケースを処理します。 デフォルトの明示的なアクションがない場合があります。その場合、末尾のelseを省略するか、エラーチェックに使用して不可能な状態をキャッチできます。

ケースステートメント

caseステートメントは、式が他の多くの式の1つと一致するかどうかをテストし、それに応じて分岐する特別な多方向決定ステートメントです。 caseステートメントは、たとえば、マイクロプロセッサー命令のデコードを記述するのに役立ちます。 ケース文には次の構文があります-

<statement>
::= case ( <expression> ) <case_item>&plus; endcase
||= casez ( <expression> ) <case_item>&plus; endcase
||= casex ( <expression> ) <case_item>&plus; endcase
<case_item>
::= <expression> <,<expression>>* : <statement_or_null>
||= default : <statement_or_null>
||= default <statement_or_null>

ケース式は、指定された正確な順序で評価および比較されます。 線形検索中に、ケースアイテムの式のいずれかが括弧内の式と一致する場合、そのケースアイテムに関連付けられたステートメントが実行されます。 すべての比較が失敗し、デフォルトの項目が指定されている場合、デフォルトの項目ステートメントが実行されます。 デフォルトのステートメントが指定されておらず、すべての比較が失敗した場合、case itemステートメントは実行されません。

構文とは別に、caseステートメントは、2つの重要な点でmulti-way if-else-ifコンストラクトとは異なります-

  • if-else-ifコンストラクトの条件式は、caseステートメントのように、1つの式を他の複数の式と比較するよりも一般的です。
  • 式にx値とz値がある場合、caseステートメントは最終的な結果を提供します。

ループ文

ループステートメントには4つのタイプがあります。 それらは、ステートメントの実行を0回、1回、または複数回制御する手段を提供します。

  • 文を永久に継続的に実行します。
  • repeatは、ステートメントを一定回数実行します。
  • whileは、式が偽になるまでステートメントを実行します。 式がfalseで始まる場合、ステートメントはまったく実行されません。
  • 次のように、3ステップのプロセスによる関連するステートメントの実行を制御します-
  • 実行されるループの数を制御する変数を初期化するために通常使用される割り当てを実行します
  • 式を評価します。結果がゼロの場合、forループは終了し、ゼロでない場合、forループは関連するステートメントを実行してからステップ3を実行します
  • loopcontrol変数の値を変更するために通常使用される割り当てを実行し、ステップ2を繰り返します

以下は、ループ文の構文規則です-

<statement>
::= forever <statement>
||=forever
begin
   <statement>&plus;
end

<Statement>
::= repeat ( <expression> ) <statement>
||=repeat ( <expression> )
begin
   <statement>&plus;
end

<statement>
::= while ( <expression> ) <statement>
||=while ( <expression> )
begin
   <statement>&plus;
end
<statement>
::= for ( <assignment> ; <expression> ; <assignment> )
<statement>
||=for ( <assignment> ; <expression> ; <assignment> )
begin
   <statement>&plus;
end

遅延制御

遅延制御

手続き文の実行は、次の構文を使用して遅延制御することができます-

<statement>
::= <delay_control> <statement_or_null>
<delay_control>
::= # <NUMBER>
||= # <identifier>
||= # ( <mintypmax_expression> )

次の例では、割り当ての実行を10時間単位遅らせます-

#10レガ= regb;

次の3つの例では、番号記号(#)に続く式を示します。 割り当ての実行は、式の値で指定されたシミュレーション時間の分だけ遅延します。

イベント制御

手続き文の実行は、次のイベント制御構文を使用して、ネットまたはレジスタの値の変更、または宣言されたイベントの発生と同期することができます-

<statement>
::= <event_control> <statement_or_null>

<event_control>
::= @ <identifier>
||= @ ( <event_expression> )

<event_expression>
::= <expression>
||= posedge <SCALAR_EVENT_EXPRESSION>
||= negedge <SCALAR_EVENT_EXPRESSION>
||= <event_expression> <or <event_expression>>
  • <SCALAR_EVENT_EXPRESSION>は、1ビット値に解決される式です。

ネットおよびレジスタの値の変更は、ステートメントの実行をトリガーするイベントとして使用できます。 これは、暗黙的なイベントの検出として知られています。 Verilog構文では、変更の方向に基づいて変更を検出することもできます。つまり、値1(posedge)または値0(negedge)に向かって変更を検出できます。 未知の式の値に対するposedgeとnegedgeの動作は次のとおりです-

  • 1から不明、および不明から0への遷移でネガエッジが検出されます
  • 0から不明、および不明から1への遷移でポーズが検出されます

手順:常にブロックと初期ブロック

Verilogのすべての手順は、次の4つのブロックのいずれかで指定されます。 1)初期ブロック2)常にブロック3)タスク4)機能

初期ステートメントおよびalwaysステートメントは、シミュレーションの開始時に有効になります。 初期ブロックは1回だけ実行され、そのアクティビティはステートメントが終了すると終了します。 対照的に、常にブロックは繰り返し実行されます。 そのアクティビティは、シミュレーションが終了したときにのみ終了します。 モジュールで定義できる初期ブロックと常にブロックの数に制限はありません。 タスクと機能は、他の手順の1つ以上の場所から有効にされる手順です。

初期ブロック

最初のステートメントの構文は次のとおりです-

<initial_statement>
::= initial <statement>

次の例は、シミュレーションの開始時に変数を初期化するための初期ステートメントの使用を示しています。

Initial
Begin
   Areg = 0;//initialize a register
   For (index = 0; index < size; index = index &plus; 1)
   Memory [index] = 0;//initialize a memory
   Word
End

初期ブロックのもう1つの一般的な使用法は、シミュレートされる回路の主要部分に刺激を与えるために1回実行される波形記述の指定です。

Initial
Begin
   Inputs = ’b000000;
  //initialize at time zero
   #10 inputs = ’b011001;//first pattern
   #10 inputs = ’b011011;//second pattern
   #10 inputs = ’b011000;//third pattern
   #10 inputs = ’b001000;//last pattern
End

常にブロック

「always」ステートメントは、シミュレーション実行全体を通して継続的に繰り返されます。 alwaysステートメントの構文は次のとおりです。

<always_statement>
::= always <statement>

「常に」ステートメントは、ループする性質があるため、何らかのタイミング制御と組み合わせて使用​​する場合にのみ役立ちます。 「always」ステートメントが進む時間を提供しない場合、「always」ステートメントはシミュレーションのデッドロック状態を作成します。 たとえば、次のコードは、無限のゼロ遅延ループを作成します-

Always areg = ~areg;

上記のコードにタイミング制御を提供すると、次の例のように潜在的に有用な説明が作成されます-

Always #half_period areg = ~areg;