computer system foundationCSF 2026
演習 C / 8-BIT COMPARATOR

8ビット比較器

比較のための新しい回路は要らない。演習Bの引き算の結果を読み取るだけで、大小関係が分かる。

難易度 ★★★ 所要 25–35分 前提 演習B
01

引き算の結果は、比較の結果でもある

演習Bで作った減算器は diff(差)と borrow(桁借り)の2つを出した。 実はこの2つだけで、a と b の大小関係は完全に分かる。CPU が「if 文」を判断するときも、内部では同じことをしている。

関係a − bborrowdiff見分け方
a = b000差がゼロ
a < b1ラップした値桁借りが起きた
a > b00 以外桁借りなし、かつ差がゼロでない
つまり 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

考えてみよう

  1. gt を ~lt とだけ書くと、どの入力で間違った答えになりますか。チェッカーで実際に試して確かめてみましょう。
  2. a=0, b=255 のとき diff と borrow はいくつですか。そこから eq・lt・gt がどう決まるか説明してみましょう。
  3. この比較器は符号なしの比較である。符号付き(−128〜127)で比べたい場合、どこを変える必要がありますか。
  4. 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