Verilogはハードウェア記述言語(HDL)として、論理回路やデジタルシステムの設計に使われます。この記事では、Google Colab上でVerilogコードをPythonから実行する方法を、iverilog
ツールを使って解説します。
必要な準備
Google Colabはデフォルトで Verilog のコンパイラを持っていないため、まず iverilog
をインストールします。
!apt-get update
!apt-get install -y iverilog
このコマンドで、Colabに Verilog のコンパイラ iverilog
とシミュレータ vvp
を追加できます。
今回の題材:AND回路のテストベンチ
以下のVerilogコードでは、シンプルな AND ゲートを設計し、その出力が正しく動作するかを確認する**テストベンチ(検証モジュール)**を定義しています。
module and_gate (
input a,
input b,
output y
);
assign y = a & b;
endmodule
and_gate
モジュールは2つの入力信号 a
, b
を受け取り、AND演算をした結果 y
を出力します。
テストベンチの内容
次に、実際にこの回路をテストするための testbench
モジュールを作成します。
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
で実行します。
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)