Verilog alwaysブロック:構文とセンシティビティリストを理解する
always ブロックはVerilogの 手続き ブロックの1つです。alwaysブロック内の文は順次実行されます。
構文
always @ (event) [statement]
always @ (event) begin [multiple statements] end
always ブロックは特定のイベントで実行されます。イベントはセンシティビティリストで定義されます。
センシティビティリストとは?
センシティビティ リストは、alwaysブロックがいつ実行されるかを定義する式で、@ 演算子の後、括弧 ( ) 内で指定します。このリストには、値の変化でalwaysブロックを実行する1つまたは複数の信号を含めます。
以下のコードでは、信号 a または b の値が変化するたびに、alwaysブロック内のすべての文が実行されます。
// "a"または"b"の値が変化するたびにalwaysブロックを実行
always @ (a or b) begin
[statements]
end
alwaysブロックの用途
always ブロックは組み合わせ要素や順序要素の実現に使用できます。フリップフロップのような順序要素は、クロックとリセットが与えられるとアクティブになります。同様に、組み合わせブロックは入力値のいずれかが変化するとアクティブになります。これらのハードウェアブロックはすべて互いに独立して並行動作します。それらの接続がデータフローを決定します。この振る舞いをモデル化するため、always ブロックを、センシティビティリスト内の信号がアクティブになるとトリガーされ、何らかのアクションを実行する継続的なプロセスとして作成します。
以下の例では、alwaysブロック内のすべての文が、信号 clk のすべての立ち上がりエッジで実行されます。
// 信号"clk"の立ち上がりエッジでalwaysブロックを実行
always @ (posedge clk) begin
[statements]
end
センシティビティリストがない場合どうなる?
always ブロックはシミュレーション期間中、継続的に繰り返されます。センシティビティリストはタイミング制御をもたらします。つまり、センシティビティリスト内のいずれかの信号が変化すると、alwaysブロックがトリガーされます。alwaysブロック内にタイミング制御文がない場合、ゼロ遅延の無限ループによりシミュレーションがハングします!
例
以下の例は、信号 clk の値を反転させようとするalwaysブロックです。この文は前の文から0時間単位後に実行されます。したがって、文に遅延がないため、0時間単位で永遠に繰り返され、シミュレーションがハングします!
// alwaysブロックは時間0で開始
// しかしいつ繰り返されるべきか?
// タイミング制御がないため、0時間単位で留まり
// ループし続け、シミュレーションがハング!
always clk = ~clk;
センシティビティリストが空でも、他の形式の時間遅延が必要です。シミュレーション時間は、以下のように always 構造内の遅延文で進めます。これで、クロック反転が10時間単位ごとに行われます。
always #10 clk = ~clk;
したがって、実際のVerilog設計コードには常にセンシティビティリストが必要です。
順序要素の設計例
以下のコードは、データ入力、クロック、アクティブローリセットを受け取る tff というモジュールを定義します。出力は、クロックの立ち上がりエッジで d が1なら反転します。ここで、always ブロックは clk の立ち上がりエッジまたは rstn の立ち下がりエッジでトリガーされます。
クロックの立ち上がりエッジでは何が起こる?
クロックの立ち上がりエッジでは以下のイベントが起こり、すべての立ち上がりエッジで繰り返されます:
- 最初の
ifブロックでアクティブローリセットrstnの値をチェック rstnが0なら、出力qをデフォルト値0にリセットrstnが1なら、リセット非アサートでデフォルト振る舞い- 前のステップが偽なら:
dの値をチェックし、1ならqの値を反転dが0なら、qの値を維持
module tff (input d, clk, rstn, output reg q);
always @ (posedge clk or negedge rstn) begin
if (!rstn) q <= 0;
else if (d) q <= ~q;
else q <= q;
end
endmodule
リセットの立ち下がりエッジでは何が起こる?
rstn の立ち下がりエッジでは以下のイベントが起こり、すべての発生で繰り返されます:
- 最初の
ifブロックでrstnの値をチェック。立ち下がりエッジでは値は0 rstnの値が0なら、リセットがアサートされ、出力をデフォルト値0にリセットrstnの値が1のケースは考慮不要(現在のイベントはrstnの 立ち下がりエッジ)
組み合わせ要素の設計例
always ブロックは組み合わせブロックの設計にも使用できます。例えば、以下のデジタル回路は3つの異なるロジックゲートの組み合わせで、信号 o で特定の出力を提供します。
以下のコードは、4つの入力ポートと o という単一の出力ポートを持つ module です。always ブロックは、センシティビティリスト内のいずれかの信号が値を変化させるとトリガーされます。出力信号はモジュールポートリストで reg 型として宣言されます。これは手続きブロックで使用されるためです。手続きブロックで使用されるすべての信号は reg 型で宣言する必要があります。
module combo (
input a, input b, input c, input d,
output reg o
);
always @ (a or b or c or d) begin
o <= ~((a & b) | (c^d));
end
endmodule
信号 o は、RHSの組み合わせ式が真になると1になり、偽になると0になります。
Verilog
- Verilogマスター:デジタル回路設計のための完全チュートリアル
- Verilog連結マスター:実践ガイド
- Verilogエッセンシャル:簡潔な概要
- Verilog代入文の理解:種類、構文、ベストプラクティス
- Verilogブロッキング代入とノンブロッキング代入:違いを徹底解説
- Verilog関数のマスター:効率的なRTL設計のために
- Verilogタスクの理解:関数との違い、構文、使用法
- Verilogクロックジェネレータ:設計と実装ガイド
- Verilog数学関数のマスター:効率的なハードウェア設計のために
- Verilog $timeformatのマスター:精度と表示制御
- 任意のスコープでのVerilog timescale理解と表示