ブレッドボードで作る 8bit CPU のキットを組み立てました

# はじめに

Build an 8-bit computer from scratch
https://eater.net/8bit

の動画をみながら、[専用のキット](https://eater.net/8bit/kits) を組み立てて CPU の勉強をしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/a8954b99-7c8a-a959-4b36-4e3600b6cafa.png)

![8bit.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13867/076bd798-7882-f3eb-de29-6a614de67470.gif)

<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

## 動機

ソフトウェアのプログラミングのお仕事を25年くらいしています。直近15年くらいはいわゆる **組み込み系** が中心だったのですが、組み込み系の中ではかなり高レイヤーに位置する **ユーザーインターフェース** が専門で、OS とかコンパイラとかハードウェアは僕に取っては **動いていて当然のもの** でした。

少し前に [基礎から学ぶ-組込みRust](https://amzn.to/4aTyE5Z) を読んで、Rust やマイコン自体やマイコンでのプログラミングに触れたことで、（僕からみた）低レイヤーに興味を持ち、色々勉強をはじめ、簡単な回路を設計し、カスタム基板を作成し、 [朝の待ち合わせ用の簡易的な時計](https://qiita.com/task_jp/items/5a35bd27ef3d556ab093) を自分で作れるようになったりしていました。

その流れで、会社の同僚が紹介してくれたのが前述の Ben Eater の「8-bit computer」で、最初は YouTube の動画をひたすら見ていたのですが、見れば見るほど作りたくなってしまい、せっかくなので公式のストアからキットを買い（たった数日で届きました！）、自分で組み立てることにしました。

## 得たもの

- CPU を構成する基礎的な電子部品や電子回路の知識
- ロジックICや様々なIDの知識
- 基本的な CPU の設計や構成
- 簡単なアセンブラの知識

# クロックモジュールの作成 - [Clock module](https://eater.net/8bit/clock)

## 555 タイマーでクロック信号を作る

https://www.youtube.com/watch?v=kRlSFm519Bo

[555タイマー](https://ja.wikipedia.org/wiki/555_%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC) というタイマーICの [無安定モード](https://ja.wikipedia.org/wiki/555_%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC#%E7%84%A1%E5%AE%89%E5%AE%9A_(Astable)) を利用して、CPU のクロック信号を作っていきます。

555タイマーの内部構造の解説を聞きながら、無安定モードの回路をブレッドボード上に作成し、LED を点滅させることができました。

https://x.com/task_jp/status/1785220071843045720/video/1

## シングルクロックボタンを作る

https://www.youtube.com/watch?v=81BgFhm2vz8

ボタンの [チャタリング](https://ja.wikipedia.org/wiki/%E3%83%81%E3%83%A3%E3%82%BF%E3%83%AA%E3%83%B3%E3%82%B0) 対策として、なんとまた555タイマーが登場します。

今回はボタンが押されたときに555タイマーの [単安定モード](https://ja.wikipedia.org/wiki/555_%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC#%E5%8D%98%E5%AE%89%E5%AE%9A_(Monostable)) が機能するように回路を組み立てました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">555でデバウンス対策のやつ <a href="https://t.co/d0CgcKCcNF">pic.twitter.com/d0CgcKCcNF</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785236803584459153?ref_src=twsrc%5Etfw">April 30, 2024</a></blockquote>

## トグルボタンを作る

https://www.youtube.com/watch?v=WCwJNnx36Rk

プッシュ式もしくはスライド式のトグルスイッチを利用して、上記２つの信号を選択できるようにします。

今回も、このスイッチのチャタリング対策として555タイマーを利用します。
３回目は [両安定モード](https://ja.wikipedia.org/wiki/555_%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC#%E4%B8%A1%E5%AE%89%E5%AE%9A_(Bistable)) で、シンプルに555タイマーの中の [SRラッチ](https://ja.wikipedia.org/wiki/%E3%83%A9%E3%83%83%E3%83%81%E5%9B%9E%E8%B7%AF#SR%E3%83%A9%E3%83%83%E3%83%81/%E5%8F%8C%E5%AE%89%E5%AE%9A%E6%80%A7%E3%83%A9%E3%83%83%E3%83%81) を利用する形になります。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">トグルも555（のRSラッチ）で <a href="https://t.co/V6fFymz42e">pic.twitter.com/V6fFymz42e</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785263822707855438?ref_src=twsrc%5Etfw">April 30, 2024</a></blockquote>

## 切り替え機能を作る

https://www.youtube.com/watch?v=SmQ5K7UQPMM

トグルボタンの出力と（反転したものを）自動、手動の出力と AND し、両者を OR して１つの出力にまとめます。将来のために、コンピューターを停止する HLT という入力も追加しておきます

```mermaid
flowchart LR
  Astable([自動クロック回路])--- AND1{AND}
  Bistable([トグルスイッチ]) --- AND1
  Bistable --- INV1{INV}
  INV1 --- AND2
  Monostable([手動クロックボタン]) --- AND2{AND}
  AND1 & AND2 --- OR{OR}
  OR --- AND3{AND}
  HLT([HLT]) --- INV2{INV}
  INV2 --- AND3
  AND3 --- Output([クロック信号])
```

元の動画はクロック信号のところにLEDをつないでいますが、それによってクロックの電圧が下がって困る場合には、以下のように余ってるInverterを２回経由するといいかもしれません。

```mermaid
flowchart LR
  Output([クロック信号]) --- INV1{INV} --- INV2{INV} --- LED
```

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">Kit1 のクロック回路完成！<br>とても綺麗に配線できたと思う。 <a href="https://t.co/7iCkS1euYI">pic.twitter.com/7iCkS1euYI</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785284015689548261?ref_src=twsrc%5Etfw">April 30, 2024</a></blockquote>

# 電子部品の基礎知識 - [Background](https://eater.net/8bit)

本格的にブレッドボードで CPU を作りはじめる前に、基本的な部品のおさらいをしました。

## 半導体とは

https://www.youtube.com/watch?v=33vbFFFn04k

共有結合のシリコン結晶にリン(P)を混ぜたりホウ素(B)を混ぜたりして結晶中を価電子が動くようになって、両者を組み合わせるとダイオードが完成します。

## トランジスタとは

https://www.youtube.com/watch?v=DXvAlwMAxiA

NPN の形で半導体を作ると、トランジスタになります。

## ロジックゲート

https://www.youtube.com/watch?v=sTu3LwpF6XI

トランジスタとスイッチを組み合わせて、以下の回路を作ってみました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">トランジスタを使ったバッファ回路 <a href="https://t.co/3pXmDImzsm">pic.twitter.com/3pXmDImzsm</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785341645061488985?ref_src=twsrc%5Etfw">April 30, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">トランジスタを使ったインバーター回路 <a href="https://t.co/skkd2nzZ1u">pic.twitter.com/skkd2nzZ1u</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785489060632662188?ref_src=twsrc%5Etfw">May 1, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">トランジスタを使った AND 回路 <a href="https://t.co/L1zMhnoeE5">pic.twitter.com/L1zMhnoeE5</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785514540878413972?ref_src=twsrc%5Etfw">May 1, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">トランジスタを使った OR 回路 <a href="https://t.co/Yn3zJmoVZ6">pic.twitter.com/Yn3zJmoVZ6</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785532320767947031?ref_src=twsrc%5Etfw">May 1, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">トランジスタを使った XOR 回路 <a href="https://t.co/9kGFfZj0dE">pic.twitter.com/9kGFfZj0dE</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1785603355617980463?ref_src=twsrc%5Etfw">May 1, 2024</a></blockquote>

## SR ラッチ

https://www.youtube.com/watch?v=KM0DdEaY5sY

トランジスタでロジックゲートを作ったので、モジュール化されたロジックICで次のステップに進みます。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">NORのロジックICを使った SRラッチ 回路 <a href="https://t.co/3Vi24kbhqy">pic.twitter.com/3Vi24kbhqy</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1786640262321889498?ref_src=twsrc%5Etfw">May 4, 2024</a></blockquote>

## D ラッチ

https://www.youtube.com/watch?v=peCh_859q7Q

Set/Reset を、Data/Enable にしてみました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">AND と NOR のロジック IC を使った D ラッチ回路できた <a href="https://t.co/7Xd60ryxnQ">pic.twitter.com/7Xd60ryxnQ</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1787759589972488440?ref_src=twsrc%5Etfw">May 7, 2024</a></blockquote>

## D フリップフロップ

https://www.youtube.com/watch?v=YW-_GkUguMM

Enable のところを [RC回路](https://ja.wikipedia.org/wiki/RC%E5%9B%9E%E8%B7%AF) にして、クロックの立ち上がりの一瞬だけデータを取り込むようにしました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ブレッドボードで D flip-flop を作った。 <a href="https://t.co/xz0QFpdPvI">pic.twitter.com/xz0QFpdPvI</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1787765649676419438?ref_src=twsrc%5Etfw">May 7, 2024</a></blockquote>



# レジスター - [Registers](https://eater.net/8bit/registers)

## バスアーキテクチャ

https://www.youtube.com/watch?v=QzWW-CBugZo

バスと呼ばれる８本の線を複数のモジュールに接続し、モジュール間でデータの共有を行うアーキテクチャで CPU を作ることを学びました。

１つのモジュールがバスにデータを共有し、他のモジュールがそこからデータを読むのですが、ちょっとタイミング関係が難しそうです。


## トライステートロジック

https://www.youtube.com/watch?v=faAjse109Q8

High/Low の他に、接続していないという状態を持てることで、必要のないときはバスには関わらないようにできることを学びました。


## 1bit レジスター

https://www.youtube.com/watch?v=-arYx_oVIj8

D フリップフロップ(74LS74)を利用して１ビットを任意のタイミングでクロックに合わせて保持するレジスター回路の作り方を学びました。

74LS74 他のICがキットに含まれていなかったため、ここの実践はスキップしました。

## 8bit レジスター

https://www.youtube.com/watch?v=CiMaWbz_6E8

[74LS173](https://eater.net/datasheets/74ls173.pdf) という4bitのDレジスターICを２個利用して、8bitのレジスターを作成しました。74LS173には出力にトライステートの機能が用意されていますが、レジスターの中身をLEDで可視化するためにそれは利用せず、別途 [74LS245](https://eater.net/datasheets/74ls245.pdf) を使うことにしました。

## レジスターの動作確認

https://www.youtube.com/watch?v=9WE3Obdjtv0

レジスターモジュールを複数個組み立て、バスを介して8bitデータのやりとりができるようになりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">（左側の）８ビットのバスにハードコードしたデータを、クロックに合わせて（赤の）Aレジスタに保存して、Aレジスタの値をバスに共有して、それを（黄色の）Bレジスタに保存するコード（マジで「コード」）ができたああああ。たくさんのことにハマって、丸２日かかったｗ 電気難しい。 <a href="https://t.co/Y3KWaaHyKA">pic.twitter.com/Y3KWaaHyKA</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788129564184764878?ref_src=twsrc%5Etfw">May 8, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">さらに（インストラクション）レジスタを追加。バス経由でデータの読み書きが自由にできてる。嬉しい。 <a href="https://t.co/PFxwIbNbO0">pic.twitter.com/PFxwIbNbO0</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788185150150656239?ref_src=twsrc%5Etfw">May 8, 2024</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# 演算装置 - [ALU](https://eater.net/8bit/alu)

## ２進数の足し算をロジックゲートで行う方法

https://www.youtube.com/watch?v=wvJc9CZcvBc

XOR で 1bit の足し算ができて、繰り上がりは AND で計算できる（半加算器)。
そこに XOR, AND, OR を追加すると、下からの繰り上がりを考慮した計算もできる（全加算器）。

## 負の数の表現

https://www.youtube.com/watch?v=4qH4unVtJkE

最上位bitを±として使ってみて、１の補数を試して、２の補数にたどりつきます。

## 演算装置の設計

https://www.youtube.com/watch?v=mOVOS9AjgFs

ALU にAレジスターとBレジスターを直接つないで、加算を行う設計にします。
直前に足し算の回路を自作したので、ここでは4bitの足し算を行う [74LS283](https://eater.net/datasheets/74ls283.pdf) を採用し、２個で8bitの計算ができるようにしました。

減算が少々難しいのですが、
1. ２の補数を生成する
2. 加算する
という仕組みで解決します。

２の補数は、ビット反転をして１を足すので、まず XOR でビット反転に対応します。
| 演算フラグ | 入力 | XOR 出力 |
|:---------|:----:|:----|
| 足し算(0) | 0    | 0(そのまま)   |
| 足し算(0) | 1    | 1(そのまま)   |
| 引き算(1) | 0    | 1(反転)   |
| 引き算(1) | 1    | 0(反転)   |

１を足すのは、全加算器のキャリー入力を有効にすることで対応します。

とてもスマートに解決することができました。

## 演算装置の実装

https://www.youtube.com/watch?v=S-3fXU3FZQc

- [74LS283](https://eater.net/datasheets/74ls283.pdf) 4ビット全加算器
- [74LS86](https://eater.net/datasheets/74ls86.pdf) XOR 4つ
- [74LS245](https://eater.net/datasheets/74ls245.pdf) トライステートバッファ

上記を頑張って組み立てます。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ALU を作って、足し算ができるようになった！ <a href="https://t.co/U3tpuFaslF">pic.twitter.com/U3tpuFaslF</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788238612854899055?ref_src=twsrc%5Etfw">May 8, 2024</a></blockquote>

## 演算装置の修正

https://www.youtube.com/watch?v=U7Q8-2YZTUU

１つ前の実装にバグがあったようなので、原因を調査して修正をしました。

低レイヤーのデバッグは難易度が高いですね。

次のステップで、実際に自分の回路にもバグが見つかり同じように修正をすることになりました。

## 演算装置のテスト

https://www.youtube.com/watch?v=4nCMDvnR2Fg

`A = A + B` の計算を演算装置で繰り返すことでテストをしました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">引き算もできてる気がする <a href="https://t.co/baeIP8Ip66">pic.twitter.com/baeIP8Ip66</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788239054531936343?ref_src=twsrc%5Etfw">May 8, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">バグを発見した <a href="https://t.co/dPsKodHsdy">pic.twitter.com/dPsKodHsdy</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788374223079211178?ref_src=twsrc%5Etfw">May 9, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">直した <a href="https://t.co/B77esCm3AQ">pic.twitter.com/B77esCm3AQ</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788376821479993623?ref_src=twsrc%5Etfw">May 9, 2024</a></blockquote>


# RAM - [Random access memory (RAM) module](https://eater.net/8bit/ram)

## RAM の概要

https://www.youtube.com/watch?v=FnxPIZR1ybs

8bit の読み書きができる回路の配列で、インデックスをアドレスと呼び、２進数のアドレスから特定のアドレスを表す信号に変換して特定の場所の記憶装置を有効化しているようです。

レジスタをたくさん並べてもいいのですが、様々な理由で、トランジスタとコンデンサを組み合わせたもので記憶をし、情報が消えないように定期的にコンデンサの充電をする DRAM という方式が一般的なようです。

メモリを自作するのは今回は避けて、 [74189](https://eater.net/datasheets/74189.pdf) という、4bit × 16 = 64bit のメモリICを採用します。
8bit 必要なので、２個使います。

全体で16バイトのRAMになります。

## RAM の実装

https://www.youtube.com/watch?v=uYXwCBo40iA

74189 の出力が反転されているので、74LS04 を２個使って信号を元に戻します。

また、バスとの入出力にまたトライステートバッファ(74LS245)を使います。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">RAMを作った。データ書き込む時の挙動（全部光る）が微妙にお手本と違うんだけどいいのかな。 <a href="https://t.co/uxfkC2WerJ">pic.twitter.com/uxfkC2WerJ</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788450071165759883?ref_src=twsrc%5Etfw">May 9, 2024</a></blockquote>

## RAM のアドレスレジスタ

https://www.youtube.com/watch?v=KNve2LCcSRc

バスからメモリのアドレス(4bit)を取得するための仕組みをAレジスタと同じようにDレジスタIC(74LS173)を使って実装します。

メモリアドレスはバスへの出力はしないため、トライステートバッファは必要ありません。

それから、RAM は手動でも操作するので（プログラミングモード）、DIPスイッチでも操作できるようにします。

切り替えは、[74LS157](https://eater.net/datasheets/74ls157.pdf)というICで行うことにしました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">RAMのアドレス側の対応をした。 <a href="https://t.co/DPhAl3vw0i">pic.twitter.com/DPhAl3vw0i</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788479768750624892?ref_src=twsrc%5Etfw">May 9, 2024</a></blockquote>

## RAM のデータ操作

https://www.youtube.com/watch?v=5rl1tEFXKt0

メモリのアドレスと同じスイッチで手動での書き込みに対応します。
回路もほぼ同じですが、コンピューターの動作時の書き込みはクロック信号と同期して動作する必要があるので NAND を利用して一工夫しています。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">RAM のデータ側の対応をした。 <a href="https://t.co/5ebdutaBw1">pic.twitter.com/5ebdutaBw1</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788602880519451099?ref_src=twsrc%5Etfw">May 9, 2024</a></blockquote>

## RAM の動作確認

https://www.youtube.com/watch?v=Vw3uDOUJRGw

RAM の出力を動画と同じように下位3bitでしか行ってなかったのですが、5bit目と6bit目が入れ替わってしまっていて、私も苦労して原因を特定して修正しました。

また、動画の最後で、メモリの書き込み用の信号を RC 回路に変更してクロックの立ち上がりのエッジのタイミングで書き込むように変更しています。

# プログラムカウンタ - [Program counter](https://eater.net/8bit/pc)

## JK flip-flop

https://www.youtube.com/watch?v=F1OC5e7Tn_o

SRラッチを拡張して、セット／リセットが両方1のときに対応した回路を作成しました。

## レースコンディションの調査

https://www.youtube.com/watch?v=st3mUEub99E

しかし、意図したようには動作しませんでした。

## Master-slave JK flip-flop

https://www.youtube.com/watch?v=rXHSB5w7CyE

SRラッチを２段にして、実用的なフリップフロップを作りました。
富豪的な解決方法ですね。

そして、一旦自分で作ったら、モジュール化されたIC(74LS76)を使うことにするようです。

## バイナリカウンター

https://www.youtube.com/watch?v=exGEmA67dNc

74LS76 を利用すると、クロック信号の倍の周期で切り替わる信号が作れます。
それを並べると、２進数のカウンターになります。

## プログラムカウンターの設計

https://www.youtube.com/watch?v=g_1HyxBzjl0

ジャンプやカウントアップの切り替え機能も実装されているモジュール化されたバイナリカウンターIC([74LS161](https://eater.net/datasheets/74ls161.pdf))を採用します。

バスとのやりとりはここでも 74LS245 を利用します。

## プログラムカウンターの実装

https://www.youtube.com/watch?v=tNwU7pK_3tk

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">プログラムカウンターを作った。<br>LEDに抵抗入れてないせいか最後のとこがちと怪しい。 <a href="https://t.co/D1GtJxl9sH">pic.twitter.com/D1GtJxl9sH</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1788729688611049571?ref_src=twsrc%5Etfw">May 10, 2024</a></blockquote>

# 出力レジスタ - [Output register](https://eater.net/8bit/output)

## 7セグデコーダー

https://www.youtube.com/watch?v=7zffjsXqATg

ロジック回路で0〜Fを7セグの信号に変更してみました。無理。。。

## EEPROM での実装

https://www.youtube.com/watch?v=BA12Z7gQ4P0

[AT28C16](https://eater.net/datasheets/28c16.pdf) という 2K x 8bits の EEPROM を利用して、00~0F に、対応するセグメントのデータを入れます。

EEPROM の動作を学ぶために、データを読み書きする回路を作ってみます。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">EEPROM の手動読み書き回路を作った <a href="https://t.co/IcaC2BuVv8">pic.twitter.com/IcaC2BuVv8</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789128092415619267?ref_src=twsrc%5Etfw">May 11, 2024</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">↑の配線をスッキリさせた <a href="https://t.co/Hds9wmr9Ih">pic.twitter.com/Hds9wmr9Ih</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789153207564042696?ref_src=twsrc%5Etfw">May 11, 2024</a></blockquote>

自分で工夫をして、書き込みデータも DIP スイッチでできて、7セグ表示にも対応してみました。


## Arduino Nano で EEPROM に書き込みをする

https://www.youtube.com/watch?v=K88pgWhEb1M

[Arduino Nano 33 BLE ヘッダー付き](https://amzn.to/3VlZVbw) もしくは互換があるものを利用して、PCでプログラミングしたデータを簡単に EEPROM にかけるようにします。

IOピンの数の関係で、11bit のアドレスをそのままは扱わず、8bitのシフトレジスター(74HC595)を２個利用しています。


<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">Arduino で EEPROM を読み書きする回路を作った <a href="https://t.co/MDMdeIhC37">pic.twitter.com/MDMdeIhC37</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789219264974782662?ref_src=twsrc%5Etfw">May 11, 2024</a></blockquote>

## 3桁の7セグ表示に対応する

https://www.youtube.com/watch?v=dLh1n2dErzE

555タイマーと、JK flip-flop のバイナリカウンタと 74LS139 デコーダーの組み合わせで４桁をそれぞれ高速に表示し、人間の目には残像で４桁とも常に表示されているように見えるという魔法が登場しました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">8bitのデータを数値で表示できるようになった <a href="https://t.co/ozLOn4SNBA">pic.twitter.com/ozLOn4SNBA</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789333902546571392?ref_src=twsrc%5Etfw">May 11, 2024</a></blockquote>

# バスで各モジュールを結合する - [Bringing it all together](https://eater.net/8bit/bus)

出力レジスタがバスからデータを読むために [74LS273](https://eater.net/datasheets/74ls273.pdf) を採用しました。

また、取り込みのコントロールラインとクロックを AND したものを取り込み信号として利用しています。

お手本はバスの８本を中央に並べる形になっていますが、少し工夫をして、CPU 全体で利用する以下のものも並べるようにしました。
- クロック
- ↑を反転したもの
- リセット
- ↑を反転したもの

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">全体を合体してる途中。ワクワクしてきた <a href="https://t.co/16LBRhDx2x">pic.twitter.com/16LBRhDx2x</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789517144285454476?ref_src=twsrc%5Etfw">May 12, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">x -= -1 をし続けるー <a href="https://t.co/KuqXnpsCkP">pic.twitter.com/KuqXnpsCkP</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789529596528111995?ref_src=twsrc%5Etfw">May 12, 2024</a></blockquote>

## コントロールシグナルの概要

https://www.youtube.com/watch?v=AwUirxi9eBg

各モジュールに存在するコントロール線（I/O など)を一ヶ所に集めて操作しやすくします。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">全体をバスで繋いだ <a href="https://t.co/axhIlDFjDc">pic.twitter.com/axhIlDFjDc</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789807671996305783?ref_src=twsrc%5Etfw">May 12, 2024</a></blockquote>

# CPU の制御回路 - [CPU control logic](https://eater.net/8bit/control)

## 命令セット

https://www.youtube.com/watch?v=dXdoim96v5A

8bit のうち、上位4bitを命令コード、下位4bitを引数として命令体系を構築します。

|アドレス|命令/データ|バイナリデータ|
|------:|:-------|---------|
|0000|LDA 14|0001 1110|
|0001|ADD 15|0010 1111|
|0002|OUT   |1110 0000|
|...|||
|1110|28|00011100|
|1111|14|00001110|

## インストラクションカウンター

https://www.youtube.com/watch?v=X7rCxs1ppyY

各CPU命令のマイクロインストラクションを逐次実行するためのカウンターを作成します。

バイナリカウンタ([74LS161](https://eater.net/datasheets/74ls161.pdf))を利用し、クロックをカウントアップするのですが、処理のタイミングを考慮し、クロックを反転してソースとして利用します。

ついでにデコーダー([74LS138](https://eater.net/datasheets/74ls138.pdf))で、各ステップを信号として独立して扱えるようにします。

カウンタ自体は16まで数えられますが、マイクロインストラクションの最大は５なので、
０から４まで数えたらカウンタICのリセットに信号を送るようにします。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">インストラクションのカウンターを作った <a href="https://t.co/3Q86G1ILkF">pic.twitter.com/3Q86G1ILkF</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790021569202303002?ref_src=twsrc%5Etfw">May 13, 2024</a></blockquote>

## インストラクションの実装

https://www.youtube.com/watch?v=dHWFpkGsxOs

EEPROM を利用して、インストラクションカウンターと命令コードをアドレスにとり、コントロール信号をデータとして出力するようにします。
コントロールの信号が15個あるため、EEPROM を２つ利用します。
データピンを個々のコントロール信号線とつないで、自動でマイクロインストラクションが実行されるようにします。
EEPROM の中身は手動で書き込みました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">コントロールのロジックをEEPROMで実装して、RAM上のプログラムを実行できるようになった！ <a href="https://t.co/BhtgkJtXbr">pic.twitter.com/BhtgkJtXbr</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790218470938100008?ref_src=twsrc%5Etfw">May 14, 2024</a></blockquote>

## リセット回路

https://www.youtube.com/watch?v=HtFro0UKqkk

リセットボタンを作成し、反転した信号も作成し、各モジュールのリセット機能と接続しました。

インストラクションカウンターのリセット信号とも連携して動作するようになっています。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">リセットボタンを作って、回路全体をリセットできるようにした <a href="https://t.co/4C7Zf11lbU">pic.twitter.com/4C7Zf11lbU</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790047080804704621?ref_src=twsrc%5Etfw">May 13, 2024</a></blockquote>

後半は全体の電源の話をしていました。

Ben Eater おすすめのブレッドボード BB830 は、[mouser から購入可能](https://www.mouser.jp/ProductDetail/BusBoard-Prototype-Systems/BB830?qs=VEfmQw3KOauhPeTwYxNCaA%3D%3D) です。でも透明のが届くかも。

## Arduino で EEPROM を書き込む

https://www.youtube.com/watch?v=JUVt_KYAp-I

プログラミングでマイクロコードが管理できるようになり、インストラクションを簡単に増やせるようになりました。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">足し算を一回してクロックを止めて、リセットボタンで初めからやり直せるようになった！ <a href="https://t.co/uWG1OVUDe3">pic.twitter.com/uWG1OVUDe3</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790283135974019516?ref_src=twsrc%5Etfw">May 14, 2024</a></blockquote>

## CPU 命令の追加

https://www.youtube.com/watch?v=FCscQGBIL-Y

以下の命令を追加しました

- SUB
- STA
- LDI
- JMP

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ジャンプ命令に対応して、永遠に x+=3 し続けられるようになったよ！ <a href="https://t.co/p2vx2ODEDZ">pic.twitter.com/p2vx2ODEDZ</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790664780547850738?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote>

## チューリング完全にしよう

https://www.youtube.com/watch?v=AqNDk_UJW4k

コンピューターとは、についてのお勉強をしました。

## CPU のフラグを管理するレジスタ

https://www.youtube.com/watch?v=ObnosznZvHY

Carry フラグと Zero フラグを Dレジスタに保持するようにし、保持用のコントロール信号も追加しました。またマイクロインストラクションで利用できるよう、EEPROM にフラグを接続しました。

## 条件ジャンプ

https://www.youtube.com/watch?v=Zg1NdPKoosU

フラグを考慮した形でマイクロインストラクションを書き換え、JC, JZ が利用できるようになりました！

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">JC JZ を実装して、255までカウントアップして、それから0までカウントアップするプログラムが動くようになった！ <a href="https://t.co/WKfIyVWDyJ">pic.twitter.com/WKfIyVWDyJ</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790751313292357869?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote>

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">掛け算のプログラムも動くようになった！<br>8x9=72 あってる！！ <a href="https://t.co/zXl8UMQeMi">pic.twitter.com/zXl8UMQeMi</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790758494301569100?ref_src=twsrc%5Etfw">May 15, 2024</a></blockquote>

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">フィボナッチの計算できた！<br>0: LDI 1 // 1 -&gt; A<br>1: STA 14 // A -&gt; <a href="https://twitter.com/14?ref_src=twsrc%5Etfw">@14</a><br>2: STA 15 // A -&gt; <a href="https://twitter.com/15?ref_src=twsrc%5Etfw">@15</a><br>3: OUT // A -&gt; LED<br>4: ADD 14 // A += <a href="https://twitter.com/14?ref_src=twsrc%5Etfw">@14</a><br>5: JC 13 // HLT<br>6: STA 14 // A -&gt; <a href="https://twitter.com/14?ref_src=twsrc%5Etfw">@14</a><br>7: OUT // A -&gt; LED<br>8: ADD 15 // A += <a href="https://twitter.com/15?ref_src=twsrc%5Etfw">@15</a><br>9: JC 13 // HLT<br>10: JMP 2 // loop<br>...<br>13: HLT // halt<br>... <a href="https://t.co/Q7vOWY3Lxy">pic.twitter.com/Q7vOWY3Lxy</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1790988553310425230?ref_src=twsrc%5Etfw">May 16, 2024</a></blockquote>

# 完成

以上で Ben Eater の 8bit CPU のキットが完成しました。

# 試行錯誤

## フィボナッチ数列の計算を効率よく行おう

11バイトで計算ができるのも十分すごいのですが、上記のコードを書いていたら、
「あれ？SUMレジスタの値を、AレジスタとBレジスタに交互に入れていけば計算できるのでは？」と閃きました。
ということで、フィボナッチ数列の計算のための専用命令を２つ追加し、わずか３バイトで計算ができるようになりました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">１命令でフィボナッチ数列の計算を１つ進めるインストラクションをCPUに実装したら、３バイトのプログラムで超高速に計算ができるようになった。<br><br>0x0: LDI 1<br>0x1: FBB 0x2<br>0x2: FBA 0x1<br><br>ALUの結果をAかBレジスタにいれつつ7セグ出力とジャンプをして、オーバーフロー時には回路が止まる命令すごい。 <a href="https://t.co/oYUnaZNhDd">pic.twitter.com/oYUnaZNhDd</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1791147621823942695?ref_src=twsrc%5Etfw">May 16, 2024</a></blockquote>

## 最大公約数の計算

16バイトでなんとかなるのすごい。

<blockquote class="twitter-tweet" data-conversation="none"><p lang="ja" dir="ltr">ユークリッドの互除法で最大公約数求めるプログラムが16ビットに収まったｗ<br><br>0: LDA E<br>1: SUB F<br>2: JZ B<br>3: JC 9<br>// swap:<br>4: LDA F<br>5: SWP1 E<br>6: SWP2 E<br>7: STA F<br>8: JMP 0<br>// continue:<br>9: STA E<br>A: JMP 0<br>// done:<br>B: LDA F<br>C: OUT<br>D: HLT<br>// data:<br>E: 15<br>F: 9 <a href="https://t.co/fHjysIrdGx">pic.twitter.com/fHjysIrdGx</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1791341822876496062?ref_src=twsrc%5Etfw">May 17, 2024</a></blockquote>

# キット組み立てに利用した道具の紹介

（アマゾンのリンクはアフィリエイトになっています）

## ケーブルの長さを測るやつ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ブレッドボードにちょうどいい長さのケーブルを作成する器具を作った！ <a href="https://t.co/xAX8TRfEBO">pic.twitter.com/xAX8TRfEBO</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1767801469523128411?ref_src=twsrc%5Etfw">March 13, 2024</a></blockquote>

## ブレッドボードの電源ラインをつなぐやつ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">ブレッドボードの±同士を繋ぐのめんどくさくなくするやつつくった <a href="https://t.co/BYsYJhwNzF">pic.twitter.com/BYsYJhwNzF</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1786645283369320763?ref_src=twsrc%5Etfw">May 4, 2024</a></blockquote>

## 抵抗とかコンデンサをブレッドボードにちょうど良く加工しやすくるすやつ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">LEDとか抵抗とかをブレッドボードに差しやすい形にする道具を作った。足の広さを決めて、押し込んで（引っ張って）、カットするとちょうどいい感じになるー <a href="https://t.co/WdOXVaCTxL">pic.twitter.com/WdOXVaCTxL</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1766842450243440699?ref_src=twsrc%5Etfw">March 10, 2024</a></blockquote>

## ロジックテスタ

ロジックテスタを作ってみよう！【MR-LOGIC-TESTER】

https://www.marutsu.co.jp/pc/i/952287/

もっと早く買っておけばよかった。。。

## オシロスコープ

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">とうとう買ってしまったよ。 <a href="https://t.co/oKAKfVQ6Pm">pic.twitter.com/oKAKfVQ6Pm</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1789901087337529429?ref_src=twsrc%5Etfw">May 13, 2024</a></blockquote>

https://amzn.to/3KGFq4G

## ラジオペンチ

ツノダ(Tusnoda) King TTC 先曲りラジオペンチ 125mm RB-125

https://amzn.to/45nbOTf

## ニッパー

ホーザン(HOZAN) 精密ニッパー フルフラッシュカットタイプ 細銅線用 N-55

https://amzn.to/4cdbzfK

## ケーブルストリッパー

エンジニア オートワイヤーストリッパー PAW-41

https://amzn.to/3VDf1Lm

これは超便利です。

## 抵抗内蔵LED

https://akizukidenshi.com/catalog/c/cledinres/

抵抗つなぐのが面倒くさくて、大人買いして遠慮なく使いました。

## ケース

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">最近ブレッドボードで組み立ててたCPU が、こちらの棚板にわりとピッタリ収まったので、とてもいい気分です。<a href="https://t.co/D6cyMtlimr">https://t.co/D6cyMtlimr</a> <a href="https://t.co/3evpv319wp">pic.twitter.com/3evpv319wp</a></p>&mdash; Tasuku Suzuki (@task_jp) <a href="https://twitter.com/task_jp/status/1793267977170923529?ref_src=twsrc%5Etfw">May 22, 2024</a></blockquote>