01
引き算の結果は、比較の結果でもある
演習Bで作った減算器は diff(差)と borrow(桁借り)の2つを出した。 実はこの2つだけで、a と b の大小関係は完全に分かる。CPU が「if 文」を判断するときも、内部では同じことをしている。
| 関係 | a − b | borrow | diff | 見分け方 |
|---|---|---|---|---|
| a = b | 0 | 0 | 0 | 差がゼロ |
| a < b | 負 | 1 | ラップした値 | 桁借りが起きた |
| a > b | 正 | 0 | 0 以外 | 桁借りなし、かつ差がゼロでない |
つまり eq は「diff の全ビットが 0」、lt は「borrow がそのまま」、
gt は「eq でも lt でもない」。3つ目は、前の2つから作れる。
02
作るモジュールの仕様
- module
- comparator8
- input
- a [7:0] / b [7:0]
- output
- eq — a = b で 1 / lt — a < b で 1 / gt — a > b で 1
- 方針
- 演習Bの減算ロジックを内部に持ち、その diff と borrow から3つのフラグを導く
03
書いて、その場でチェック
減算の部分(演習Bと同じ)はあらかじめ書いてある。あなたが書くのは 最後の3行、diff と borrow から eq・lt・gt を導く部分だけである。
module comparator8 (
input [7:0] a,
input [7:0] b,
output eq,
output lt,
output gt
);
endmodule
Ctrl / ⌘ + Enter でも実行
答え合わせ(自分で試してから開く)
assign eq = (diff == 8'd0); // 差がゼロ assign lt = borrow; // 桁借りが出た assign gt = ~(eq | lt); // どちらでもない
eq は ~|diff(リダクション NOR:全ビットが 0 なら 1)とも書ける。 gt を ~lt とだけ書くと、a = b のときも 1 になってしまうので誤りである。
04
考えてみよう
- gt を ~lt とだけ書くと、どの入力で間違った答えになりますか。チェッカーで実際に試して確かめてみましょう。
- a=0, b=255 のとき diff と borrow はいくつですか。そこから eq・lt・gt がどう決まるか説明してみましょう。
- この比較器は符号なしの比較である。符号付き(−128〜127)で比べたい場合、どこを変える必要がありますか。
- CPU の「もし a が b より小さければジャンプする」という命令は、この3つの信号のどれを使うでしょうか。(演習Eにつながる)
発展:本物のツール(EDA Playground)でも動かす 任意
実際のシミュレータで波形も見たい人は、EDA Playground に設計を貼り付けて実行できる(Gmail アカウントが必要)。 手順は 使い方ガイド へ。
TESTBENCH(左パネル)
module tb_comparator8; reg [7:0] a, b; wire eq, lt, gt; comparator8 uut (.a(a), .b(b), .eq(eq), .lt(lt), .gt(gt)); initial begin $dumpfile("dump.vcd"); $dumpvars(0, tb_comparator8); $monitor("a=%0d b=%0d | eq=%0d lt=%0d gt=%0d", a, b, eq, lt, gt); a = 8'd10; b = 8'd10; #10; a = 8'd3; b = 8'd10; #10; a = 8'd200; b = 8'd15; #10; a = 8'd0; b = 8'd0; #10; a = 8'd255; b = 8'd0; #10; a = 8'd0; b = 8'd255; #10; $display("--- テスト完了 ---"); $finish; end endmodule