2026-10-30

コンピューターシステムの理論と設計 ~第一章 Nandひとつから、 すべてが始まる~

最近、低レイヤーに興味があり、『コンピュータシステムの理論と実装』(通称 nand2tetris)を読み進めています。 今回は第1章「Nandひとつから、すべてが始まる」で学んだことと、そこから興味が広がって調べた半導体の世界についてまとめてみました。

課題は nand2tetris の Web IDE で解いていて、ブラウザだけで回路を書いてテストまでできるので手軽に始められます。

Nandとは

Nandは Not + And を縮めたもので、「Andして、そのあとNotする」という意味です。つまりAndの結果をひっくり返したものになります。

abAndNand
0001
0101
1001
1110

両方が1のときだけ0になる、というシンプルな関数ですが、Nandだけでどんな論理回路でも作れるというのがこの章のポイントです。

Nandから作った15個の関数

第1章では、Nandを材料にして15個のチップ(関数)を作りました。下の表は、それぞれの材料・役割と、JavaScriptで書くとどうなるかを自分なりに整理したものです。

関数材料することJSできること(使う場所)
Nand最初からある両方1のときだけ0!(a && b)すべての関数の材料
NotNandひっくり返す!a−x を作る。ALUの nx, ny, no
AndNand, Not両方1のときだけ1a && b足し算の繰り上がり(carry)。値を通す・止める
OrNot, Andどちらか1つでも1なら1a || bFullAdderで2つのcarryをまとめる
XorAnd, Not, Or違うときだけ1a !== b足し算の右の桁(sum)
MuxNot, And, Orsel で a か b を選ぶsel ? b : aどのデータを使うか選ぶ
DMuxNot, Andsel で in を a か b に流すsel ? {a:0, b:in} : {a:in, b:0}どこにデータを送るか選ぶ
Not16Not × 1616ビットをひっくり返す~xALUの nx, ny, no
And16And × 1616ビットをビットごとにAndx & yALUの x&y
Or16Or × 1616ビットをビットごとにOrx | y16ビットのOr計算
Mux16Mux × 1616ビットの a か b を選ぶsel ? b : aALUで「0にする/しない」「反転する/しない」を選ぶ
Or8WayOr × 78本のどれか1つでも1なら1bits.some(b => b)ALUの zr(結果が0かどうか)
Mux4Way16Mux16 × 34つから1つ選ぶ(sel 2ビット)[a, b, c, d][sel]メモリから読み出す場所を選ぶ(3章)
Mux8Way16Mux4Way16 × 2, Mux168つから1つ選ぶ(sel 3ビット)[a, …, h][sel]メモリから読み出す場所を選ぶ(3章)
DMux4WayDMux × 34つの出口のどれかに流すメモリに書き込む場所を選ぶ(3章)
DMux8WayDMux, DMux4Way × 28つの出口のどれかに流すメモリに書き込む場所を選ぶ(3章)

普段書いている && や ? : が、実はこういう小さな部品の組み合わせでできていると思うと面白いです。また、ここで作った関数の多くは、後の章で作るALU(計算をする部品)やメモリでそのまま使われます。

HDLとは

課題では、これらのチップを HDL(Hardware Description Language) で書いていきます。HDLは、ハードウェアの設計図を文字で書くための言語です。

ここでいう設計図とは「何の部品を何個使って、どこをどうつなぐか」のことで、HDLの1行は「部品を1個置いて、線をつなぐ指示」になります。たとえば、Nandを2つ使ってAndを作るとこう書けます。

1行目のNandで a と b のNandを計算し、その出力 nandOut を2つ目のNandの両方の入力につなぐことで、結果をひっくり返しています(Nandの両方の入力に同じ値を入れるとNotになる)。

プログラミング言語と違うのは、配線図なので行の順番は関係ないという点です。上から順に実行されるのではなく、すべての部品が同時に存在していて、線でつながっているだけ、というイメージです。

実際の回路で動かしてみる

HDLで書いたものが現実ではどうなるのかが気になったので、Tinkercad で実際に回路を組んでみました。

Nandが入ったIC

実際のハードウェアでは、Nandが実装されたICが最初の部品になります。今回使ったのは 74HC00 というICで、14本のピンがついていて中にNandが4つ入っています。

Nand1つには次の3本のピンがあります。

  1. 入力1
  2. 入力2
  3. 出力

これが4つ分で12本、さらに電源用の2本を足して、合計14本のピンになっています。

7400チップの外観と、中にある4つのNandとピンの配置

74HC00と同じピン配置の7400チップです。(画像: Audrius Meskauskas , CC BY-SA 3.0 )

Not関数を作る

Notは、スイッチを1個のNandの入力1と入力2の両方につなぐだけで作れます。

ここでいう「つなぐ」は電気を通すということで、スイッチをONにすると入力1, 2の両方に電気が届くようにします。 両方の入力が1になるとNandの出力は0、スイッチがOFFなら出力は1になるので、入力をひっくり返すNotになります。

スイッチを74HC00のNandの2つの入力につないで、出力をLEDで確認するNot回路

And関数を作る

Andは、HDLで書いたものと同じようにNandを2つ使って作ります。つなぎ方は次の通りです。

  1. スイッチA を、1個目の Nand の 入力1 につなぐ
  2. スイッチB を、1個目の Nand の 入力2 につなぐ
  3. 1個目の Nand の 出力 を、2個目の Nand の 入力1 と入力2 の両方につなぐ
  4. 2個目の Nand の 出力 が、And の答えになる

2つのスイッチを両方ONにするとLEDが光るAnd回路

スイッチを2つともONにしたときだけLEDが光ることを確認できました。HDLの1行が、ブレッドボード上の1本1本の配線に対応しているのが実感できます。

NotやAndは何のために作るのか

このハードウェア上の関数は、電気の流れそのものが計算になっているものです。そして、ソフトウェアが最後に頼る、唯一の「本当に計算する場所」になります。

JavaScriptの関数も、最終的にはこういう回路に電気が流れて計算されています。ソフトウェアは自分で計算しているのではなく、ハードウェアの中にある関数のどれを使うかを 0 と 1 で選んでいるだけなんだな、と感じました。

半導体の世界

ここまで来ると、実際のCPUはどう作られているのかが気になってきたので、少し寄り道して調べてみました。

CPU

CPUにはNandが数百万個入っていて、1枚のシリコンの板の上に、トランジスタも配線も全部まとめて焼き付けて作られているそうです。

この動画 が分かりやすかったです。とんでもなく精密に作られていて驚きました。

まとめ

Nandひとつからコンピュータの部品を組み立てていく第1章でしたが、そこから半導体のビジネスやNVIDIAの話まで興味が広がって、いろいろ面白いことを知ることができてすごく良かったです。 次の章以降も引き続き進めていこうと思います。

参考資料

Thanks for the visit Nozo Blog