「CPUの創りかた」の要約を書いてみた

https://www.amazon.co.jp/CPUの創りかた-渡波-郁/dp/4839909865
この本の要約を書くことで、知識をアウトプットしようと思います。おかしい点があれば、コメントしていただけると幸いです。
<h2>回路で使う代表的な装置</h2>
回路で使う代表的な装置を紹介します。
<h3>抵抗</h3>
[1/4w][1/2w]みたいな型がある。±5%くらいの誤差がある。
<h3>コンデンサ</h3>
多くの種類があるが、今回は2種類を紹介
<h4>セラミックコンデンサ</h4>
応答速度は速いが、容量が小さい。電力の1次キャッシュ？的にICの近くに配置したりする。
<h4>電解コンデンサ</h4>
応答速度は遅いが、大きな容量が安価に得られる。極性（プラスとマイナス）があり、これを間違えると破裂する。耐えられる電力も物によって異なる。
<h3>ダイオード</h3>
電気が一方通行でしか流れない。
<h3>IC</h3>
ごく小さな板に多くのトランジスタ・ダイオードなどを組みこんだ、電子回路の素子。集積回路。
<h3>テスター</h3>
アナログとデジタルがある。アナログテスターは応答速度が速い。
テスターの針は電磁石で動く。だから電流が流れると針が動く。そこから電圧に変換。
テスターの内部に抵抗が入っており、I=E/Rというオームの法則により、電流がわかれば電圧も測れる。
高級なテスターは抵抗がデッカい→そのおかげで誤差が小さくなる。（p30参照）
<h2>LED</h2>
豆電球は点灯中と消灯時で抵抗値が異なる。
電力（電流＊電圧）は電球内で熱エネルギーに還元されて、発光する。
豆電球には抵抗があるが、LEDには抵抗がない。だからI=E/Rより5Vの電源に繋げるとすると、I=5/0＝∞となり、ショート。これの解決策としては、回路に抵抗を付け加えるというものがある。
LEDは抵抗を持たないが、電流が流れると電圧を下げるという仕組みがある（低下した電圧を順電圧という）。この順電圧は流れる電流の量によらずほぼ一定。
順電圧よりも電圧の低い乾電池を使うと、電流は流れない。
<h3>抵抗の消費電力の計算</h3>
P=I*E（電力＝電流＊電圧）とI=E/R
より
P=R*I*I
となり、抵抗の消費電力が決まる。消費電力が高すぎると抵抗の温度が上がりすぎて焼け壊れるから注意。
<h2>デジタル回路の基礎の基礎</h2>
ICは主に汎用ICと専用ICに分けることができる。
汎用ICと専用ICの関係はジャガイモとレトルトカレーのような関係。ジャガイモの方がプリミティブだから、カレー以外の材料にも使える（汎用的）。レトルトカレーはカレー以外にはならないが、簡単にカレーを完成させることができる。
<h3>汎用IC</h3>
NANDゲート：2つの入力が両方Hの時、出力がLになる。
汎用ICはこのような基本ゲートやその組み合わせがいくつか入ったもの。
電圧が高いをH,低いをLと記述する（逆もある）。
Hに1を割り当てている場合を生論理、Lに1を割り当てている場合を負論理という。
<h3>簡単な論理回路</h3>
・NOT（論理反転）：入力を論理反転して出力する。
ICに動いてもらうためには電源に繋げる必要がある（意外と忘れがち）。
・AND（論理積）：入力が両方Hの時にだけHが出力される。それ以外はLが出力。
・OR（論理和）：入力のどちらかがHであればHを出力。（入力が両方Lの時だけ出力がLになる。）
・NANDゲート：2つの入力が両方Hの時、出力がLになる。
・多入力ゲート：入力が3つ以上あるもの（いろんな種類がある）
<h3>実際の回路</h3>
Hを入力するにはもちろん電源へ接続しないといけないが、Lを入力するにも0V(GND)に接続しないといけない。そうしないとゴミとかで微量な電流が流れておかしくなる。
使わないゲートもGNDか5Vに繋げておかないと、おかしくなるから注意。
ICは静電気に弱いから、自分の体に静電気を溜めないように注意。
ICはHとLの切り替えの時に電力を消費するが、この出力のスイッチングのスピードが早すぎて、電源からの電力の切り替えが追いつかない（電源とICが数十センチ離れているから）ので、ICの超近くにコンデンサを設置しておく。これにより電力の供給が間に合う。
<h2>リセットとクロック回路</h2>
<h3>クロック</h3>
クロックはHとLを超高速で出力する。早すぎてテスターでは追えない。
スイッチを切り替える時に一瞬5vにもGNDにも繋がってない瞬間が訪れる。どこにも繋がっていないと不具合が起きるので、clock信号を5vに繋いでおく。（p86）
スイッチというのは内部の接点同士が接触してONになるわけだが、この際に激しくバウンドする。バウンドが起きると、本当はクロックを一回出したいだけなのに、3回クロックがきたとCPUが誤解してしまったりする（チャタリング）。パソコンのキーボーとかでもこのチャタリングが起きている。
チャタリングの対策としては、コンデンサを間に挟むことで、電圧の上昇スピードを緩やかにするというものがある（電圧の下降スピードも同じようにゆっくりになる）。
ただこうして、電圧の変化スピードを緩やかにするとHとLの狭間な瞬間が生まれてしまう。しかしシュミットトリガインバータというICを使えば、中途半端な電圧の時も安定して作動する。
<h3>リセット</h3>
コンピュータは電源投入時にもリセットする必要がある。
仕組みはクロックと一緒でコンデンサを使う。
<h3>クロックジェネレータ</h3>
1Hzは1秒に1回
コンデンサを入れることで電圧が0→2.5（HとLが切り替わる）→7.5→-2.5→2.5・・・と入れ替わる。（p105）
<h2>ROMを作る</h2>
ROM=Read Only Memory。不揮発性（電源が入ってなくても記憶を保持できる）
PCのBIOS（OSの起動や、PCと接続機器間の入出力を制御するプログラム）がROMに格納されている。
本当はROMはリードオンリーじゃない方が良い(OSのアップデートとかあるから)が、かつては不揮発性のメモリといえばROMしかなかったという背景がある。
ROMに対してn番地のデータをくれというと、その番地のデータだけを取り出してくれる。
ROMのデータを取り出すためのスイッチもICで作れる（p126）。（求めたいところだけLを出力すれば良いだけ）
<h2>CPUの設計準備</h2>
<h3>命令フォーマット</h3>
今回は8bitで構成されている。上位4ibtがオペレーションコード。下位4bitがイミディエイトデータ。オペレーションコードは「Aレジスタに書き込む(転送)」みたいなやつで、イミディエイトデータが実施に書き込む（転送する）値。
<h3>機械語とは</h3>
4bitということは0~15を扱うことができる。
今回はAとBの2つのレジスタを持つ。それぞれのビットには番号が割り振られていて、上から順にbit3,bit2,bit1,bit0。0100という命令はbit2が1ということになる。
イミディエイトデータが不要の時は0000とする。
「MOV A,1001（Aレジスタに1001を転送）」「ADD A,1001（Aレジスタに1001を加算）」はアセンブラで書かれたプログラムの一例。
ROMの0番地から順番に実行したい命令を書き込んでいけば良い。
クロックが供給され続ける限り、CPUは例え2番地までしかちゃんとした命令を書き込んでなくても、次の命令（3番地、4番地・・）を実行しようとする。これを止める必要がある。そのためにはジャンプ命令を書き込んでおけば良い。2番地までの命令を実行して欲しいなら、3番地にジャンプ命令（「JMP 0011」0011が３番地を表す）を書き込めば、永遠に3番地で無限ループを繰り返してくれる。
9+7をしようとすると答えは2進数で10000となり、これは4bitに収まらないので、レジスタには下4桁の0000だけが書き込まれる。これの対策として繰り上がり(キャリー）を示すCフラグを用意する。繰り上がりが発生したら1をCフラグに書き込むことにし、繰り上がりが発生するまでは永遠にn番地の指示を繰り返すみたいなこともできるようになる。（p154）
<h3>プログラムカウンタ</h3>
現在実行している命令の番地を記録しているのがプログラムカウンタ。命令を実行するたびにカウンタは＋1される。CPUをリセットするということは　プログラムカウンタをリセットすること。
<I/O>
Input or Outputのこと。
入力ポートは4bit分あり、ここにスイッチを4つ繋げることで0010みたいな値をレジスタに転送することができるようになる。出力ポートにも4bit分あり、レジスタの0010みたいな値を出力ポートに転送することでその値に合わせてLEDが点灯する。
<h2>1bitCPU</h2>
<h3>フリップ・フロップ</h3>
フリップ・フロップは簡単にいうとメモリー。フリップフロップ1つで1bit、つまり1か0を記憶できる。フリップ・フロップはクロックにつながっており、クロックがLからHに立ち上がる瞬間にデータをキャプチャし、キャプチャしたデータは次にクロックがLからHに変化するまで変わらない。（p160）
フリップフロップの値はクロックが押されるたびに変化する。レジスタはフリップフロップで構成するわけだが、クロックが押されるたびに値が上書きされてしまうと困る。（レジスタは値をメモするためのものだから）対策として、フリップフロップに自身の出力をキャプチャさせる（p165）。これだけだと自分の値を永遠にキャプチャし続けるだけだから、自分の値or自分の値を論理反転した値のどちらキャプチャするか選べるようにする。
<h2>ALUとプログラムカウンタ</h2>
ALUは演算回路
半加算器と全加算器の違いはこの記事を参照に
https://www.seplus.jp/dokushuzemi/fe/fenavi/mastering_tech/digital_logic/
ここまでの話ですでに転送系の命令はすでに実行できるようになってるから、あとはこれに演算命令を追加するだけ。
データセレクタの仕組み（p202）。
<h3>フラグ</h3>
フラグは条件分岐(15以下ならAを実行し、以上ならAをスキップetc)と関わりがある。
加算で発生した繰り上がりがキャリー。キャリーを記録するのがキャリーフラグ。そしてこのキャリーフラグを見て、後から来た条件分岐命令が命令をジャンプするか決める。
キャリーフラグはキャリーをメモ（記憶）する必要があるので、レジスタと同じくフリップフロップを使う。
<h3>プログラムカウンタ</h3>
フリップ・フロップはクロックの立ち上がりで命令が実行されるわけだから、プログラムカウンタはクロックの立ち上がりで、＋1されれば良い。
リセット信号により、プログラムカウンタはゼロになる。
p215の回路の全体像っぽいのが参考になる。
命令をジャンプしたいときはプログラムカウンタ、ジャンプしたい番地の番号を書き込めば良い（レジスタと仕組みは一緒）。
<h2>命令デコーダ</h2>
指示すべきはSELECT　AとSELECT BとLOAD 0~3（保持または上書き） の6bit分。この指示をオペレーションコードによって行う。Cフラグによってもデータの流れが変わるため、オペレーションコードとCフラグの計5bitから6bitの信号を作り出す回路を用意すれば良い。この回路を命令デコーダという。
<h2>番外編</h2>
クロックの周期が早すぎると、フリップフロップがデータをキャプチャする前に次の信号が来ておかしくなる。