演習B
★★☆ 中級
所要:20–30分
8ビット減算器
2の補数の仕組みを使って、加算器を応用した減算器を Verilog で設計しよう。
📚 概念説明:2の補数による減算
コンピュータの減算は「加算器を使って実現されます。 減算 A − B は、A + (−B) として計算できます。 2進数で −B を表すには 2の補数(ビット反転 + 1)を使います。
2の補数の計算例(8ビット)
B = 0000_0011(= 3)
~B = 1111_1100(ビット反転)
−B = ~B + 1 = 1111_1101(= -3 の2の補数表現)
A − B = A + (~B) + 1 ← Cin に 1 を渡すだけ!
減算器の構成
- 加算器の B 入力を
~B(全ビット反転)に - 加算器の Cin を
1に固定 - これだけで A − B を計算できる!
ボロー(Borrow)とは
A < B の場合、結果が負になり ボロー = 1 になります。8ビット符号なし整数では ~cout がボローに相当します。
| A | B | diff = A−B | borrow | 備考 |
|---|---|---|---|---|
| 10 | 3 | 7 | 0 | 正常 |
| 0 | 0 | 0 | 0 | ゼロ |
| 3 | 10 | 249 | 1 | アンダーフロー |
| 255 | 1 | 254 | 0 | 正常 |
📝 課題
モジュール名:subtractor8
入力:a [7:0]、b [7:0]
出力:diff [7:0](差)、borrow(アンダーフロー時 1)
💻 Verilog テンプレート
Design(右パネル)
// ================================ // 8ビット減算器モジュール // A - B = A + (~B) + 1 // ================================ module subtractor8 ( input [7:0] a, input [7:0] b, output [7:0] diff, output borrow ); wire [8:0] result; // ~b はビット反転(B の1の補数) // +1 は Cin=1 で実現 → 2の補数 = ~b + 1 assign result = {1'b0, a} + {1'b0, ~b} + 9'd1; assign diff = result[7:0]; assign borrow = ~result[8]; // キャリーが出なかった = ボロー endmodule
Testbench(左パネル)
module tb_subtractor8; reg [7:0] a, b; wire [7:0] diff; wire borrow; subtractor8 uut (.a(a), .b(b), .diff(diff), .borrow(borrow)); initial begin $dumpfile("dump.vcd"); $dumpvars(0, tb_subtractor8); $monitor("a=%0d b=%0d | diff=%0d borrow=%0d", a, b, diff, borrow); a = 8'd10; b = 8'd3; #10; // 正常:7 a = 8'd0; b = 8'd0; #10; // ゼロ:0 a = 8'd3; b = 8'd10; #10; // アンダーフロー:borrow=1 a = 8'd255; b = 8'd1; #10; // 254 a = 8'd100; b = 8'd100; #10; // ゼロ:0 $display("--- テスト完了 ---"); $finish; end endmodule
▶ EDA Playground で開く
上のテンプレートを貼り付けてシミュレーションしてみましょう。
🚀 EDA Playground を開く →※ ログインに Gmail が必要です。 使い方ガイドを見る
🤔 考えてみよう
- a=5, b=200 のとき diff と borrow の値を計算して、シミュレーション結果と合っているか確認しよう。
- 加算器(演習A)と減算器のモジュールを比べると、何が違いますか?共通点は何ですか?
- Verilog で
assign diff = a - b;と書くだけでも動作します。なぜでしょうか?手動で2の補数を使う意義は何でしょうか? - 加減算を 1つのモジュールで処理するには、どのような設計にしますか?(ヒント:演習Cで登場します)