0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Verilogで作る4ビットCPU入門:シミュレーションと回路図生成まで

Last updated at Posted at 2025-10-26

目的

Verilogで簡単な4ビットCPUを作成し、どんな回路が生成されるかを確認します。
作業はx86_64 Ubuntu上にて行います。
加算、減算とメモリの操作のみて、分岐等にはまだ対応していません。

実装

cpu4.v
//============================================================
// 4bit CPU
//============================================================
// このファイルは1つのCPUをまるごと定義しています
// 命令は8bitで上位4bitが命令コード下位4bitが値やメモリアドレスです
//============================================================

module cpu4 (
    input clk,          // クロック信号時間の進みを表す1回動くたびに1命令実行
    input reset,        // リセット信号最初に戻す
    output reg [3:0] acc,   // アキュムレータ計算結果を入れる4ビットレジスタ
    output reg halted       // HLT命令を実行したら1になる止まった状態
);

    //===== メモリ16 x 8bit ===========================
    reg [7:0] memory [0:15];   // メモリプログラムとデータを格納

    //===== プログラムカウンタ ==============================
    reg [3:0] pc;  // 次に実行する命令の場所015

    //===== 命令の内訳 =======================================
    reg [7:0] instr;           // 現在実行中の命令 8bit
    wire [3:0] opcode = instr[7:4];   // 上位4ビット  命令の種類
    wire [3:0] operand = instr[3:0];  // 下位4ビット  値またはアドレス

    //===== メモリ初期化外部ファイル読み込み ===========
    integer i;
    initial begin
        // メモリを0で初期化
        for (i = 0; i < 16; i = i + 1)
            memory[i] = 8'b00000000;

        // 外部ファイルからプログラムを読み込む
        // 別ファイル program.mem に命令を記述しておく
        $readmemb("program.mem", memory);
    end

    //===== CPU動作 =================================
    always @(posedge clk) begin // クロックclkが立ち上がった瞬間01になった瞬間ここが実行される
        if (reset) begin // resetが1の場合に実行
            pc <= 0;
            acc <= 0;
            halted <= 0;
        end else if (!halted) begin
            //=======================
            // 1. 命令を読み取る
            //=======================
            instr <= memory[pc];

            //=======================
            // 2. 命令を実行する
            //=======================
            case (opcode)
                4'b0001: begin // LDI (即値をACCへ格納)
                    acc <= operand;      // ACCに値を入れる
                    pc <= pc + 1;        // 次の命令へ
                end
                4'b0010: begin // LD (指定したメモリアドレスの値(下位4ビット) ACC に読み込む)
                    acc <= memory[operand][3:0]; // メモリの値を読み込む
                    pc <= pc + 1;
                end
                4'b0011: begin // ST(LDの逆)
                    memory[operand] <= {4'b0000, acc}; // ACCをメモリに書く(4ビットのみ対応上位4ビットは常に0000)
                    pc <= pc + 1;
                end
                4'b0100: begin // ADD
                    acc <= acc + memory[operand][3:0]; // メモリの値を足す
                    pc <= pc + 1;
                end
                4'b0101: begin // SUB
                    acc <= acc - memory[operand][3:0]; // メモリの値を引く
                    pc <= pc + 1;
                end
                4'b1111: begin // HLT
                    halted <= 1;  // 停止
                end
                default: begin
                    pc <= pc + 1; // 何もせず次へ
                end
            endcase
        end
    end
endmodule



//============================================================
// 実際にCPUを動かして結果を見るためのコード
//============================================================
module testbench;
    reg clk;        // 入力
    reg reset;      // 入力
    wire [3:0] acc; // 出力
    wire halted;    // 出力

    // CPUを接続
    cpu4 uut (
        .clk(clk),
        .reset(reset),
        .acc(acc),
        .halted(halted)
    );

    // クロックを作る0101と変化
    initial begin
        clk = 0;
        forever #5 clk = ~clk;  // 5単位ごとに反転周期10
    end

    // テストシーケンス
    initial begin
        $dumpfile("cpu4.vcd");  // 波形ファイル出力
        $dumpvars(0, uut);

        // リセット
        reset = 1;
        #10;
        reset = 0;

        // 実行を少し待つ
        #100;

        // 結果表示
        $display("ACC = %d", acc);
        $finish;
    end
endmodule

実行方法

iverilog -o cpu4.out cpu4.v
vvp cpu4.out

回路図生成

yosys
read_verilog cpu4_2.v
hierarchy -top cpu4
proc; opt
show -format dot -prefix cpu4
rsvg-convert cpu4.svg -o cpu4.png
dot -Tsvg cpu4.dot -o cpu4.svg

cpu4.png

機械語

00010011 : LDI 3(ACC ← 3)
01000101 : ADD 5(ACC ← ACC + MEM[5])
00110110 : ST 6(MEM[6] ← ACC)
11110000 : HLT(停止)
00000000 : 使わない領域
00000010 : MEM[5] = 2

00010011
01000101
00110110
11110000
00000000
00000010
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
00000000
test@test-ThinkPad-X280:~/kaihatsu/cpu$ iverilog -o cpu4.out cpu4.v
test@test-ThinkPad-X280:~/kaihatsu/cpu$ vvp cpu4.out
VCD info: dumpfile cpu4.vcd opened for output.
ACC =  5
0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?