回路を書いて動作を確認する

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

概要: いよいよ仕上げのユニットです。電子錠回路を例に、設計の一連の手順を学習します。

目標:

  • 電子錠の仕様を理解し、内部ブロック構成を設計できる
  • 立ち上がり検出回路を記述できる
  • 10to4エンコーダ回路を記述できる
  • 4ビット×4段シフトレジスタを記述できる
  • 一致比較回路を記述できる
  • 錠出力保持回路を記述できる

1. 電子錠回路の概要

もふねこ

Cシリーズの集大成!マンションのオートロックみたいな「電子錠」の回路を作ってみるよ🐾
これまで学んだ組み合わせ回路と順序回路を全部合体させて、一つのシステムを完成させよう!

このユニットでは電子錠の回路を例に、設計の一連の手順を学習します。電子錠はマンションのオートロックなどでよく見かけます。暗証番号を入力して錠を開くため、鍵が不要です。

💡 電子錠の動作概要
  • テンキーにより暗証番号「5、9、6、3」を順番に入力
  • 正しい4桁が入力された場合 → 電子錠が開く(LOCK=0)
  • 誤った番号(例:「1、2、3、4」)を入力した場合 → 電子錠は開かない
  • ロックキー(CLOSE)を押すと → 電子錠が閉じる(LOCK=1)
  • ここで説明する電子錠は簡易版(暗証番号の設定機能・表示部は省略)

2. 仕様と入出力端子表

信号名方向ビット幅機能
CLK入力1動作クロック
TENKEY[9:0]入力10テンキー入力(0〜9の各キーに対応)
CLOSE入力1ロックキー(1のとき錠を閉じる)
LOCK出力1錠の状態(1=施錠、0=解錠)

3. 内部ブロック構成

電子錠の内部ブロックは以下の5つで構成します。

ブロック名回路種別機能
① 立ち上がり検出順序回路TENKEYの立ち上がりを検出し、1クロック分の1パルスを出力
② エンコーダ組み合わせ回路TENKEY[9:0](10ビット)→ 4ビット2進数に変換
③ 暗証番号入力レジスタ順序回路(シフトレジスタ)4ビット×4段のシフトレジスタで入力順に番号を格納
④ 一致比較組み合わせ回路シフトレジスタの値と設定暗証番号を比較し、一致でMATCH=1
⑤ 電子錠出力順序回路(FF)MATCH=1で開状態を保持、CLOSE=1で閉状態に戻す

4. ① 立ち上がり検出回路

もふねこ

ボタンを押したとき、人間にとっては「一瞬」でも、回路から見たら「何万クロックも押しっぱなし」状態なんだ🐾
だから、押された瞬間の「1クロックだけ」を切り取るエッジ検出が絶対に必要なんだよ!

TENKEYのいずれかのキーが押されたとき(立ち上がり)を検出し、CLKの1周期の間だけ1を出力する回路です。この信号を使ってエンコーダ出力を1桁ずつシフトレジスタに入力します。

// 立ち上がり検出: TENKEYの論理和の立ち上がりを1CLK分のパルスに変換
// TENKEY_OR: 10ビットTENKEYのOR(いずれか1つでも押されたら1)
wire TENKEY_OR;
assign TENKEY_OR = |TENKEY;   // リダクションOR演算子

reg  TENKEY_DLY;
wire PULSE;

// 1クロック遅延させてエッジ検出
always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 )
        TENKEY_DLY <= 1'b0;
    else
        TENKEY_DLY <= TENKEY_OR;
end

// PULSE: 現在は1、1クロック前は0 → 立ち上がりエッジを検出
assign PULSE = TENKEY_OR & ~TENKEY_DLY;
💡 立ち上がり検出の原理
  • TENKEY_OR:TENKEYの10ビットをリダクションOR → いずれか押されたら1
  • TENKEY_DLY:TENKEY_ORを1クロック遅延させた信号
  • PULSE = TENKEY_OR & ~TENKEY_DLY:現在=1、前=0 → 立ち上がりのみ1クロック分の1を出力

5. ② エンコーダ回路

TENKEY[9:0](10ビット)を4ビットの2進数に変換します。10ビットのまま記憶すると回路規模が大きくなるため、4ビットに変換してシフトレジスタに格納します。

// エンコーダ: 10ビットTENKEY → 4ビット2進数
function [3:0] ENCODE;
input [9:0] key;
begin
    case ( key )
        10'b0000000001: ENCODE = 4'd0;   // キー0
        10'b0000000010: ENCODE = 4'd1;   // キー1
        10'b0000000100: ENCODE = 4'd2;   // キー2
        10'b0000001000: ENCODE = 4'd3;   // キー3
        10'b0000010000: ENCODE = 4'd4;   // キー4
        10'b0000100000: ENCODE = 4'd5;   // キー5
        10'b0001000000: ENCODE = 4'd6;   // キー6
        10'b0010000000: ENCODE = 4'd7;   // キー7
        10'b0100000000: ENCODE = 4'd8;   // キー8
        10'b1000000000: ENCODE = 4'd9;   // キー9
        default:        ENCODE = 4'd0;
    endcase
end
endfunction

wire [3:0] ENC_OUT;
assign ENC_OUT = ENCODE( TENKEY );

6. ③ 暗証番号入力レジスタ

4ビット×4段のシフトレジスタに、キー入力のたびにエンコーダ出力を格納します。最新の4桁が常にREG[0]〜REG[3]に保持されます。

// 4ビット×4段シフトレジスタ
reg [3:0] REG [3:0];   // REG[0]〜REG[3]: 4段の4ビットレジスタ配列

always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 ) begin
        REG[0] <= 4'd0;
        REG[1] <= 4'd0;
        REG[2] <= 4'd0;
        REG[3] <= 4'd0;
    end
    else if ( PULSE == 1'b1 ) begin
        // PULSEが1のとき(キー押下検出時)にシフト
        REG[3] <= REG[2];       // 古い値を上位にシフト
        REG[2] <= REG[1];
        REG[1] <= REG[0];
        REG[0] <= ENC_OUT;      // 最新の入力をREG[0]に格納
    end
end
💡 シフトレジスタの動作

「5→9→6→3」の順で入力された場合:

入力順REG[3]REG[2]REG[1]REG[0]
「5」入力後5
「9」入力後59
「6」入力後596
「3」入力後5963

7. ④ 一致比較回路

シフトレジスタの値と設定暗証番号「5、9、6、3」を比較し、4桁すべて一致した場合にMATCH=1を出力します。

// 一致比較: 暗証番号 = 5, 9, 6, 3(REG[3]が最初, REG[0]が最後)
wire MATCH;
assign MATCH = ( REG[3] == 4'd5 ) &
               ( REG[2] == 4'd9 ) &
               ( REG[1] == 4'd6 ) &
               ( REG[0] == 4'd3 );

8. ⑤ 電子錠出力回路

MATCH=1で解錠状態を保持し、CLOSE=1で施錠状態に戻す回路です。

// 電子錠出力: LOCK=1が施錠、LOCK=0が解錠
reg LOCK;

always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 )
        LOCK <= 1'b1;           // リセット → 施錠状態
    else if ( CLOSE == 1'b1 )
        LOCK <= 1'b1;           // CLOSE=1 → 施錠
    else if ( MATCH == 1'b1 )
        LOCK <= 1'b0;           // MATCH=1 → 解錠
    // それ以外 → LOCKの値を保持(変化なし)
end

9. 回路記述全体(解答例)

module ELECTRONIC_LOCK ( CLK, RB, TENKEY, CLOSE, LOCK );
input        CLK, RB, CLOSE;
input  [9:0] TENKEY;
output       LOCK;
reg          LOCK;

// ---- ① エンコーダ(function)----
function [3:0] ENCODE;
input [9:0] key;
begin
    case ( key )
        10'b0000000001: ENCODE = 4'd0;
        10'b0000000010: ENCODE = 4'd1;
        10'b0000000100: ENCODE = 4'd2;
        10'b0000001000: ENCODE = 4'd3;
        10'b0000010000: ENCODE = 4'd4;
        10'b0000100000: ENCODE = 4'd5;
        10'b0001000000: ENCODE = 4'd6;
        10'b0010000000: ENCODE = 4'd7;
        10'b0100000000: ENCODE = 4'd8;
        10'b1000000000: ENCODE = 4'd9;
        default:        ENCODE = 4'd0;
    endcase
end
endfunction

// ---- ② 立ち上がり検出 ----
wire       TENKEY_OR;
reg        TENKEY_DLY;
wire       PULSE;
assign TENKEY_OR = |TENKEY;

always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 ) TENKEY_DLY <= 1'b0;
    else              TENKEY_DLY <= TENKEY_OR;
end
assign PULSE = TENKEY_OR & ~TENKEY_DLY;

// ---- ③ エンコーダ出力 ----
wire [3:0] ENC_OUT;
assign ENC_OUT = ENCODE( TENKEY );

// ---- ④ 暗証番号入力レジスタ(4ビット×4段シフトレジスタ)----
reg [3:0] REG [3:0];

always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 ) begin
        REG[0] <= 4'd0; REG[1] <= 4'd0;
        REG[2] <= 4'd0; REG[3] <= 4'd0;
    end
    else if ( PULSE == 1'b1 ) begin
        REG[3] <= REG[2];
        REG[2] <= REG[1];
        REG[1] <= REG[0];
        REG[0] <= ENC_OUT;
    end
end

// ---- ⑤ 一致比較 ----
wire MATCH;
assign MATCH = ( REG[3] == 4'd5 ) &
               ( REG[2] == 4'd9 ) &
               ( REG[1] == 4'd6 ) &
               ( REG[0] == 4'd3 );

// ---- ⑥ 電子錠出力 ----
always @( posedge CLK or negedge RB )
begin
    if ( RB == 1'b0 )       LOCK <= 1'b1;
    else if ( CLOSE == 1'b1 ) LOCK <= 1'b1;
    else if ( MATCH == 1'b1 ) LOCK <= 1'b0;
end

endmodule
⚠️ 設計上の重要ポイント
  • PULSE(立ち上がり検出)を使わないとキーを押している間ずっとシフトが発生してしまう
  • リダクションOR演算子 |TENKEY で10ビットの論理ORを1行で記述できる
  • LOCK出力の優先順位:リセット → CLOSE(施錠) → MATCH(解錠) → 保持
  • シフトレジスタにはノンブロッキング代入(<=)を使うこと

📝 C8 まとめ: 回路記述と動作確認(電子錠)

ブロック回路種別記述方法
エンコーダ(10→4ビット変換)組み合わせfunction + case文
立ち上がり検出(1CLKパルス)順序always + assign(遅延&エッジ検出)
暗証番号レジスタ(4×4シフト)順序reg配列 + always(PULSE制御)
一致比較(4桁照合)組み合わせassign(&演算の連結)
錠出力(状態保持)順序always(CLOSE/MATCH優先順位)