半加算回路は、 1桁の2進数を足し合わせて和と繰り上がりを求められる。
しかし、これだけでは複数桁の足し算はできない。 そこで必要になるのが「全加算回路」である。
本記事では、全加算回路について論理式から解説する。 真理値表を機械的に埋めるのではなく、直感的な理解を提供する。
半加算回路では足りない
2進数において、下の桁からの繰り上がりを考慮した足し算を考えたい。
下の桁から入ってくる繰り上がりをCarry inと呼び、\(C_{\mathrm{in}}\)で表す。 また、その桁から上の桁へ出ていく繰り上がりをCarry outと呼び、\(C_{\mathrm{out}}\)で表す。
「全加算回路」は、その桁の2つの入力A・Bと \(C_{\mathrm{in}}\)の3入力を受け取り、和Sと\(C_{\mathrm{out}}\)の2つを出力する回路である。
全加算回路の真理値表
入力のオンの数でSと\(C_{\mathrm{out}}\)を整理すると以下となる。
- 0個なら、和は0で繰り上げなし
- 1個なら、和は1で繰り上げなし
- 2個なら、合計は2進数で10(2)なので、和は0で繰り上げあり
- 3個なら、合計は2進数で11(2)なので、和は1で繰り上げあり
これを真理値表にまとめると以下となる。
| A | B | \(C_{\mathrm{in}}\) | S | \(C_{\mathrm{out}}\) |
|---|---|---|---|---|
| 0 | 0 | 0 | 0 | 0 |
| 0 | 0 | 1 | 1 | 0 |
| 0 | 1 | 0 | 1 | 0 |
| 0 | 1 | 1 | 0 | 1 |
| 1 | 0 | 0 | 1 | 0 |
| 1 | 0 | 1 | 0 | 1 |
| 1 | 1 | 0 | 0 | 1 |
| 1 | 1 | 1 | 1 | 1 |
入力が3つあると、23=8通りの組み合わせがあって、 なかなかイカツイ見た目である。
どうすれば、Sと\(C_{\mathrm{out}}\)をAとBと\(C_{\mathrm{in}}\)を用いて表現できるだろうか。
半加算回路を2つ組み合わせる
半加算回路は下位の繰り上げを扱えないが、 2つの入力に対する和と繰り上げCを以下のように表現できた。
$$ \begin{aligned} S_1 &= A\oplus B \\ C_1 &= A\land B \end{aligned} $$
半加算回路を2つ組み合わせることで、全加算回路が作れそうな気がしないだろうか。
そこで、全加算回路の入力A,Bを1つ目の半加算回路に入力する。 すると、和\(S_1\)と繰り上げ\(C_1\)の出力が得られる。
まだ下位の繰り上げ\(C_{\mathrm{in}}\)を加味できていないので、 2つ目の半加算回路にその桁の途中の和\(S_1\)と\(C_{\mathrm{in}}\)を入力する。
$$ \begin{aligned} S_2 &= S_1 \oplus C_{\mathrm{in}}\\\\ C_2 &= S_1 \land C_{\mathrm{in}} \end{aligned} $$
\(S_2\)はその桁の和\(S_1\)に下桁からの繰り上げ足したものであり、その桁の最終的な和となる。
2つの繰り上がりをORでまとめる
では、上桁への繰り上げ\(C_{\mathrm{out}}\)はどうなるか。
今、上桁への繰り上げが二種類ある。
- その桁を足すことで生じる上桁への繰り上げ\(C_1\)
- その桁の和\(S_1\)に下桁からの繰り上げ\(C_{\mathrm{in}}\)を足すことで生じる上桁への繰り上げ\(C_2\)
このどちらか一方でも繰り上げがあるのなら、上桁への繰り上げが起こる。
よって、
$$ C_{\mathrm{out}}=C_1\lor C_2 $$
と書ける。
全加算回路の図
以上で、全加算回路は、2つの半加算回路とOR回路を組み合わせることで実現できると分かった。
入出力を繋いで図を描くと次のようになる。
flowchart LR
A((A))
B((B))
CIN((Cin))
HA1["半加算回路1"]
HA2["半加算回路2"]
OR["OR"]
CIN_PAD[" "]
S_PAD[" "]
S((S=S2))
COUT((Cout))
style CIN_PAD fill:transparent,stroke:transparent
style S_PAD fill:transparent,stroke:transparent
A --> HA1
B --> HA1
HA1 -->|S1| HA2
CIN --> HA2
CIN ~~~ CIN_PAD
CIN_PAD ~~~ HA2
HA1 -->|C1| OR
HA2 -->|C2| OR
HA2 --> S
HA2 ~~~ S_PAD
S_PAD ~~~ S
OR --> COUT
下桁からの繰り上げ\(C_{\mathrm{in}}\)を加味しつつ、 その桁の2つの二進数A,Bを足し合わせる。 その結果、その桁での和Sと上桁への繰り上げ\(C_{\mathrm{out}}\)を出力する。
全加算回路の論理式
その桁の和
まず、その桁に残る和Sの論理式について考える。
AとBだけを足した途中の和は、\(A\oplus B\)である。 ここへ、下の桁からの繰り上がり\(C_{\mathrm{in}}\)を足す。
\(C_{\mathrm{in}}=0\)なら、AとBの和はそのままである。 一方、\(C_{\mathrm{in}}=1\)なら、その桁の和は0から1、または1から0へ反転する。
したがって、
$$ \begin{aligned} S&=S_2 \\ &=S_1\oplus C_{\mathrm{in}}\\ &=(A\oplus B)\oplus C_{\mathrm{in}}\\ &=A\oplus B\oplus C_{\mathrm{in}} \end{aligned} $$
となる。
これは、A・B・\(C_{\mathrm{in}}\)のうち、1である入力が奇数個ならSが1になることを表している。
- 1が0個ならSは0
- 1が1個ならSは1
- 1が2個ならSは0
- 1が3個ならSは1
2つの入力のXORは「どちらか片方」を表した。
この延長で理解しようとすると、2つ連結したXORは「3つのうち1つだけ」と思えるが、そうはならない。 XORを順番に行った結果として、1が奇数個なら1になる。
上桁への繰り上げ
次に、上の桁への繰り上がり\(C_{\mathrm{out}}\)を考える。
AとBが両方1なら、その時点で繰り上がる。 下桁からの繰り上げ\(C_{\mathrm{in}}\)は関係ない。 この条件は\(A\land B\)である。
AとBの片方だけが1なら、\(C_{\mathrm{in}}=1\)のときに合計が2となり、繰り上がる。 この条件は\((A\oplus B)\land C_{\mathrm{in}}\)である。
AとBが両方0なら、\(C_{\mathrm{in}}=1\)でも合計は1なので繰り上がらない。
以上から、2つの繰り上がる条件をORで結ぶと、
$$ \begin{aligned} C_{\mathrm{out}} &=C_1\lor C_2\\ &=(A\land B)\lor(S_1\land C_{\mathrm{in}})\\ &=(A\land B)\lor\{(A\oplus B)\land C_{\mathrm{in}}\} \end{aligned} $$
となる。
つまり、この式は次のように読める。
- AとBが両方1なら、それだけですでに繰り上がる
- AとBの片方だけが1のところへ、\(C_{\mathrm{in}}\)が加わって繰り上がる
AとBが両方1の場合は、初めの項\(A\land B\)によってすでに繰り上がる。 したがって、この論理式全体では、後ろの項にある\(A\oplus B\)を \(A\lor B\)に置き換えても出力は変わらない。 その上で、後ろの項で\(C_{\mathrm{in}}\)をANDで分配することで以下のように変形できる。
$$ C_{\mathrm{out}} =(A\land B)\lor(A\land C_{\mathrm{in}})\lor(B\land C_{\mathrm{in}}) $$
これは、AとB、Aと\(C_{\mathrm{in}}\)、Bと\(C_{\mathrm{in}}\)の いずれかの組が両方1なら、繰り上がることを示している。
複数桁の足し算を全加算回路を組み合わせて実現する
全加算回路を組み合わせることで、複数桁の各桁の足し算を計算できる。
ここでは、3桁の2進数\(101_{(2)}+011_{(2)}\)を計算する。
3桁の数を足すには、全加算回路を3個用意する。 0桁目から順に計算し、各回路の\(C_{\mathrm{out}}\)を 次の上位桁の\(C_{\mathrm{in}}\)へ接続する。
最下位の0桁目には、それより下の桁が存在しない。 そこで、最初の\(C_{\mathrm{in}}\)には0を入力する。
各桁の計算は次のように進む。
| 桁 | A | B | \(C_{\mathrm{in}}\) | S | \(C_{\mathrm{out}}\) |
|---|---|---|---|---|---|
| 0桁目 | 1 | 1 | 0 | 0 | 1 |
| 1桁目 | 0 | 1 | 1 | 0 | 1 |
| 2桁目 | 1 | 0 | 1 | 0 | 1 |
0桁目では、\(1+1+0=10_{(2)}\)なので、 その桁に0を残して1を繰り上げる。
1桁目では、0と1に、0桁目からの繰り上げ1を加える。 ここでも合計は\(10_{(2)}\)となり、0を残して1を繰り上げる。
2桁目でも同様に、1と0に、1桁目からの繰り上げ1を加える。 その桁に0を残し、最後の繰り上げ1が新しい最上位の桁となる。
したがって、3個の全加算回路が出力した \(C_3,S_2,S_1,S_0\)を上位から並べると、
$$ 101_{(2)}+011_{(2)}=1000_{(2)} $$
となる。
このように、下位桁の\(C_{\mathrm{out}}\)を上位桁の \(C_{\mathrm{in}}\)へ順番に渡せば、同じ全加算回路を並べるだけで桁数を増やせる。 繰り上がりが波紋のように下位桁から上位桁へ伝わるため、 この構成を「リップルキャリー加算回路」と呼ぶ。
結び
全加算回路は、3つの入力の合計を「その桁に残す値」と「次の桁へ送る値」に分ける回路である。
さらに、繰り上がりを上位桁の全加算回路へ渡すことで、複数桁の足し算へ拡張できる。