幼女でもできる自作CPUチップ (7) 論理ゲートのレイアウト

 前回の記事

ourfool.hatenablog.com

では、CPU内で演算機能を担うALUについて、論理ゲートレベルの接続図を示した。

 これで、以前書いたCPUチップのデータパス図のうち、命令デコーダとALUについて、ゲートレベル表現が完了したことになる。

f:id:ourfool:20160702194116j:plain

f:id:ourfool:20160702194139j:plain

こうしてみると大半はまだ未完成と見えるのだが、実のところ設計は既に8割方終了したといってもいい。レジスタ類や出力ポートはDフリップフロップを、データセレクタはマルチプレクサを並列にしたものであり、プログラムカウンタもDフリップフロップを元にしたシンプルな回路であるから、設計の面でほとんど苦労はない。

 今回は、CPUチップ製造に向けた大いなる第一歩として、テストチップ用のレイアウトデータ作成をおこなう。具体的には、前回まで設計を続けてきたALUの、シリコンチップ上における図面を、手描きで作成していく。CPUを製造する前に、ALU単体の載ったチップを作り、実際に測定をおこなって検証しておこう、という魂胆である。

 シリコンチップで集積回路を作るためには、まず、シリコン上の構造物(ポリシリコン・拡散層・金属配線など)の配置を図面データに起こす必要がある。こうしたデータを一般にレイアウトと呼ぶ。

f:id:ourfool:20160702214958g:plain

(Wikipedia "Integrated circuit design"より)

チップ設計者がおこなう作業は基本的にこのレイアウト作成までである。そののち、図面データを元に、パターン生成用の露光マスクを作り、フォトリソグラフィーによって最終的なシリコンウェハの製造をおこなっていくことになるが、これらは半導体生産工場にておこなわれる作業である。

 ディジタル回路は膨大な数のトランジスタから成っている。既に以前の記事で述べたとおり、通常の半導体設計フローでは、ツールによってこれらの膨大なレイアウトを自動的に生成する。一方、一般の幼女はそんな高級なツールを持ち合わせているはずもないので、トランジスタを形成するp型、n型の半導体層やポリシリコン、金属配線の形から何から、全て手描きしていくことになるわけである。

f:id:ourfool:20160702231921p:plain

(Wikipedia "Field-effect transistor"より) 

 現在、LSIチップに集積されているトランジスタの多くはMOSトランジスタである。MOSトランジスタは電界効果トランジスタの仲間で、正確にはMOSFETという。これは、Metal-Oxide-Semiconductor-Field-Efect-Transistorの頭文字をとったものである。上図のようにMetal(金属電極)とOxide(絶縁膜)からなるゲート端子*1、拡散層から成るドレイン端子とソース端子から成っている。

f:id:ourfool:20160702233526g:plain

(Wikipedia "Field-effect transistor"より) 

 MOSトランジスタはざっくりいうとスイッチとして使われている。ゲート端子に加える電圧によってドレイン端子とソース端子間を流れる電流を変化させることができるため、ゲート端子に加わる電圧がHIGHのときON、LOWのときOFFとなるスイッチのように使える。左図はゲート端子に加える電圧Vgを変化させた際の電流の様子を示している。右図は流れる電子の密度で、電圧Vgにしたがって、流れたり(つながったり)、流れなかったり(離れたり)していることがわかる。

 MOSトランジスタにはNMOSトランジスタとPMOSトランジスタの2種類があり、ゲート端子の電圧に対するONとOFFの特性が逆になっている。つまりゲート端子の電圧がHIGHのとき、NMOSトランジスタはON、PMOSトランジスタはOFF、となるわけである。この2種類を組み合わせて作った、よさのある回路構成がいわゆるCMOS論理回路である。NMOSとPMOSを組み合わせると常にどちらかがOFFになるから、電源からGNDに定常電流が流れない、つまり電力効率がよい、というのがそのよさについての雑な説明である。

f:id:ourfool:20160702235052j:plain

(Wikipedia "CMOS"より) 

たとえば、CMOSでNANDゲートを作ると左図のような回路図になり、それはすなわち右図のようなレイアウトになる。こうしてたくさんお絵かきしていくと、なんとCPUが出来る。

 さて、ALUをお絵かきしていくために、まずは、インバータやNANDゲート、NORゲート、マルチプレクサといった基本素子を作った。なにしろ数百個の膨大な数のトランジスタを描いていくので、いきなりALUを描いていくのは無謀というものである。であるからして、まずは基本素子を作り、それをコピペして配置していくわけである。

f:id:ourfool:20160702235727j:plain

インバータ

 

f:id:ourfool:20160702235816j:plain

NANDゲート

 

f:id:ourfool:20160702235831j:plain

マルチプレクサ

 

ここで青い線が金属配線、オレンジ色の部分がポリシリコンによるゲート端子、緑色の部分がn拡散層やピンク色の部分がp拡散層を表している。これだけ描くのもぶっちゃけ相当めんどくさいがまあなんとかなった*2

 次回は、こうした基本素子を組み合わせていよいよALUを作る。ついでに、それらのレイアウトからSpiceファイルを抽出して、回路シミュレーションによる検証をおこなう。というか実は既に検証を終えているのでそれに関して記事をかく。いよいよCPU作りっぽくなってきた(?)。

*1:歴史的には、長い間、導電体のポリシリコン電極が用いられて、数年前から金属ゲートとhigh-k材料を組み合わせたプロセスが広がってきた、で、いわゆる14nmプロセスに突入した現在はもはやどちらでもなく3次元構造の変態仕様になっている。

*2:もちろん、こんなことを著名なメーカの設計者が日常的にやっている筈はない。通常の半導体設計者が使うようなお高いソフトウェアではこれらのような基本論理ゲートはもちろん、簡単な回路のレイアウトは一通り揃っている。

幼女でもできる自作CPUチップ (6) ALUのゲートレベル表現

 前回の記事

ourfool.hatenablog.com

では、CPUの中でもっともつよいもの、ALUの設計をおこなった。

 ALUの構成要素のうち、AND演算器、OR演算器、マルチプレクサはゲートレベルの表現を示したが、加減算器は面倒なので先送りしていた。今回はこの加減算器のゲートレベル表現をおこなっていく。

 ALUとその内部にある加減算器の構成を再掲しておく。

f:id:ourfool:20160607235815j:plain

 

f:id:ourfool:20160607235930j:plain

 加減算器の構成要素のうち、インバータは既にゲートレベル表現であり、マルチプレクサのゲートレベル表現も前回の記事で示している。したがって、あとは全加算器さえゲートレベルで表現してやれば、加減算器のゲートレベル化はクリア、よってALU全体もクリア、ということになりそうである。

 さて、全加算器について書く前に、その構成要素である半加算器について見ていく。

f:id:ourfool:20160608000330j:plain

半加算器は、2つの入力信号DataA、DataBの足し算結果を出力する回路である。2進数であるから、0+0=0、0+1=1、1+0=1、1+1=10(繰り上げ)というような感じになっている。足し算の結果はSumとして出力される。1+1で繰り上がりが発生する場合のみ、桁上げ信号Carryが1になる。

 半加算器の真理値表を満たすゲートレベル表現は以下のようになる。うまいことすることでNANDとインバータだけで表現できる。半加算器の設計にもいろいろと工夫のしようはあるのだが、今回はごく普通のCMOS回路としておく。

f:id:ourfool:20160608001201j:plain

 一見すると半加算器でしっかり足し算ができるように思えるが、半加算器はあくまで半人前の加算器である。理由は、複数bitの足し算をおこなう場合、2つの入力に加えて下の桁からの繰り上がりを考慮しなければならないからである。

 繰り上がりを考慮した加算器を全加算器と呼ぶ。全加算器は以下のような構成である。

f:id:ourfool:20160608001045j:plain

図からわかるように、全加算器は2つの半加算器とORゲートから構成できる。1段目の半加算器で2つのデータの足し算結果を出力している。その結果と、下の桁からの桁上がり信号ICarryとをさらに2段目の半加算器で足し合わせ、最終的な結果をSumとして出力している。1段目の足し算と2段目の足し算のどちらかで繰り上がりが発生していれば、それを上の桁に伝える桁上げ信号OCarryとして出力する。これで加算演算が実現できた。

 半加算器のゲートレベル表現は上に示したとおりであるから、それを2つ組み合わせれば全加算器のゲートレベル表現ができる。

f:id:ourfool:20160608002107j:plain

これでいよいよALUが完成–––ではなく、最後にもう一工夫を加えておく。

f:id:ourfool:20160608002239j:plain

OCarryを出力するORゲートの2入力はどちらもインバータを経ている。つまりここで、「notAまたはnotB」は「not「AかつB」」、というガチで女児レベルの定理を活用できる。ドモルガン律からの全てNANDのみ構成––––––優勝!!!

 というわけで今回は、ALUの回路をすべてゲートレベルで記述することができた。次回はこれを回路シミュレータに記述し検証をおこなう。

幼女でもできる自作CPUチップ (5) ALU設計

 前回の記事

ourfool.hatenablog.com

では、CPUの命令セットに準拠した命令デコーダの設計をおこなった。

 今回は、命令デコーダの出力に応じて種々の演算をおこなう、CPUの中でもっともつよいもの、ALUの設計をおこなう。

 前回の記事に示した命令デコーダの出力のうち、S2、S1、S0がALUの演算機能を切り替えるための信号、SelectALUである。内部データパス図で示したとおり、SelectALUは3bitの信号であり、この3bitの組み合わせによって、加算、減算、論理演算(AND、OR、NOT)と、ALUの機能を切り替える。命令の内容と照らし合わせるとわかるように、SelectALU信号に応じて実現するべき演算内容は以下のようにまとめられる。

f:id:ourfool:20160606182243p:plain

SelectALU=101~111はそもそも入力として現れないため、前回のデコーダ設計と同様、気にしないこととする。

 これらの演算を実現できるよう、各演算用の回路ブロックを搭載することとし、ALU内部を回路ブロックごとの接続図で表してみる。

f:id:ourfool:20160606182525p:plain

台形を横にしたようなブロックは、2入力のマルチプレクサである。1bit(0 or 1)の信号に応じて、2つの入力のうちどちらを出力するか選択する。加減算器ブロックは、加算、減算用の回路をひとつにしたものである。先ほどの表を見てみると、加算と減算ではSelectALU[0]の値が異なっているので、この信号で加算と減算を切り替えればよい。SelectALU[2]では加減算器の出力をインバータに入力するか、しないかを切り替える。インバータを挟んだ場合、NOT演算が実現できる。また、AND演算器とOR演算器はSelectALU[0]で切り替える。最終段ではSelectALU[1]に応じて、どちらかの入力を選択する。上に示した表と見比べてみると、SelectALUに応じて適当な演算器の出力が選択されるように、たぶん、なっているはずである。

 さらに、ブロックの中身を詳しく見ていく。

f:id:ourfool:20160606184504p:plain

加減算回路は全加算器(FA)とマルチプレクサ(Mux)によって実現する。全加算器をデータのbit数と同じだけ並べることで、加算を実現する。さらに、全加算器への入力をインバータにより反転させることで、減算を実現する。これが、情報系の耳タコワードたる「2の補数」による減算というやつである。ウェハ上のレイアウトを作成する前に、このブロック図をさらに論理ゲートレベルまで落とす必要があるが、煩雑になるので今回はやめておく。

 他のブロックについても見てみる。

f:id:ourfool:20160606184904p:plain

 ANDとORはゲートレベルのANDとORをデータのbit数分並列に並べるだけであり、ドチャクソ簡単である。女児向けの説明にはなるが、ANDゲートやORゲートの記号を使わずに敢えてNANDゲート+インバータ、NORゲート+インバータと表現しているのは、今後CMOS回路でこれを実現したいからである。CMOS回路では、トランジスタの動作上、NANDやNORゲートが基本単位となる。ANDやORゲートはそれらにインバータを付けて実現すると考えておくとわかりやすい。このあたりはトランジスタレベルの回路を見てみると速攻で理由がわかって優勝できる。

 今回はALUの具体的な回路構成を策定した。次回はこれらをLTSpice上でシミュレーションし、演算が正確におこなえるかどうか調査する。余力があれば、命令デコーダともつないでみたい。

 なお、これまで書くタイミングがなかったが、本記事は以下のような書籍を参考にして執筆している。どの本も、知ってる幼女は確実に知ってる、知らない幼女は覚えとかないと死ぬぞといった感じのアンセムである。晴れて5回記事が続いたということで、続いているうちに示しておく。

コンピュータの構成と設計 第5版 上

コンピュータの構成と設計 第5版 上

 
コンピュータの構成と設計 第5版 下

コンピュータの構成と設計 第5版 下

 
ディジタル回路設計とコンピュータアーキテクチャ (IT Architects' Archiveクラシックモダン・コンピューティング)

ディジタル回路設計とコンピュータアーキテクチャ (IT Architects' Archiveクラシックモダン・コンピューティング)

 
CPUの創りかた

CPUの創りかた

 

幼女でもできる自作CPUチップ (4) 命令デコーダ設計

 前回の記事

ourfool.hatenablog.com

では、CPUの具体的な構成や命令セット、つまりアーキテクチャを策定した。

 そして今回は、第1回のフローに示したRTL設計をおこなっていく–––––つもりだったのだが、方針を変えて回路シミュレータを使い各回路ブロックの検証をおこなうことに決めた。

 というのも、RTL設計にはそもそもHDL (Hardware description language) に関する知識が必要であり、その上、シミュレーション用のソフトウェアも利用方法が難解である。これらの理由から「幼女でもできる」という趣旨には反しているように思えてきた*1

 加えて、RTL設計をソフトウェアでおこなえば、そこから自動で論理ゲートレベルの設計をおこなうことが出来てしまう。これによって、自ら論理設計をおこなう、というクッソ面倒な作業へのモチベーションが潰える危険性は極めて高い。それゆえ、全体のRTL検証は後回しとして、まずはフリーの回路シミュレータで各ブロックごとの地道な検証をおこなっていく。

 まず、前回記事内容の修正について書いていく。

f:id:ourfool:20160529183155p:plain

前回は上図のImDataやAddressを5bitとしていたが、これを10bitへと変更する。これは、流石に5bit(命令が最大32ステップ)じゃなんもできないのでは、、といった考えから来たやむを得ずの変更である。前回このCPUを「LO5」と命名したが、この変更に伴って「LO10」へと改名する。オペコードは5bitのままであるから、命令セットに変更はない。一方、レジスタやALU間のデータはすべて10bitでやり取りされる。
 また、命令デコーダの真理値表に一部誤りがあったので、修正したものを再掲する。

f:id:ourfool:20160529183743j:plain

だいぶ威圧感を感じるが、今回はこれを人力で論理ゲートレベルに直し、回路シミュレータで検証する。

 ここでデコーダ入力のCはキャリー信号を表す。ALUが加算命令をおこなう際、桁上げがおこった場合にはキャリー信号を出力する。この信号の有無で、CPUの挙動を変えることにより、条件分岐ジャンプ命令(JNC)を可能にする。

 論理ゲートレベルへの変換に先立って、まずは論理の簡単化をおこなう。大学の授業等ではカルノー図で頑張るところだが、流石に5(or 6)変数にカルノー図を使うのはつらいので、Web上のアプリを使わせていただくことにする(オンライン 論理圧縮・論理式簡単化システム 論理あっしゅ君)。これによって、真理値表の5入力(O4、O3、O2、O1、O0)と、SBやSAといった出力の関係を論理式として把握できる。
 それぞれについて地道に値を打ち込み、調べていくことになるのだが、このままの真理値表を使うのではあまりに面倒なので、以下のような表を作成し直す。

f:id:ourfool:20160529184925j:plain

5bitの入力が(0, 0, 0, 0, 0)~(1, 1, 1, 1, 1)と順に変化していくよう、命令を並び替えている。これで入力が一気に楽になった。

 5bitの入力で表せる状態が2^5=32種類なのに対して、命令は21種類しかない。よって、その他の11状態はそもそも入力として現れる可能性がないので、出力は何であっても構わないとして、x(Don't care)としている。これにより、論理の簡単化が図れる。

 それぞれの結果は以下に示すようになった。

f:id:ourfool:20160529190104j:plain

SB、SAあたりは何も考えていないだけに酷いことになったが、その他はほどほどに簡単化されたので、まあ良しとする。

 さて、これらの論理式をインバータやNANDゲート、NORゲートといった論理回路図で表現し、それを検証することが、今回の目標である。

 検証には、フリーの回路シミュレータとして有名なLTspiceを用いることにした。

電子回路シミュレータLTspice入門編―素子数無制限!動作を忠実に再現! (ツール活用シリーズ)

電子回路シミュレータLTspice入門編―素子数無制限!動作を忠実に再現! (ツール活用シリーズ)

 

フリーのSpiceシミュレータにも関わらず素子数無制限で収束性もよく、幼女でも気軽に扱えるUIが魅力である。書籍など情報源も豊富。

 LTspiceにはデフォルトでディジタル論理ゲートのデータが含まれているので、それを用いてシミュレーションをおこなう。Edit→Componentから[Digital]→and、or、invなどを選択し配置する。入力波形は、voltage素子を用いて生成する。

 雑でアレなのだが、シミュレーション用の回路図は以下のようになった。上部で入力波形を生成しており、下にそれぞれの論理式を満たすよう、NANDやNORゲートを配置している。

f:id:ourfool:20160529191746j:plain

 上部の拡大図は以下、voltage素子を複数配置してそれぞれの周期を調整すれば、5bit入力を順次変化させていくことができる。

f:id:ourfool:20160529192058j:plain

 SBは以下のような接続、ゲートはデフォルトで5入力なので、使わない端子はまとめてGNDへ接続する。

f:id:ourfool:20160529192149p:plain

 SA、S2、S1は以下のような接続。

f:id:ourfool:20160529192441p:plain

 S0、LA、LBは以下。

f:id:ourfool:20160529192939p:plain

 LP、LOは以下。

f:id:ourfool:20160529192910p:plain

 接続を終えたのち、シミュレーションをおこなった。Simulate→Runののち、各ノードをクリックすれば電圧が確認できる。解析時間さえ設定すればよく非常に簡単。

f:id:ourfool:20160529193415j:plain

波形は上からO4、O3、O2、O1、O0、LBを表している。入力のO4-O0が変化するにしたがって、LBも真理値表どおりの値をとっていることが確認できる。この作業を各出力についておこない検証した。意外と合っているもの(勝利)。

 今回は命令デコーダの設計をおこなった。この調子で、次回はALUの設計をおこなう。続いて、これら2つの回路をウェハ上のレイアウト図にする。たぶんこれが一番難しい。

*1:一般的なCPUの設計論にはHDLが必須だが、論理合成のプロセスはブラックボックスになってしまう。CPUを0から作る、というコンセプトには人力論理合成の方が合っているように思える。

Arduino+XBeeでつくるワイヤレスオナホールネットワーク (1)

 以下は、海外のテクノロジー系DIY工作専門誌である、Make:Onaholeの記事"Building Wireless Onahole Networks"を鷺ノ宮わっふる(@ourfool)が翻訳したものである。日本の事情を考慮し一部ローカライズを行っているものの、基本的には原文に忠実な訳を心掛けている。日本語版の権利については同誌の出版社が保有している。本記事の内容については最大限の努力をもって正確を期しているが、本記事の内容に基づく運用によるいかなる倫理・道徳的な責任も負いかねるので、ご了承願いたい。

 

はじめに

 この記事は、USBオナホールを使ったネットワークの構築についての基本的な入門編だ。USBオナホールの活用やハッキングに興味のある人は、そのための第一歩として、この記事を活用してほしい。

 USBオナホールによって、社会は圧倒的な変化を遂げた。かつて、自分の目の前にしかなかったオナホールは世界とつながり、ユーザはネットワークを通じ、世界中のどこへでも進出できるようになった。ユーザ同士は興味深い情報を見せびらかしたり、共有したり、あるいは他のプロジェクトに自分のデータを役立ててもらうこともできるようになった。このようなツールと出会えたことは驚くべき幸運である。

 この記事は、ホビイスト、学生、Maker、ハードウェアハッカーなど、幅広い人々を対象としている(ただし全員男性でなければならないが)。ここではUSBオナホールのほかに、Arduinoや、Processing、Zigbeeといった親しみやすい環境を使ってサンプルを製作する。これらは非常に人気のあるプロトタイピングツールで、使いやすく、柔軟性に富んでいる(これらは同時にオナホールにも顕著な特長だ)。そのため、読者が若い発明家であっても、経験豊富なエンジニアであっても、プロジェクトを効率的に進めることができる。筆者としては、この記事によって読者の人生がさらに豊かなものになる手助けができることを願っている。

 

1章:動かしてみる

  さっそく仕事にとりかかろう。この章では、ArduinoとUSBオナホールを接続し、USBオナホールのスイッチに応じてLEDを点灯させる。これから、実際につかうデバイスについて説明しよう。

 

・USBオナホール

 USBオナホールはUSBケーブルでほかのデバイスとつながることができるまったく新しいオナホールだ。専用のソフトを使えば、非常にわくわくするような行為を楽しむことができる。

 いまもっとも簡単に手に入るものは、TechArtsのUSBオナホールだ。

 あるいは、このあと発売されるKISSのUSBオナホールも魅力的な選択肢となるだろう。

  この記事では、TechArtsのUSBオナホールにだけにしぼって説明をおこなう。

 

Arduino

 Arduinoは、自作愛好家に人気のあるオープンソースのマイクロコントローラシステムだ。学びやすく、使いやすく、そして(オナホールと同様に)柔軟性に富んでいる。

Arduinoをはじめようキット

Arduinoをはじめようキット

 

 

・USBホストシールド

 USBホストシールドは、USBオナホールArduinoの橋渡しのために必要だ。

USBホストシールド 2.0 for Arduino (compatible with Google Android ADK)
 

 

 さあはじめよう。まずは、USBオナホールArduino、USBホストシールド、LEDを手に入れよう。つぎに、USBホストシールドを動かすためのサンプルプログラムを用意しよう。プログラムとそのインストール方法は

https://www.circuitsathome.com/arduino_usb_host_shield_projects

から入手できる。

 USBオナホールは、HIDという規格に基づいている。サンプルプログラムを入手したら、サンプルのうちUSBHIDJoystickをひらいてみよう。そして、USBHIDJoystickのsetup()に以下のような修正をおこなおう。

void setup() {
        Serial.begin(115200);
        pinMode(6, OUTPUT);

 

また、hidjoystickrptparser.cppのうち、JoystickEvents::OnButtonUp()とJoystickEvents::OnButtonDn()を以下のように変更しよう。


void JoystickEvents::OnButtonUp(uint8_t but_id) {
        if (but_id == 1) {
          Serial.print('B');
          digitalWrite(6, LOW);
        } else {
          Serial.print('D');
        }
}

void JoystickEvents::OnButtonDn(uint8_t but_id) {
        if (but_id == 1) {
          Serial.print('A');
          digitalWrite(6, HIGH);
        } else {
          Serial.print('C');        
      }
}

 

 これだけで、準備はととのった。あとはArduinoとUSBホストシールドをつなぎ、6番のPinとGNDのPinの間にLEDをとりつけよう。そのあとで、パソコンからArduinoにプログラムを書き込もう。

 ついに待ちにまった瞬間がやってきた。すべて順調なら、USBオナホールにかたいものを挿入するたび、LEDが点灯するはずだ。ぜひ試してみてほしい。

f:id:ourfool:20150601002324j:plain

f:id:ourfool:20150601002326j:plain

 

トラブルシューティング

 最初からLEDが点灯したら、それは素晴らしいことだ。しかし、何回かやり直さなければならないこともある。うまくいかなかったときは、単純なところからはじめてみよう。ArduinoやUSBオナホールが正しく接続されているか、LEDの向きは間違っていないか、まずは確かめてほしい。

 つぎに、Arduinoのシリアルモニタを確かめてみよう。今回のサンプルでは、オナホールの2つのボタン入力に応じてA, B, C, Dの文字が表示されるはずだ。これがうまくいっていなかったら、その場合に応じて、間違っている部分を探してみよう。

 また、ネット上にはすばらしい情報源やフォーラムがあり、助けを求めたり、参考にすることができる。

 

成功!

 実際にLEDを点灯させることができたら、盛大にお祝いをしよう。アニメイションを見たり、サイリウムを振ったり、USBオナホールを実際に使ってみよう。あるいはこれら3つのことを同時にやるのもよいだろう。なにしろ最初の大きな一歩を踏み出したのだから!

 

幼女でもできる自作CPUチップ (3)

 第1回の記事

ourfool.hatenablog.com

でおおまかな設計フローを示し、

第2回の記事では仕様設計をおこなった。

ourfool.hatenablog.com

 今回は、フローに示したもののうち、アーキテクチャ設計について書いていく。

 前回、どのようなCPUをつくるか、つまり仕様を固めたので、今回はその仕様を満たすよう具体的な内部構成を決めていく。

 しかし構成を決めるに先立って、前回前々回とすっかり失念していた重要な作業をおこなわなければならない。CPUの命名である。IntelさんのCPUにCore i7 ○○とかCeleron○○とかつよい名前がついているように、今回つくるCPUにもここで名前をつける。

 今回のCPUは「自らレイアウトする(Layout-Originally)5bitのCPU」であるから、シンプルに「LO5」という名称でいこうと思う。無難で単純な命名ではあるが、なんとなく心地よい響きだ。

 まず、LO5のデータパスを以下にしめす。データパスとはCPU内部のデータの流れを図に示したものをいう。

f:id:ourfool:20150503222139p:plain

 前回の記事は「幼女でもできる」と銘打った割に不親切でメモ的な内容になってしまったので、ここでいろいろと動作を補足しておく。

 5bitのCPUであるから、データは5bit単位でやりとりされる。入出力(Input, Output)も5bitである。Input, Outputは5bitのデータが並列に送られる。つまり実際には5本の信号線があり、各々が0 or 1のデジタル信号を送る。他の信号線も同様である。複数の信号線を1本で表現していることは、斜線+○bitという表記であらわしている。

 一般的なパソコンのメモリ(RAM)にあたるものはLO5に存在せず、代わりにROMだけが存在する。これは一般的なパソコンでいうところのハードディスクであるとかSSDにあたる。ふつう高速なRAMに一旦プログラムを持ってきてから実行するところを、遅いROMから直接持ってきて実行しているという感じである*1

 変なかたちのブロックはALUといって、計算をする部分である。ここに送られたデータ同士の演算をおこない、その結果を出力する。レジスタはデータをたくわえる部分。たくわえられたデータ同士で演算をおこない、その結果を再びたくわえる、ということを繰り返し、出力を変化させていくことができる。

 ALUへの入力データ選択(SelectData)、ALUの機能選択(SelectALU)、ALUの出力したデータの行き先(Load○)はROMに保存されたプログラムにしたがって決まる。ROMのどこに保存されたプログラムを実行するかは、Addressによって決まる。

 ROMなどの外部回路との接続も図に示すと、下のようになる。

f:id:ourfool:20150503225832p:plain

 ROMに保存された命令は、オペコード+イミディエイトデータという構成で、全て合わせて10bitとなっている。10bitのうち、前半5bitのオペコードは命令の演算内容を表し、後半5bitのイミディエイトデータ(ImData)は命令に用いる値を表している。たとえば、「レジスタAの値に5を足す」という命令を考えると、「レジスタAの値に○○を足す」をオペコードが表し、「5」をImDataが表している*2

 オペコードごとに異なった演算を実行するには、ALUへの入力データと出力先のレジスタを、各オペコードに応じて適宜選択する必要がある。したがって、オペコードに対応して選択のための信号を生成する、命令デコーダが必要になる。

 もろもろ鑑みて、デコーダの真理値表は以下のように決めた。実際の回路では、以下の真理値表を満たすような論理回路から成るデコーダをROMの出力につなぎ、ALU、レジスタの選択信号をつくる。

f:id:ourfool:20150503180010p:plain

 ここでニーモニックとは命令にわかりやすい名前をつけたものである。LO5は全21種類の命令を持っている。貧弱だが、算術演算(ADD、SUB)、論理演算(AND、OR、NOT)、ジャンプ(JMP、JNC)を一通り備えているし十分満足とする。なお、このようなCPUの命令体系は命令セット(instruction set architecture, ISA)と呼ばれる。これは普通のパソコン等でいうと、x86とかARM*3とかなんとかその辺の語彙にあたる。

 コンピュータの話ではRISCとかCISCとかいう言葉がよく出てくるが、これは命令セットの設計手法の話である。ざっくり言うと、命令の種類が少ないのがRISC、多くて複雑なのがCISCで、x86CISC、ARMはRISCというのが入門講義の模範的な解答(?)である。

 LO5はというと、別にReduced Instruction Set Computerでもなく、かといって、Complex Instruction Set Computerなはずもないので、なんとも言えない。いま勝手に作った言葉でいうとYowai Instruction Set ComputerでYISCくらいがしっくりくる。

 さて、あらためて真理値表をまとめてみると、どうもやっぱり面倒そうな気がしてくるのだが、まあなんとか実装できるということにしておく。気休め程度に工夫を加えたオペコードが、劇的な簡単化をもたらすに違いない。

*1:ここでの解説はおおむね「感じ」である。技術的には結構おかしなことを言っている部分もあるので注意されたい。

*2:ふつうは「オペランド」なるものがある。LO5にも一応オペランドっぽい部分はあるのだが、デコーダ回路論理の都合で微妙に複雑なことになっている。

*3:ただしARMという言葉は多義であって、常に命令セットアーキテクチャのことだけを示すわけではない。

幼女でもできる自作CPUチップ (2)

 前回の記事

ourfool.hatenablog.com

で書いた設計フローのうち、仕様設計が確定したのでこれについて書く。

 まず、汎用レジスタは5bitとした。今回作るCPUは5bitのCPUということになる。プログラムカウンタも5bitとする。動作周波数は数Hz~数kHzまでを考慮して設計する。

 5bitというすこぶる気持ち悪い値を選んだ理由としては、4bitだとあまりにオリジナリティのないものができそう、と想像したことが大きい。4bitと比べてやや設計は煩雑になる。これが後々後悔につながらないことを祈るばかりである。

 汎用レジスタ、プログラムカウンタが5bitということで、アドレス空間はそのまま2^5=32Byte…ではなく2^5=32種類のアドレス×命令長10bitというやはりすこぶる気持ち悪い感じになる。プログラムは最大で32ステップとなる。貧弱な気もする一方で、頑張ればいろいろできそうな気もする微妙なライン。

 たとえば、現在PCに使われているような64bitのCPUだと形式状は2^64=16EByteとかいうわけわからんアドレス範囲を扱える*1。これと比べると流石にどうしようもないが、それはそれ、これはこれ、としよう。

 IOはCPU内蔵で単純な5bitパラレルポートとする。具体的なアプリケーションは謎だが今後考えていけばなんとかなるはずだろう。

 クロック、リセット回路、ROM(RAM?)は外部に作る。このあたりはdip部品で基板上に実装する。ただし、全部を載せようとすると基板が巨大になる懸念もある。いま考えているところでは、ROMの基板を4段、CPU+クロック、リセット回路を積んだ基板を1段、とし、Arduinoシールド的なノリで5段積層にするつもりである。数kHz動作までならタイミング的な話は特に考えなくともなんとかなるのではないかと期待を抱いている。

f:id:ourfool:20150429235715p:plain

何よりなんかかっこいいのでこれでいきたい。なおROMは現状だとdipスイッチで実装するつもりだが、物量地獄回避のためRAMを使う可能性もある。ただそれはそれで面倒、かつ外部からの書き込みが必要になるとどうも自作感が薄れてくるので本命はdipスイッチ32個である。

 次回はCPUの具体的な動作をRTL記述する。随分構想が固まってきたのでここは早めに突破してなんとか回路設計、レイアウト設計に時間*2を使っていきたい…

*1:当然ながら16EByteのメモリ実装は物理的に不可能なので、いろいろと工夫がなされている、このあたりは単純化するとどんどん技術的に間違った話となっていくので打ち止めにする。

*2:実のところ、今回のCPUチップ試作にはそれなりのアテとそれに伴う締切が存在する。とんでもなくまたとない機会なので、是が非でも利用したいと思う一方、現状では間に合わない算段となっている。