デジタル集積回路設計:基礎概念からVerilogHDLによる論理設計まで

1. デジタルIC設計の基礎概念

1.1 抽象化と階層化の意義

集積回路設計では、複雑系を管理するために抽象化と階層化の概念を導入する。一般的に、システムレベル、モジュールレベル、ゲートレベル、回路レベル、デバイスレベルの5つの層に分割して設計が進められる。

この階層化がもたらす主な利点は以下の通りである:

  1. 設計の生産性が向上し、大規模回路の構築が可能になる。設計者は特定の階層の制約内で最適化に注力できる。
  2. システムからデバイスまでの産業分業を促進し、各分野の専門企業が技術を深掘りできる。
  3. EDAツールや計算機の能力を活かした、ルールベースの最適化と反復処理が可能になる。
  4. 設計全体の欠陥を局所化でき、対象範囲を絞ることで問題の本質を見極めやすくなる。

1.2 VLSIにおけるCMOSプロセスの優位性

超大規模集積回路(VLSI)でCMOSプロセスが主流である理由は、静的消費電力が極めて少ないこと、回路構造が単純で製造コストが低いこと、そして集積度が高くチップ面積を縮小できることにある。低消費電力かつ高集積であるため、高周波動作が求められる大規模ロジックの実装に最適である。

1.3 ASIC/FPGAのフロントエンド設計フローとトップダウン設計

ASICフロントエンド:RTLコーディング → 機能シミュレーション → 論理合成 → 等価性検証(形式検証) → 静的タイミング解析(STA)

FPGA設計フロー:RTLコーディング → 機能シミュレーション → 論理合成 → ゲートレベルシミュレーション → 配置配線 → タイミングシミュレーション → ボード実機検証

トップダウン設計の意義は、設計全体の整合性を保ちながらフローを最適化し、効率を高める点にある。一方で課題としては、各段階の境界条件を明確に定義する必要があること、その制約下で仕様を確実に満たすように設計を収束させなければならないことが挙げられる。

1.4 同時スイッチングノイズ(SSN)の低減策

寄生インダクタンスに起因するSSO(同時切替ノイズ)による不安定化を防ぐための主なアプローチは以下の通りである:

  • 電源およびグラウンドプレーンのインピーダンスを低減する。
  • 電流ループのインダクタンスを最小化する。
  • 信号、電源、GNDのピン配分比率を最適化する。
  • 電源・GNDピンの近傍に適切なデカップリングキャパシタを実装する。

1.5 CMOSインバータの駆動力強化

出力駆動の要件を満たしつつ駆動能力を高めるには、MOSトランジスタのゲート幅(W/L比)を大きくすればよい。しかし、大サイズ化に伴い入力容量も増大し、前段の遅延が悪化する。このトレードオフは、寸法を段階的に大きくしたインバータをカスケード接続する「テーパードバッファチェーン」を用いることで解決でき、駆動力と伝搬遅延のバランスを最適化できる。

1.6 デジタル回路設計と学習アプローチ

メモリコンピューティングやニューラルネットワークアクセラレータのような先端アーキテクチャのチップ実装において、行列制御やタイミング生成の土台となるのはデジタルIC設計の知識である。講義内容を実プロジェクトの要件と結びつけて設計方法論を深く理解し、過去の経験則と理論を融合させることで、より高度な研究開発が可能になる。

1.7 VerilogHDLの役割

VerilogHDLは、テキストベースの記述でハードウェアを定義可能にした。システム級、アルゴリズム級、RTL級、ゲート級、スイッチ級といった複数の抽象度でモデル化できるため、トップダウン設計フローを効率よく実行するための強力な基盤を提供する。

1.8 合成可能回路と非合成回路の特徴

合成可能回路:論理合成ツールによりゲートレベルのネットリストに変換可能なRTL記述。信頼性の高い合成結果を得るためのガイドラインとして、initialブロックの不使用、遅延文の排除、不定回数ループの回避、ユーザー定義プリミティブ(UDP)の不使用が推奨される。また、同期設計を基本とし、alwaysブロックでのセンシティビティリストの完全な列挙、_latchの推論を防ぐための条件分岐の網羅、同一変数への多重駆動の回避などが求められる。

非合成回路:シミュレーション専用の機能や構文を含む記述。初期化ブロック、イベント制御、force/release、real/time型、assign/deassignによるreg操作、x値やz値を用いた比較などは合成対象外となる。

1.9 ブロッキング代入とノンブロッキング代入

ブロッキング代入(=):組合せ論理の記述に適する。右辺の評価後ただちに左辺へ代入され、次の文の実行をブロックする。

ノンブロッキング代入(<=):順序回路の記述に適する。右辺の評価はただちに行われるが、左辺への反映はシミュレーション時間ステップの終了時まで遅延され、他の文と並行して評価が進む。

注意点として、順序回路およびラッチのモデリングにはノンブロッキング代入を、組合せ論理のalwaysブロックにはブロッキング代入を用いる。同一alwaysブロック内での混用は厳禁であり、複数のalwaysブロックから同じ変数を駆動してはならない。

1.10 同期回路と非同期回路の比較

同期回路は単一のクロックソースで全フリップフロップが同時に状態更新するため、遅延変動が少なくグリッチの影響を回避しやすい。STAが簡素化され、検証が容易になる利点がある。一方、非同期回路は構造はシンプルだが、クロックドメインをまたぐ際のメタスタビリティ問題や、遅延の蓄積による状態遷移の異常を考慮する必要がある。

1.11 ラッチとD-フリップフロップ

ラッチはレベルセンシティブであり、イネーブル信号が有効な間は入力がそのまま出力に透過される。一方、D-FFはエッジセンシティブであり、クロックの遷移時点でのみ状態を捕捉する。ラッチはゲート数が少なくて済むが、グリッチを通過させやすく、STAを著しく困難にする。そのため、特別な意図がない限り、RTL設計で意図せぬラッチの生成は避けるべきである。

2. VerilogHDLによる論理回路設計

2.1 前導1検出器

32ビットの入力ベクタにおいて、最上位ビット(MSB)側から探索して最初に1が現れる位置を出力する組合せ回路。入力が全0の場合は32を出力する。

入出力仕様:

名称方向ビット幅説明
vecI32入力ベクタ
lead_idxO6最初の1の位置 (0〜32)

設計要件:論理遅延を最小化し、合成可能なVerilogコードを実装する。

module FindFirstOne (
    input  wire [31:0] vec,
    output reg  [5:0]  lead_idx
);
    integer k;
    always @(*) begin
        lead_idx = 6'd32;
        for (k = 31; k >= 0; k = k - 1) begin
            if (vec[k]) lead_idx = 6'd31 - k;
        end
    end
endmodule
module tb_find_first_one;
    reg  [31:0] vec;
    wire [5:0]  lead_idx;

    FindFirstOne uut (.vec(vec), .lead_idx(lead_idx));

    initial begin
        vec = 32'b00011000_10000000_00000000_00000000; #10;
        vec = 32'b00000000_11111111_00000000_00000000; #10;
        vec = 32'b00000000_00000000_00000000_00001010; #10;
        vec = 32'b00000000_00000000_00000000_00000000; #10;
        $finish;
    end
endmodule

2.2 シーケンス検出器

入力ストリームから特定のビットパターン(111000 または 101110)を検出する同期順序回路。パターン検出後の次のクロックサイクルで結果を出力する。入力有効信号が無効でもシフトレジスタはリセットされず、重複検出を許容する。

入出力仕様:

名称方向ビット幅説明
clkI1システムクロック
rst_nI1非同期リセット (アクティブLow)
valid_inI1入力有効信号
serial_inI1入力データ
match_outO1パターン検出結果

設計要件:面積を最小化し、合成可能なVerilogコードを実装する。

module PatternDetector (
    input  wire clk,
    input  wire rst_n,
    input  wire valid_in,
    input  wire serial_in,
    output wire match_out
);
    reg [5:0] pattern_buf;

    assign match_out = (pattern_buf == 6'b111000 || pattern_buf == 6'b101110);

    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            pattern_buf <= 6'b0;
        end else if (valid_in) begin
            pattern_buf <= {pattern_buf[4:0], serial_in};
        end
    end
endmodule
module tb_pattern_detector;
    reg clk, rst_n, valid_in, serial_in;
    wire match_out;

    PatternDetector uut (
        .clk(clk), .rst_n(rst_n), .valid_in(valid_in), 
        .serial_in(serial_in), .match_out(match_out)
    );

    always #5 clk = ~clk;

    initial begin
        clk = 0; rst_n = 0; valid_in = 0; serial_in = 0;
        #10 rst_n = 1; valid_in = 1;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #10 serial_in = 1;
        #10 serial_in = 1;
        #10 serial_in = 1;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #10 serial_in = 1;
        #10 serial_in = 1;
        #10 serial_in = 0;
        #10 serial_in = 1;
        #10 serial_in = 1;
        #10 serial_in = 1;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #10 serial_in = 0;
        #50 $finish;
    end
endmodule

2.3 バイナリ-BCD変換器

8ビットの符号なし2進数(0〜255)を10ビットのBCDコードに変換する組合せ論理回路。10ビットBCDのフォーマットは、上位2ビットが百の位、中間4ビットが十の位、下位4ビットが一の位を表す。

入出力仕様:

名称方向ビット幅説明
binary_valI8入力2進数
bcd_resultO10出力BCDコード

設計要件:論理遅延を最小化し、合成可能なVerilogコード(Double Dabbleアルゴリズム等)を実装する。

module BinToBcdConverter (
    input  wire [7:0] binary_val,
    output wire [9:0] bcd_result
);
    reg [3:0] hundreds, tens, units;
    integer   m;

    always @(*) begin
        hundreds = 4'd0;
        tens     = 4'd0;
        units    = 4'd0;

        for (m = 7; m >= 0; m = m - 1) begin
            if (hundreds >= 5) hundreds = hundreds + 3;
            if (tens     >= 5) tens     = tens + 3;
            if (units    >= 5) units    = units + 3;

            hundreds = hundreds << 1;
            hundreds[0] = tens[3];
            
            tens = tens << 1;
            tens[0] = units[3];
            
            units = units << 1;
            units[0] = binary_val[m];
        end
    end

    assign bcd_result = {hundreds[1:0], tens, units};
endmodule
module tb_bin_to_bcd;
    reg  [7:0] binary_val;
    wire [9:0] bcd_result;

    BinToBcdConverter uut (
        .binary_val(binary_val),
        .bcd_result(bcd_result)
    );

    initial begin
        binary_val = 8'b10100101; #10; // 165
        binary_val = 8'b11110000; #10; // 240
        binary_val = 8'b00000000; #10; // 0
        binary_val = 8'b11111111; #10; // 255
        $finish;
    end
endmodule

タグ: Verilog VLSI CMOS FPGA DigitalLogic

7月28日 21:57 投稿