100日後に完成するCPU 作業メモ
モチベーション
目次
Week 1
- Day 1 logisim-evolutionのインストール
- Day 2 ANDゲート、ORゲートの動作を試してlogisimに慣れる
- Day 3 真理値表の確認と回路の自動生成
- Day 4 組合せ回路 - 桁上がりを考慮しない半加算器を作ってみよう
- Day 5 組合せ回路 - 4 bitの加算回路を作ってみよう
- Day 6 組合せ回路 - 3 bit加算回路と10進数の7セグLED表示で簡易電卓に仕上げる
- Day 7 順序回路の導入 - Dフリップフロップに挑戦
Week 2
- Day 8 順序回路 - SRラッチ、DラッチからDフリップフロップまでをおさらい
- Day 9 組合せ回路+順序回路 - 3bit加算回路の電卓にメモリ機能を加える
- Day 10 命令セット (ISA) に想いを馳せる
- Day 11 ADD, NOP 2命令を持つCPUみたいなものができた
- Day 12 レジスタ2つの入出力を、マルチプレクサで切り替える (失敗)
- Day 13 2つの命令、4つのステップで「111-11」の引き算をする
- Day 14 プログラムの手動実行から自動実行へ - ROMの仕組みを知ろう
Week 3
- Day 15 ROMにプログラムを書き込み、カウンタと接続する
- Day 16 プログラムを自動実行するには - 「111-11」を永遠に計算し続ける機械
GitHub
- TBD
参考文献、書籍
- 動かしてわかる CPUの作り方10講
- Build an 8-bit computer from scratch
- CODE - コードから見たコンピュータのからくり
- RISC-VとChiselで学ぶ はじめてのCPU自作 --オープンソース命令セットによるカスタムCPU実装への第一歩
- コンピュータの構成と設計 MIPS Edition 第6版 上・下電子合本版
- grself/CIS221_Lab_Manual: This is the Logisim-Evolution lab manual I use with my Cochise College CIS 221 Digital Logic class.
- Visual 6502 Remix
YouTube
Day 1 logisim-evolutionのインストール
Day 2 ANDゲート、ORゲートの動作を試してlogisimに慣れる
Day 3 真理値表の確認と回路の自動生成
Day 4 組合せ回路 - 桁上がりを考慮しない半加算器を作ってみよう
Day 5 組合せ回路 - 4 bitの加算回路を作ってみよう
加算器の派生として、ALUに入る前に、1の補数やそれを作る回路に触れておきたい。
(CODE 第1版 13章参照)
Day 6 組合せ回路 - 3 bit加算回路と10進数の7セグLED表示で簡易電卓に仕上げる
7セグメントLEDデコーダは、logisimで真理値表から論理回路を自動生成する機能を使って作った。
真理値表はせっかくなのでと手打ちしてみた。これをtxtファイルとしてlogisimにインポートできる。
# Truth table
# 4 bit to 7 segment display
d c b a | A B C D E F G
~~~~~~~~~~~~~~~~~~~~~~~
0 0 0 0 | 1 1 1 1 1 1 0
0 0 0 1 | 0 1 1 0 0 0 0
0 0 1 0 | 1 1 0 1 1 0 1
0 0 1 1 | 1 1 1 1 0 0 1
0 1 0 0 | 0 1 1 0 0 1 1
0 1 0 1 | 1 0 1 1 0 1 1
0 1 1 0 | 1 0 1 1 1 1 1
0 1 1 1 | 1 1 1 0 0 0 0
1 0 0 0 | 1 1 1 1 1 1 1
1 0 0 1 | 1 1 1 1 0 1 1
1 0 1 0 | 1 1 1 1 1 1 0
1 0 1 1 | 0 1 1 0 0 0 0
1 1 0 0 | 1 1 0 1 1 0 1
1 1 0 1 | 1 1 1 1 0 0 1
1 1 1 0 | 0 1 1 0 0 1 1
1 1 1 1 | 1 0 1 1 0 1 1
視認性のため、入力を d, c, b, a と並べたがこれでよかったかどうか。
最初は4bit加算回路と対応する7セグメントLED 多桁表示をするつもりだったけど、10の位を簡易に 0,
表示切り替える以上の時間が取れなかったので、3bit加算回路にしておいた。
Day 7 順序回路の導入 - Dフリップフロップに挑戦
クロック立ち上がり時の入力が保持されます。ただ立ち上がり、立ち下がりといった状態遷移以外でも出力が変化してしまっているようです。これで正しいのかな。
ここの問いは、クロックをパルスで供給していなかったため、振る舞いとしては正しかった。
ただ、CPUとして使う際にはパルスとして供給するべきだった。Day 8を参照。
クロックを動かしてのシミュレーション開始には、左から1番目、3番目のボタンを押す。
Day 8 順序回路 - SRラッチ、DラッチからDフリップフロップまでをおさらい
Day 7からはいよいよ順序回路に入った。
ラッチ、フリップフロップの理解があいまいなまま、なんとなくDフリップフロップらしいものを作ろうとしてしまったので、Day 8でおさらいすることに。
ブレッドボード 8bit CPU製作者のBen Eater氏のチュートリアルを見返す。今後の設計指針に、他も参考に見返しておきたい。
また発振回路やラッチ、フリップフロップにおいて、「出力を入力に戻すという形態」で、「各ゲートの動作時間」をうまく使っていることをおさえておきたい。
logisimの Simulate > Timing diagram
で見られるタイミングチャートは、複数のLogging Modeがある。 Continuous real-time mode
にすると、クロックのパルス間で入力を変化させた時の様子も観察できる。
Day 9 組合せ回路+順序回路 - 3bit加算回路の電卓にメモリ機能を加える
CODE - コードから見たコンピュータのからくり 第1版 (2003/4/14) のp.214から着想しました。
回路図を書き出す
logisim-evolutionのメニューから、 File > Export Image
で回路図を書き出してみる。
Half Adder
Full Adder
7 Segment LED Decoder
3-bit Adder with Storage Registers and 7 Segment LED
Day 10 命令セット (ISA) に想いを馳せる
4-bit CPU TD4
『CPUの創りかた』(https://amzn.to/49OKQVK) が初出、自作例が多くネット上にあり、最近では『作ろう! CPU』(https://amzn.to/49rt3nv) に取り上げられています。
8-bit CPU P08
Qiita記事『コンピュータの動作原理』(https://qiita.com/niQSun/items/4d92eab8cce210db4b77) に見つけました。
MIPS
『コンピュータの構成と設計』 (https://amzn.to/439sFbj) いわゆるパタヘネ本の第6版MIPS Editionで詳解。
RISC-V (RV32I)
『RISC-VとChiselで学ぶ はじめてのCPU自作』(https://amzn.to/3SPe8N7) がドンピシャです。
Day 11 ADD, NOP 2命令を持つCPUみたいなものができた
Day 12 レジスタ2つの入出力を、マルチプレクサで切り替える (失敗)
ADD A, im(任意の数a)
INV B, A
ADD B, 1
ADD B, im(任意の数b)
としたら、aの2の補数が取れて、それをbに加算することでb-aが計算できるのでは? と考えたけれど、そこまでは到達できなかった。
エラーの原因が回路の問題か、logisim自体のシミュレーションの問題なのか切り分けが必要。
エラーの理由が分かった。Dフリップフロップで作ったレジスタA、レジスタBに常にクロックを供給していたので、手前のデマルチプレクサの切替えで信号が来ていない時にも、レジスタの書き換え (入力が0なのでリフレッシュ) していた。
クロック供給も、デマルチプレクサの切替えに同期して、有無を制御すれば直る。
INV、ADD 2つの組合せ回路、A、Bの2レジスタを持ち、即値を与えることもできるとすると、
INV A, B
INV B, A
ADD A, im # A = A + im だけでなく A = B + imも可能
ADD B, im # B = B + im だけでなく B = A + im も可能
MOV A, B
MOV B, A
の少なくとも6命令が与えられることになる。
そして、命令、Distination Operand、Source Operandそれぞれを1 bitで指定しているので、
INV A, B # 001
INV B, A # 010
ADD A, im # 100
ADD B, im # 111
MOV A, B # 101 (im = 0)
MOV B, A # 110 (im = 0)
こうした3bitの命令とオペランド指定となる。
Day 13 2つの命令、4つのステップで「111-11」の引き算をする
以下4つの命令を実行した。
ADD A, A, 0011
INV B, A
ADD A, B, 0001
ADD A, A, 0111
ビット列とすると以下になる。
1 0 0 0011
0 1 0 0000
1 0 1 0001
1 0 0 0111
Day 14 プログラムを自動実行するには - ROMの仕組みを知ろう
Day 15 プログラムを自動実行するには - ROMにプログラムを書き込み、カウンタと接続する
以下4つの命令に加え、何もしない (0を足す) 命令を4ステップ埋めると良さそう。
ADD A, A, 0011
INV B, A
ADD A, B, 0001
ADD A, A, 0111
ADD A, A, 0000
ADD A, A, 0000
ADD A, A, 0000
ADD A, A, 0000
ビット列とすると以下になる。
1 0 0 0011
0 1 0 0000
1 0 1 0001
1 0 0 0111
1 0 0 0000
1 0 0 0000
1 0 0 0000
1 0 0 0000
ただ、これで実行すると2周目にずれる。レジスタAに初期値があるため。それらをリセットするために以下とする。
ADD A, A, 0011
INV B, A
ADD A, B, 0001
ADD A, A, 0111
ADD A, A, 0000
ADD A, A, 0000
ADD A, A, 0000
ADD A, A, 1100 #レジスタAを0000にリセットするため、1100+100=10000で桁溢れさせている
ビット列とすると以下になる。
1 0 0 0011
0 1 0 0000
1 0 1 0001
1 0 0 0111
1 0 0 0000
1 0 0 0000
1 0 0 0000
1 0 0 1100
Day 16 プログラムを自動実行するには - 「111-11」を永遠に計算し続ける機械
いきあたりばったりに作ってきたけれど、 4bit TD4と32bit RISC-V RV32Iの実装の比較 #Verilog - Qiita から引用する以下ブロック図から見ると、TD4レベルでは、一定のコンポーネントが実装できている。
次の方向性のひとつは、4bit CPUの自作に挑戦! - DENKIグループ★電子工作ブログ★に倣って、RAMの追加、RAMとI/Oの括り付けなどだろうか。