順序回路の書き方基礎

📌 このページの概要と目標

概要: 順序回路の基本単位であるD-FFとラッチの記述を学び、2種類の代入文と同期/非同期リセットを理解する。

目標:

  • D-FF、ラッチの回路記述ができる
  • 順序回路用の真理値表を理解できる
  • ブロッキング代入とノンブロッキング代入について理解し記述できる
  • 非同期リセットと同期リセットについて理解し記述できる
  • 非同期リセットを使用するメリットを理解できる
  • D-FF、ラッチを記述する際の注意点を理解できる

修了判定: D-FFの記述の空欄を埋めて完成させる

1. DフリップフロップのPosedge記述

もふねこ

いよいよ「順序回路」の登場だよ!クロックに合わせて動く、記憶を持った回路だね🐾
C言語などのソフト開発にはない「ハードウェア特有の動き」だから、じっくり理解していこう!

DフリップフロップはクロックCKの立ち上がりで入力Dの値を出力Qに転送します。CKの立ち上がり以外の期間はalways文が実行されないため、Qの値は保持されます。

module DFF ( CK, D, Q );
input  CK, D;
output Q;
reg    Q;

always @( posedge CK ) begin
    Q <= D;
end
endmodule
タイミング動作
CKの立ち上がり(posedge)入力DをQに転送
それ以外の期間Qの値を保持
💡 タイミングチャートの読み方 CKが立ち上がる瞬間の入力Dの値が、そのクロック周期の出力Qの値になります。

2. DフリップフロップのNegedge記述

クロックの立ち下がりで転送するD-FFは、イベント式にnegedge CKと記述します。回路図ではCKの入力に○(反転記号)を付けます。

module DFF ( CK, D, Q );
input  CK, D;
output Q;
reg    Q;

always @( negedge CK ) begin
    Q <= D;
end
endmodule
記述転送タイミング
posedge CKCKの立ち上がり
negedge CKCKの立ち下がり

3. ラッチの記述

ラッチは入力Gの値が1の期間に入力Dの値を出力Qに転送します。D-FFと異なりクロックエッジではなくレベルで動作します。

module LATCH ( G, D, Q );
input  G, D;
output Q;
reg    Q;

always @( G or D ) begin
    if( G==1'b1 )
        Q <= D;
end
endmodule
💡 ラッチの動作
  • センシティビティリストはG or D(GまたはDが変化したときに実行)
  • G==1'b1 のとき:DがQに転送される
  • G==1'b0 のとき:if文が実行されないのでQは保持
  • if条件をG==1'b0にすると「Gが0のときに転送」するラッチになる

4. ブロッキング代入とノンブロッキング代入

もふねこ

「=」と「<=」の違いは、Verilogで一番つまづきやすいポイントなんだ🐾
順序回路を書くときは『絶対に <= (ノンブロッキング代入)を使う!』ってルールを叩き込んでね!

always文内でのレジスタ信号への代入には2種類あります。

代入方式記号動作
ブロッキング代入=1行ずつ順番に実行。前の代入が終わってから次の行へ
ノンブロッキング代入<=CKエッジ時点の右辺の値を全て同時に左辺へ代入

ブロッキング代入

wire DIN;
reg  A, B, C;
always @( posedge CK )
begin
    A = DIN;   // まずAにDINを代入
    B = A;     // 次にBにA(=DINの値)を代入
    C = B;     // 次にCにB(=DINの値)を代入
end
// 結果: A=B=C=DIN(同じ値になる)

ノンブロッキング代入

wire DIN;
reg  A, B, C;
always @( posedge CK )
begin
    A <= DIN;  // CKエッジ時のDINをAへ
    B <= A;    // CKエッジ時の(旧)AをBへ
    C <= B;    // CKエッジ時の(旧)BをCへ
end
// 結果: A=DIN, B=旧A, C=旧B(シフトレジスタ動作)
⚠️ 順序回路にはノンブロッキング代入を使用すること ブロッキング代入は記述の順序によって生成される回路が変わりミスの元になります。
ブロッキング代入で逆順(C=B; B=A; A=DIN;)に書けばノンブロッキング代入と同じ回路になりますが、それはむしろミスにつながるため、順序回路には常にノンブロッキング代入(<=)を使用してください。
💡 生成される回路の違い
  • ブロッキング代入(= で順順): DINから全FFs(A,B,C)が同じCKエッジ後に同一値になる(並列構造)
  • ノンブロッキング代入(<=): DIN→A→B→Cと1クロックずつずれて転送される(シフトレジスタ構造)

5. 非同期リセットと同期リセット

フリップフロップをリセットする方法には非同期リセット同期リセットの2種類があります。

順序回路用の真理値表の読み方

記号意味
xDON'T CARE(1でも0でも構わない)
クロックの立ち上がり
クロックの立ち下がり

非同期リセット付きDFF(DFF_ASYNC)

RBDCKQ
0xx0(RBが0ならCKに関係なくリセット)
111
100
module DFF_ASYNC ( CK, D, Q, RB );
input  CK, D, RB;
output Q;
reg    Q;

always @( posedge CK or negedge RB )
begin
    if ( RB==1'b0 )
        Q <= 1'b0;
    else
        Q <= D;
end
endmodule

同期リセット付きDFF(DFF_SYNC)

RBDCKQ
0x0(CK立ち上がりかつRB=0のときリセット)
111
100
module DFF_SYNC ( CK, D, Q, RB );
input  CK, D, RB;
output Q;
reg    Q;

always @( posedge CK )
begin
    if ( RB==1'b0 )
        Q <= 1'b0;
    else
        Q <= D;
end
endmodule
📌 非同期 vs 同期の判定方法 イベント式(@(posedge CK or negedge RB))にリセット条件(negedge RB)を記述すれば非同期リセット、記述しなければ同期リセットになります。

6. 非同期リセットのメリット・デメリット

ASIC設計ではフリップフロップやカウンタ等の初期化に非同期リセットを多く用います

✅ メリット

  • 回路の初期化にクロックが不要
  • チップ上のフリップフロップ全体の初期化が簡単
  • SYSRESB信号を0にするだけでリセット可能 → シミュレーションの初期設定パターンが短くて済む

⚠️ デメリット

  • 非同期リセット付きFFは通常のFFより回路規模が大きい
  • チップ全体にリセット信号を引き回す必要があるため、レイアウトが難しくなる
💡 シミュレーション観点からの利点 同期リセットの場合、リセットにはクロック供給が必要です。他の回路がCKを生成している場合、そのCKが入力されるまでリセットされずシミュレーション時間が長くなります。非同期リセットはこの問題がありません。

7. 記述上の注意点(ワンポイント・アドバイス)

⚠️ 注意点1:1つのalways文に1クロック・単一エッジのみ定義する

以下の記述は論理合成ツールでエラーになります(文法エラーではないためRTLシミュレーションは通る):

// ❌ NG例1: 複数のクロックを定義
always begin
    @( posedge CK1 )
        Q <= D;
    @( posedge CK2 )
        Q <= 1'b1;
end

// ❌ NG例2: 同一クロックで立ち上がりと立ち下がりの両方
always begin
    @( posedge CK )
        Q <= D;
    @( negedge CK )
        Q <= 1'b1;
end
⚠️ 注意点2:順序回路の出力にinitial文で初期値を設定しない

実際の回路では電源投入直後の出力状態(0 or 1)は不定です。initial文は論理合成ツールでエラーになります。

// ❌ NG例: initial文は論理合成できない
initial
    Q <= 1'b0;

always @( posedge CK ) begin
    Q <= D;
end
注意点RTLシミュレーション論理合成
複数クロック定義正常終了⛔ エラー
両エッジ定義正常終了⛔ エラー
initial文による初期値正常終了⛔ エラー

8. 修了判定

設問: 真理値表を参考にして、非同期リセット付きのD-FFを記述する。

立ち下がりクロックで転送され、R が1のとき出力Qは0にリセットされる。

RDCKQ
1xx0(Rが1ならCKに関係なくリセット)
011
000
▶ 解答を見る
module DFF_ASYNC ( CK, D, Q, R );
input  CK, D, R;
output Q;
reg    Q;

always @( negedge CK or posedge R )
begin
    if ( R==1'b1 )
        Q <= 1'b0;
    else
        Q <= D;
end
endmodule
💡 ポイント
  • 立ち下がりクロックなので negedge CK
  • 非同期リセットなので posedge R もイベント式に追加
  • R==1'b1 のときリセット(アクティブHigh)

📝 C4 まとめ: 順序回路の基礎

項目記述方法ポイント
D-FF(立ち上がり)always @(posedge CK)最も一般的なFF
D-FF(立ち下がり)always @(negedge CK)CK入力に○マーク
ラッチalways @(G or D) if(G) Q<=D;Gが1の期間転送
ノンブロッキング代入<=順序回路では必須
非同期リセットイベント式に negedge RB を追加ASIC設計で多用
同期リセットイベント式にリセット条件を書かないCK立ち上がりのみリセット