アフィリエイト広告
アフィリエイト広告

論理回路 / 半加算器と全加算器

論理回路のおさらいです。今回は、半加算器と全加算器について。

半加算器

A B S C
0000
0110
1010
1101
図 1. 半加算器の真理値表

半加算器は、1 ビットの加算を行なう回路だけど、下位からの桁上げ入力がない最下桁の加算器。

図 1 が、半加算器の真理値表。A、B が加算する 2 つの値、S がその和で、C は桁上がり出力です。
桁上がりってのは、ようするにオーバーフロー。1 ビットの計算しかできない半加算器なのに、和が 2 ビットになっちゃったよ、という出力です。

真理値表から、主加法標準形で求めた論理式が、次のとおり。

S = A⋅B + A⋅B = A ⨁ B
C = A⋅B

真理値表をじっと眺めればわかりますね、S は XOR、C は AND だってこと。

図 2. 半加算器の回路

論理式からつくった回路が、図 2。

むずかしい回路ではないです。A と B のどちらか一方が 1 のとき 1 を出力するのが XOR、A と B がともに 1 のとき、つまり AND したのが桁上がり。

でも、これだけでは意味わからん。1 と 1 足して 2 になってるような、なってないような加算器、って何なん? この意味不明な回路が、加算器の理解を妨げてる、と思う俺 (;´Д`)

全加算器

CiA B S Co
00000
00110
01010
01101
10010
10101
11001
11111
図 3. 全加算器の真理値表

全加算器も、1 ビットの加算を行なう回路。
半加算器との違いは、下位からの桁上げを受け取れるってこと。つまり、最下桁の半加算器から出力された桁上がりを受けて、2 ビット目の計算をする回路です。

図 3 が真理値表。A、B が加算する値、Ci は下位からの桁上げ、S が和、Co が上位への桁上げ。

だから、Co がさらに上位の全加算器に送られて、1 桁ずつ順番に加算していく仕組みなんだ。ちょっと姿がみえてきたね。

主加法標準形で論理式を求めます。まずは、和の出力 S。Ci も加算されるところがミソです。

S = CiA⋅B + Ci⋅A⋅B + Ci⋅AB + Ci⋅A⋅B
  = Ci ( A⋅B + A⋅B ) + Ci ( AB + A⋅B )
  = Ci ( A ⨁ B ) + Ci ( A ⨁ B )
  = Ci ⨁ ( A ⨁ B )

次に、桁上げ出力 Co。

Co = Ci⋅A⋅B + Ci⋅A⋅B + Ci⋅A⋅B + Ci⋅A⋅B
   = A⋅B ( Ci + Ci ) + Ci ( A⋅B + A⋅B )
   = A⋅B + Ci ( A ⨁ B )

こちらも、真理値表をじっと眺めればみえてくる。S は XOR と XNOR、Co は AND と OR だね。Ci によって切り換わる。

図 4. 全加算器の回路

論理式からつくった回路が、図 4 です。

全加算器をググると、半加算器 2 つと OR ゲートの組み合わせ回路がでてくるんだけど、俺、あれ、どうも理解しづらいんです。結果が加算になるのは、わかる。でも、いまいちストンと落ちない。

真理値表、論理式ときて、そこから回路をつくると、おお、そうか、わかった。そーゆーことか。

まぁ、理解のしかたなんて人それぞれなので、お好みでどうぞ。

VerilogHDL でシミュレーションしてみた

たいした回路でもないので、ちゃちゃっと組み立ててみてもいいのですが、VerilogHDL を勉強したので、せっかくですから、シミュレーションしてみましょう。

今回のシミュレーションでは、論理ゲートで組んだ全加算器の回路の動作が、真理値表から求めた論理式と一致するかどうか、を検証します。

回路記述

  1. module FULL_ADDER(
  2.   input wire A, B, CI,
  3.   output wire S, CO
  4. );
  5.   parameter test_type = 0;

まずは、まいどのモジュール名と入出力信号の宣言。パラメータとして test_type を設定していますが、これについては後述。

  1.   generate
  2.     if(0 == test_type) begin
  3.       // logic circuit
  4.       wire Y1, Y2, Y4;
  5.       xor U1(Y1, A, B);
  6.       and U2(Y2, A, B);
  7.       xor U3(S, Y1, CI);
  8.       and U4(Y4, Y1, CI);
  9.       or U5(CO, Y4, Y2);
  10.     end

お初の、「generate」による回路の切り換え。test_type が 0 のとき、この回路記述が選択されます。パラメータの設定は、test_type=0 ですので、こちらがデフォルトになります。

Y1、Y2、Y4 は、それぞれゲート U1、U2、U4 の出力信号です。
13~17 行目は「プリミティブゲート接続」です。プリミティブゲートとは、VerilogHDL にあらかじめ組み込まれているゲート回路。モジュールを定義しなくても、インスタンスとして利用できます。それぞれのゲートの入出力を、回路図にしたがって定義しています。

  1.     else if(1 == test_type) begin
  2.       // boolean expression
  3.       assign S = CI ^ (A ^ B);
  4.       assign CO = A & B | CI & (A ^ B);
  5.     end
  6.   endgenerate
  7. endmodule

次は、test_type=1 の場合。test_type は、テストベンチのパラメータ割り当てで変更します。パラメータ割り当てを 1 にすることで、こちらの回路に切り換わる、というしかけ。
21~22 行で、全加算器の論理式を記述しています。

テストベンチ

  1. module FULL_ADDER_TEST;
  2.   reg A, B, CI;
  3.   wire S, CO;
  4.   parameter STEP = 1000;
  5.   FULL_ADDER #(0) FULL_ADDER(A, B, CI, S, CO);
  6.   initial begin
  7.     A = 0; B = 0; CI = 0;
  8.     #STEP B = 1;
  9.     #STEP A = 1; B = 0;
  10.     #STEP B = 1;
  11.     #STEP CI = 1; A = 0; B = 0;
  12.     #STEP B = 1;
  13.     #STEP A = 1; B = 0;
  14.     #STEP B = 1;
  15.     #STEP $finish;
  16.   end
  17.   initial begin
  18.     $dumpfile("fullAdder_test.vcd");
  19.     $dumpvars(0, FULL_ADDER_TEST);
  20.   end
  21. endmodule

テストベンチは、基本的に変わってはいません。
が、8 行目。回路のインスタンス化のパラメータ割り当てで 0 を指定しています。論理ゲートを組み合わせた回路でシミュレーションします。なお、test_type のデフォルトが 0 ですから、指定しなければ組み合わせ回路でのシミュレーションになります。
パラメータ割り当てを「1」とすると、論理式によるシミュレーションに切り換わります。

シミュレーション結果

test_type = 1 論理式によるシミュレーション

図 5. 論理式によるシミュレーション結果

図 5 が、論理式によるシミュレーション結果です。

真理値表どおりの出力がえられています。論理式に間違いはないようです。

test_type = 0 論理回路によるシミュレーション

図 6. 論理回路によるシミュレーション結果

図 6 は、論理ゲートで組み立てた回路によるシミュレーション結果です。

こちらも、真理値表どおりの結果がえられています。組み合わせ回路にも間違いはないようです。
論理式によるシミュレーションとの違いは、内部信号の Y1、Y2、Y4 の波形が表示されているところです。

ということで、論理ゲートで組んだ全加算器の回路の動作と、真理値表から求めた論理式は、一致することが確認できました。

後記

さてさて、しかし 1 ビットを加算してみてもつまんないですね。せめて 4 ビットぐらいないと計算したって感じにならない。

ということで、次回は、4 ビット加算器をつくってみましょう。半加算器だ全加算器だなんてややこしいこと言ってないで、ぜんぶ全加算器でつくりゃいいでしょ? 1 桁目は Ci=0 にしときゃいいんだから。

タイトルとURLをコピーしました