CPUのしくみ入門
『CPUの創り方』という本がある。
CPUのしくみを理解し、シンプルなCPUをつくりましょう、という本である。
だが文中で著者も言っているように、CPUを自作するにはかなりの配線作業が必要になる。
そこで私は友人@su_exsさんに教えてもらった「源内CAD」というデジタル回路シミュレータを使い、CPUをつくってみることにした。
なお今回の作業では源内CAD支援コンテンツの標準ロジックIC一覧が大変参考になった。この場を借りてお礼です。
まずは源内CADの使用上の注意点。
(1)下位のシミュレーションをしないと、その回路記号を使ったシミュレーションができない
(2)クロック非同期回路でのパターン入力には、遅延を考慮する
(3)削除コマンドの癖。キャンセルしないと大事な回路記号まで削除してしまう
それでは始めて行きましょう。
【書籍160ページ】
まずは単純なフリップフロップから試す。これはCPUのレジスタに使われている素子で、値を保持するのに使われる。
ダウンロード 120324-test01.gdr (0.7K)
まずはフリップフロップ初動作
フリップフロップの動作確認
クロックがHiになるたびにフリップフロップの出力がHiとLoで入れ替わる
【書籍176ページ】
データセレクタ これも作るw
データセレクタ製作中
データセレクタ完成!(うそ。一部未完。)
ダウンロード dataSelector.gdr (2.6K)
シンボルに登録して再利用可能にする
登録して使えるようになった
こちらはデータセレクタ S0とS1がともにLoだと・・・
ダウンロード dataSelector.gdr (2.6K)
このAND素子だけがはたらいて・・・
このI0の入力だけが出力され、他の入力は捨てられる
S0がLo、S1がHiだと・・・
このAND素子だけがはたらくので・・・
入力I2だけが出力に反映されて、あとの入力は捨てられる
【書籍185ページ】
74HC161の回路図 うへえ
ダウンロード 4bitfullAdder0.gpt (0.3K)
ちなみに中身はこんな感じ(@su_exs氏作成)
矢印のか所が全部Hiだと・・・
ここに集まって桁が上がるはずなのだが・・・
ここでGNDで殺しているので桁上がりは起きないです
CLR#がLoだと・・・
これらのAND素子にLoが入力されるので・・・
すべてのフリップフロップにLoが入力されることになります
LOAD#がLoだと・・・
これらのAND素子がはたらいて入力ABCDがフリップフロップに入力される
逆にLOAD#がHiだと・・・
こちら側のAND素子がはたらいて現状の状態を維持する
左から順にABCDにHiをセットしている
左から順にABCDがHiにセットされている
【書籍191ページ】
ダウンロード 120324-RegisterSelecterTest-120326-1700.gdr (10.0K)
ダウンロード 120324-test04.gdr (1.7K)
こちらがレジスタ
こちらがデータセレクタ
あとでプログラムカウンタとして使うため、レジスタのカウンタ機能を復活させる
レジスタに0001、0010、0100、1000をLOADしてみると、うまくいっている
ここでフリップフロップが1つだけの1bitCPUをつくってみた。
ダウンロード 120326-1bitResister.gdr (1.8K)
処理はそのまま転送か反転の2種類だけ
この部分の入力がHならただの転送で、Lなら反転になる
矢印のところで下のQ#が反転している
ダウンロード 120326-1bitResister0.gpt (0.2K)
レジスタとデータセレクタのテストをしてみるため、4つめのレジスタに直接入力を付ける
ダウンロード 120324-RegisterSelecterTest-120326-17000.gpt (0.5K)
まずレジスタ4に0101を入力し・・・
ここですね・・・
レジスタ1だけ転送を受け入れる(LOAD)ようにすると・・・
レジスタ1に0101が入力されています(図はQ#なので反転して1010になっています)
次の転送元はレジスタ1で・・・
転送先はレジスタ2です
レジスタ2に0101が入力されたことがわかります
レジスタ3に0101が入力されました
これは桁上り(Cin)を込みにした全加算器
入力Aと入力BがH、桁上り入力CinがLのときは・・・
このANDゲートがHを出力して桁が上がる(C)
AだけHの場合は・・・
このANDゲートがHを出力する(S)
A+BがSと桁上りのCに反映されている
先ほどの1bit全加算器を4個つなげると、4bit全加算器
ダウンロード 4bitfullAdder.gdr (2.2K)
0001+0001=0010、0010+0010=0100、0100+0100=1000、1000+1000はC出力、Cinのみは0001
ダウンロード 4bitfullAdder0.gpt (0.3K)
ダウンロード 120327-AluTest.gdr (11.3K)
4つめのレジスタに0001をセットして1つめのレジスタに転送し、
ダウンロード 120327-AluTest0.gpt (0.6K)
0001+0001=0010
0010+0101=0111
0111+0001=1000
キャリーフラグとデコーダをつくり、4bitCPUを完成させます。
キャリーフラグをALUに接続する
ダウンロード 120329-FragTest.gdr (11.8K)
1111に0001を足すと、CF出力がHになる
ダウンロード 120329-FragTest0.gpt (0.5K)
出力(上)と入力(下)を付ける
ダウンロード 120329-OutTest.gdr (12.2K)
上から入力3、加算2、出力5
ダウンロード 120329-OutTest0.gpt (0.6K)
デコーダ回路をつなげる
うまく動かなかったのでLOAD0~3とセレクタを出力してみたら、セレクタのつなぎ方が間違っていたことが判明。
ダウンロード 120329-DecoderTest-120404.gdr (14.7K)
4bitのオペレーションコードを入力して、それが正確に動作しているかを見てみると・・・
ダウンロード 120329-DecoderTest-1204040.gpt (0.7K)
正常に動いています。長い旅が終わりました・・・
最後に、問題が起こるたびにいつも正確無比なアドバイスをくれた@su_exsくんに感謝して、このシリーズを終わります。ここまで読んでくださって、ありがとうございました。