フリップフロップを書く

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

概要: 標準IC時代のFF選択手法とHDL設計の違いを理解し、T-FF・JK-FFをVerilogで記述する方法を学ぶ。

目標:

  • HDLでFFを記述する際のalways文の基本構造を理解できる
  • 非同期リセット・非同期セット付きFFを記述できる
  • TフリップフロップをHDLで記述できる
  • JKフリップフロップをHDLで記述できる
  • QB出力付きDFFをassign文を用いて効率よく記述できる

1. HDLによるフリップフロップ記述の概要

もふねこ

昔は「JKフリップフロップ」などのIC部品を組み合わせて回路を作っていたけど、今はHDLで好きなように書けるんだ🐾
便利な時代になったからこそ、中身の仕組みをしっかり理解して書くのが大事だよ!

フリップフロップはいろいろな種類があります。HDLで記述したらどうなるか試してみると面白いと思います。

標準IC時代の設計手法

HDLが論理回路の設計に使用されるようになる前は、標準ICである74HCシリーズ・74LSシリーズを使用して論理回路の設計の大半を行っていました。

この時代の設計者は、標準ICに使用されているフリップフロップから仕様に近いものを選択し、足りない機能は他のゲートICを組み合わせて仕様を満足する設計を行っていました。

💡 標準IC時代の具体例

非同期リセット付きDフリップフロップ(標準IC)とANDゲートを組み合わせて、同期リセット付きDフリップフロップを実現していました。

  • 標準ICから「既存のFF」を選ぶ → 仕様に合わない場合はゲートで補う
  • HDL設計では → 仕様を満足するFFを直接記述できる

2. always文によるFF記述の基本構造

HDLでフリップフロップを記述する場合はalways文を使用します。

種類イベント式の記述ポイント
非同期リセット付きFF@(posedge CK or negedge RB)イベント式にリセット信号を含める
同期リセット付きFF@(posedge CK)イベント式にリセット信号を含めない
非同期リセット(アクティブH)posedge R をイベント式に追加1でリセット
非同期リセット(アクティブL)negedge RB をイベント式に追加0でリセット

FF記述の基本テンプレート

// ① 非同期リセット付きFF(アクティブLow リセット)
always @( posedge CK or negedge RB )
begin
    if ( RB == 1'b0 )      // リセット条件を最初に記述
        Q <= 1'b0;
    else                    // リセット条件以外の動作をelse項に記述
        Q <= D;
end

// ② 同期リセット付きFF
always @( posedge CK )
begin
    if ( RB == 1'b0 )
        Q <= 1'b0;
    else
        Q <= D;
end

// ③ リセットなしFF
always @( posedge CK )
begin
    Q <= D;                 // beginの直後から動作記述を始める
end
📌 FF記述の3原則
  1. イベント式の有無でリセット種類(非同期/同期)が決まる
  2. リセット条件がある場合は begin 直後に最初に記述する
  3. リセット条件以外の動作は else 項に記述する

3. TフリップフロップのHDL記述

TフリップフロップはクロックCKが入力するたびに出力Qが反転する回路で、「トグルフリップフロップ」とも呼ばれます。

T-FFの真理値表

RBCKQ (次の状態)
0x(任意)0(非同期リセット)
1↑(立ち上がり)~Q(前の状態を反転)
module TFF ( CK, Q, RB );
input  CK, RB;
output Q;
reg    Q;

always @( posedge CK or negedge RB )
begin
    if ( RB == 1'b0 )
        Q <= 1'b0;       // 非同期リセット: RBが0でQを0に
    else
        Q <= ~Q;         // CKの立ち上がりで出力を反転
end
endmodule
💡 T-FFのポイント
  • この回路は非同期リセット付きなので、negedge RB をイベント式に記述
  • RBが0のとき → Qに0を代入(リセット)
  • RBが1かつCKの立ち上がりのとき → ~Q(Qの反転値)を代入
  • 真理値表の「次の状態 = ~Q」は「前の状態の反転」を意味する

4. JKフリップフロップのHDL記述

JKフリップフロップは、標準ICを使ってデジタル回路を設計していた時代に多く利用されたフリップフロップです。わずかなゲートを付加するだけで容易にカウンタその他の順序回路を作成できます。

JK-FFの真理値表

クロックCKの立ち上がりで変化する出力Qは、二つの入力JとKの値により4通りの異なる動作をします。

RBSBJKCKQ (次の状態)
0xxxx0(非同期リセット:RBを優先)
10xxx1(非同期セット)
1100Q(保持)
11010(リセット)
11101(セット)
1111~Q(トグル)
📌 JK-FFの動作優先順位

RBが0のときSBはX(DONT CARE)→ リセット動作を優先します。

module JKFF ( CK, J, K, Q, RB, SB );
input  CK, J, K, RB, SB;
output Q;
reg    Q;

// イベント式: クロック + 非同期リセット + 非同期セットをorで接続
always @( posedge CK or negedge RB or negedge SB )
begin
    if ( RB == 1'b0 )           // RBが0: 非同期リセット(優先)
        Q <= 1'b0;
    else if ( SB == 1'b0 )      // RB以外でSBが0: 非同期セット
        Q <= 1'b1;
    else begin
        case ( {J, K} )         // JとKを連接して2ビット条件
            2'b00: Q <= Q;      // 保持
            2'b01: Q <= 1'b0;   // リセット
            2'b10: Q <= 1'b1;   // セット
            2'b11: Q <= ~Q;     // トグル
            default: Q <= Q;    // 不定値対策(必ず記述)
        endcase
    end
end
endmodule
💡 JK-FF記述のポイント
  • イベント式には クロック・非同期リセット・非同期セット の3つをorで接続
  • if-else if の順番で優先順位を表現(RBリセット → SBセット → 通常動作)
  • {J, K} でJ・Kを連接して2ビットのcase条件にする
  • J・Kが不定値になる場合もあるため default の記述を忘れずに

5. QB出力付きDFFの記述

もふねこ

反転出力(QB)を作る時、一つのalways文の中で一緒に書いちゃうと、論理合成ツールが「FFが2つ必要だ!」って勘違いしちゃうことがあるんだ🐾
「FFは1つ!反転はassignで!」って覚えておいてね!

フリップフロップには、クロック立ち上がりで入力Dの値を出力するQと、Dの値の反転を出力するQBの両方を持つものがあります。

✅ 推奨:assign文でQBを記述

module DFF_QB ( CK, D, Q, QB );
input  CK, D;
output Q, QB;
reg    Q;

always @( posedge CK )
begin
    Q <= D;                 // Qはalways文で記述
end

assign QB = ~Q;             // QBはassign文でQの反転を代入(推奨)
endmodule

❌ 非推奨:always文でQBも記述

module DFF_QB_NG ( CK, D, Q, QB );
input  CK, D;
output Q, QB;
reg    Q, QB;

always @( posedge CK )
begin
    Q  <= D;
    QB <= ~D;   // NG: 論理合成ツールはFFが2つあると解釈する
end
endmodule

✅ assign文を使った場合

  • ASICライブラリにQB付きFFがある場合 → QB付きFFとして合成
  • ない場合 → QにインバータをつけてQBを生成
  • 回路規模が小さい

⚠️ always文でQBも記述した場合

  • 論理合成ツールはフリップフロップが2つあると解釈する
  • 動作上の問題は生じないが、論理合成で余分な回路が生成される可能性があるため推奨されません。
  • 回路規模がassign文より大きくなる
⚠️ 結論:QBはassign文で記述すること QB出力はalways文内ではなく、assign QB = ~Q; を使って記述することを推奨します。

📝 C5 まとめ: フリップフロップの記述

FF種類イベント式の例動作の特徴
T-FF(非同期リセット付き)@(posedge CK or negedge RB)CK立ち上がりで出力を反転(トグル)
JK-FF(非同期リセット・セット付き)@(posedge CK or negedge RB or negedge SB)J,Kの組み合わせで保持/リセット/セット/トグル
QB付きDFF(推奨)@(posedge CK) + assign QB=~QQはFF、QBはassign文で反転
非同期リセットの判定イベント式にリセット信号を含むCKに関係なくリセット動作
同期リセットの判定イベント式にリセット信号を含まないCKエッジ時のみリセット動作