Altifigence Academy

10 / 63 · 実習

設計実習:仕様から 3 入力多数決回路へ

自然言語の仕様を完全な真理値表にし、最小化・実装・全数検査をつなげます。

実装前に条件を固定します

三つの入力 a・b・c のうち、二つ以上が 1 なら y=1 となる回路を作ります。入力は安定した 0/1、各入力の重みは等しく、以前の入力は記憶しないと定めます。「ちょうど二つ」と「二つ以上」は、111 で異なる関数です。

abc000001010011100101110111
y00010111
y=Σm(3,5,6,7)=ab+ac+bcy=\Sigma m(3,5,6,7)=ab+ac+bc

三つの項は、それぞれ二つの入力が同時に 1 であることを表します。同じ機能を y=ab+c(a+b)y=ab+c(a+b) と因数分解することもできます。どちらが速いかはセルと到着時刻によります。

多数決は全加算器のキャリーと同じです

下の cin を第三の入力 c として読んでください。cout が今回の y で、sum は奇数パリティパリティ 1 のビット数が奇数か偶数かを表す値です。パリティ検査は奇数個のビット誤りを検出しますが、偶数個の誤りを見逃す場合があります。 詳しく見るです。001 と 111 を比較すると、パリティを多数決として使う誤りが見えてきます。

cout で多数決の八つの入力を確認

a + b + cin = sum + 2 × cout

仕様を基に、実装とは独立した検査基準を作ります

(a & b) | (a & c) | (b & c) と同じ式を参照モデルにコピーすると、同じ間違いを持ち込むおそれがあります。仕様の「1 が二つ以上」を整数で計算する基準を使います。

SystemVerilog
module voter3(input logic a, b, c, output logic y);
  assign y = (a & b) | (a & c) | (b & c);
endmodule

module tb;
  timeunit 1ns;
  timeprecision 1ps;
  logic a, b, c, y;
  int ones;
  voter3 dut(.*);
  initial begin
    for (int v = 0; v < 8; v++) begin
      {a, b, c} = v[2:0];
      #1;
      ones = int'(a) + int'(b) + int'(c);
      assert (y === (ones >= 2))
        else $fatal(1, "voter mismatch at %03b", {a,b,c});
    end
    $finish;
  end
endmodule

各ビットを int に拡張したのは、1 ビット演算の幅による混乱を避けるためです。#1 はこのテストの組合せ論理が更新される時間を与えるもので、実チップが 1 ns で動く証拠ではありません。

仕様を変えて反例を探す

出力を許可する enable e を追加すると、y=e(ab+ac+bc)y=e(ab+ac+bc) になります。入力は四つになり、全数検査には 16 組必要です。e=0 のとき a・b・c をすべて無視するという不変条件不変条件 許可されたすべての実行で、常に真でなければならない条件です。例えば深さ 4 の FIFO の格納数は常に 0 以上 4 以下です。 詳しく見るも、別に検査してください。

自分で考えてみましょう

誤った実装 y=(a XOR b XOR c) を検出する入力をすべて挙げてください。「ちょうど二つが 1」の関数に変えると、元の多数決と異なる行はどれですか。

解説を見る

XOR と異なる入力は 001・010・100・011・101・110 です。前の三つでは誤って 1、後の三つでは誤って 0 になります。ちょうど二つの関数では、多数決の 111 だけが 0 に変わります。

選択はこのブラウザに適用されます。フッターからいつでも変更できます。