
4ビット加算器をPythonで組む|全加算器を連ねてALUの入口へ
2026-09-16 ・ 実践
NANDから全加算器を作りました。次はそれを連ねて4ビットの足し算にします。これがCPUの演算器(ALU)の入口。桁上がりが波のように伝わる「リップルキャリー加算器」をPythonで組み、その弱点まで理解します。
準備
Python標準機能だけ。
① 全加算器を用意(前回の復習)
def full_adder(a, b, cin):
s = a ^ b ^ cin # 和
cout = (a & b) | (b & cin) | (a & cin) # 桁上がり
return s, cout
② 4ビット加算器:桁上がりを次へ渡す
下の桁の桁上がり(cout)を、上の桁の桁上がり入力(cin)へ繋いでいきます。
def adder4(a, b):
# a, b は4ビットのリスト(下位ビットが先頭)
result = []
carry = 0
for i in range(4):
s, carry = full_adder(a[i], b[i], carry) # 桁上がりを引き継ぐ
result.append(s)
return result, carry # 4ビットの和 と 最上位の桁上がり
def to_bits(n): return [(n >> i) & 1 for i in range(4)]
def to_int(bits): return sum(b << i for i, b in enumerate(bits))
a, b = 6, 5
s, cout = adder4(to_bits(a), to_bits(b))
print(f"{a} + {b} = {to_int(s)} (桁上がり {cout})") # 6 + 5 = 11
③ 全パターンで検算
ok = True
for a in range(16):
for b in range(16):
s, cout = adder4(to_bits(a), to_bits(b))
if to_int(s) + (cout << 4) != a + b:
ok = False
print("4ビット加算器 全256パターン:", "OK" if ok else "NG")
OK。全加算器を4つ繋ぐだけで4ビットの足し算が完成しました。8ビット・64ビットも同じ要領で伸ばせます。これがALU(演算論理装置)の心臓部です。
桁上がりの伝播が遅い
この方式は、最上位の答えが出るまで「桁上がりが下から上へ順番に伝わる」のを待つ必要があります。64ビットなら64段ぶんの遅延。これがリップルキャリー加算器の弱点で、桁が増えるほど遅くなります。
速い加算器もある
この遅さを解決するのが「キャリー先読み加算器(CLA)」。桁上がりを順番に待たず、まとめて先に計算します。回路は複雑になりますが高速。CPUの実際の加算器は、速度のためにこうした工夫が入っています。「正しく動く」の次は「速く動く」が設計の課題です。
まとめ
- 全加算器を桁数ぶん連ねると多ビット加算器になる
- 下の桁の桁上がりを上の桁へ引き継ぐ(リップルキャリー)
- 全256パターンで正しく動作。ALUの心臓部
- 桁上がりの伝播で遅くなる。高速化にはキャリー先読みなど
もう少し詳しく(背景と理論)
リップルキャリー加算器は、1ビットの全加算器を桁数ぶん連結し、下位の桁上げ(キャリー)を上位へ順に伝播させる最もシンプルな加算回路です1。しかし桁上げが末端まで「さざ波(ripple)」のように伝わるため、遅延がビット数 n に**比例(O(n))し、64ビットともなると加算がCPUの律速になります2。これを解決するのがキャリー先読み加算器(carry-lookahead)**で、各桁の generate/propagate 信号から桁上げを並列に先読みし、遅延を O(log n) に短縮します——面積と速度のトレードオフです3。加算器は ALU の心臓部であり、その遅延がクロック周期の下限を左右するため、フリップフロップのタイミング制約と直結する重要な設計対象です。
次の一歩 🌸
土台のNANDから全加算器、順序回路はフリップフロップ、論理の基礎は論理回路のしくみへどうぞ。