Google ColabでVerilogコードをPythonから実行する方法



Verilogはハードウェア記述言語（HDL）として、論理回路やデジタルシステムの設計に使われます。この記事では、**Google Colab上でVerilogコードをPythonから実行**する方法を、`iverilog`ツールを使って解説します。

---

##  必要な準備

Google Colabはデフォルトで Verilog のコンパイラを持っていないため、まず `iverilog` をインストールします。

```bash
!apt-get update
!apt-get install -y iverilog
```

このコマンドで、Colabに Verilog のコンパイラ `iverilog` とシミュレータ `vvp` を追加できます。

---

##  今回の題材：AND回路のテストベンチ

以下のVerilogコードでは、シンプルな AND ゲートを設計し、その出力が正しく動作するかを確認する**テストベンチ（検証モジュール）**を定義しています。

```verilog
module and_gate (
    input a,
    input b,
    output y
);
assign y = a & b;
endmodule
```

`and_gate` モジュールは2つの入力信号 `a`, `b` を受け取り、AND演算をした結果 `y` を出力します。

---

##  テストベンチの内容

次に、実際にこの回路をテストするための `testbench` モジュールを作成します。

```verilog
module testbench;
    reg a, b;
    wire y;

    and_gate uut ( .a(a), .b(b), .y(y) );

    initial begin
        $display("a b | y");
        a = 0; b = 0; #10 $display("%b %b | %b", a, b, y);
        a = 0; b = 1; #10 $display("%b %b | %b", a, b, y);
        a = 1; b = 0; #10 $display("%b %b | %b", a, b, y);
        a = 1; b = 1; #10 $display("%b %b | %b", a, b, y);
        $finish;
    end
endmodule
```

- `reg` は入力信号に使われるレジスタ変数。
- `wire` は出力信号に使われる接続線。
- `#10` はシミュレーションで10単位時間の待機を意味します。
- `$display` により、各組み合わせの結果がターミナルに表示されます。

---

##  Pythonコードでの操作手順

Python側では、次のようにこの Verilog コードを `.v` ファイルに書き出し、`iverilog` でコンパイル、`vvp` で実行します。

```python
import subprocess

# Verilogコードをファイルに書き出し
verilog_code = """（上記と同様のVerilogコード）"""
with open("and_test.v", "w") as f:
    f.write(verilog_code)

# コンパイル
subprocess.run(["iverilog", "-o", "and_test", "and_test.v"])

# 実行
result = subprocess.run(["vvp", "and_test"], capture_output=True, text=True)

# 結果表示
print(result.stdout)
```

---

##  出力結果（例）

```
a b | y
0 0 | 0
0 1 | 0
1 0 | 0
1 1 | 1
```

このように、AND回路の出力が正しく表示されていれば、Verilogコードとテストベンチは正常に動作しています。

---

##  まとめ

- `iverilog`と`vvp`を使えば、**Colabでも手軽にVerilogシミュレーションが可能**。
- Pythonとの連携により、**自動化や繰り返し検証がしやすくなる**。
- 複雑な論理設計やFSMなども応用可能。

---

##  応用したい方へ

この仕組みを応用すれば、
- 加算器・減算器などの算術回路
- クロック・リセットを含むFSM（状態機械）
- テストデータ生成と自動検証

などに広げることもできます。ご希望あれば、ぜひお知らせください！








```
# 必要なツールのインストール（初回のみ実行）
!apt-get update -qq
!apt-get install -y iverilog  # iverilog: Verilogコンパイラ / Verilog compiler
import subprocess

# Verilogコードを文字列として定義
# Define Verilog code (AND gate + testbench)
verilog_code = """
// ANDゲートのモジュール定義 / AND gate module
module and_gate (
    input a,
    input b,
    output y
);
assign y = a & b;
endmodule

// テストベンチモジュール / Testbench module
module testbench;
    reg a, b;      // 入力信号（レジスタ）/ input signals (registers)
    wire y;        // 出力信号（ワイヤ）/ output signal (wire)

    // テスト対象のインスタンス化 / Instantiate the DUT (Device Under Test)
    and_gate uut (
        .a(a),
        .b(b),
        .y(y)
    );

    // 初期処理 / Initial block for test sequence
    initial begin
        $display("a b | y");  // ヘッダー出力 / Print header
        a = 0; b = 0; #10 $display("%b %b | %b", a, b, y);
        a = 0; b = 1; #10 $display("%b %b | %b", a, b, y);
        a = 1; b = 0; #10 $display("%b %b | %b", a, b, y);
        a = 1; b = 1; #10 $display("%b %b | %b", a, b, y);
        $finish;  // シミュレーション終了 / End simulation
    end
endmodule
"""

# Verilogコードをファイルに保存 / Save Verilog code to a file
with open("and_test.v", "w") as f:
    f.write(verilog_code)

# Verilogコードをiverilogでコンパイル / Compile Verilog code
subprocess.run(["iverilog", "-o", "and_test", "and_test.v"])

# vvpでシミュレーション実行 / Run the simulation
result = subprocess.run(["vvp", "and_test"], capture_output=True, text=True)

# 実行結果の出力 / Display the simulation result
print("▼ 実行結果 / Simulation Output ▼\n")
print(result.stdout)

```




```

# Verilogシミュレーション環境をColabに構築（1回だけ実行）
!apt-get update -qq
!apt-get install -y iverilog
import subprocess

verilog_code = """
module logic_gates(input a, input b, output and_out, output or_out, output not_a);
    assign and_out = a & b;
    assign or_out  = a | b;
    assign not_a   = ~a;
endmodule

module testbench;
    reg a, b;
    wire and_out, or_out, not_a;

    logic_gates uut(.a(a), .b(b), .and_out(and_out), .or_out(or_out), .not_a(not_a));

    initial begin
        $display("a b | AND OR NOT");
        a = 0; b = 0; #10 $display("%b %b |  %b   %b   %b", a, b, and_out, or_out, not_a);
        a = 0; b = 1; #10 $display("%b %b |  %b   %b   %b", a, b, and_out, or_out, not_a);
        a = 1; b = 0; #10 $display("%b %b |  %b   %b   %b", a, b, and_out, or_out, not_a);
        a = 1; b = 1; #10 $display("%b %b |  %b   %b   %b", a, b, and_out, or_out, not_a);
        $finish;
    end
endmodule
"""

with open("logic_test.v", "w") as f:
    f.write(verilog_code)

subprocess.run(["iverilog", "-o", "logic_test", "logic_test.v"])
result = subprocess.run(["vvp", "logic_test"], capture_output=True, text=True)
print(result.stdout)

verilog_dff = """
module dff(input clk, input reset, input d, output reg q);
    always @(posedge clk) begin
        if (reset) q <= 0;
        else       q <= d;
    end
endmodule

module testbench;
    reg clk, reset, d;
    wire q;

    dff uut (.clk(clk), .reset(reset), .d(d), .q(q));

    initial begin
        $display("clk reset d | q");
        clk = 0; reset = 1; d = 0;
        #5 clk = 1; #5 clk = 0;  // リセット
        reset = 0; d = 1;
        #5 clk = 1; #5 $display("%b %b %b | %b", clk, reset, d, q);
        clk = 0; d = 0;
        #5 clk = 1; #5 $display("%b %b %b | %b", clk, reset, d, q);
        $finish;
    end
endmodule
"""

with open("dff.v", "w") as f:
    f.write(verilog_dff)

subprocess.run(["iverilog", "-o", "dff", "dff.v"])
result = subprocess.run(["vvp", "dff"], capture_output=True, text=True)
print(result.stdout)

```