マイクラで4bitCPU
この記事は、大阪工業大学 Advent Calendar 2020の16日目の記事です。
はじめに
マインクラフトで4bitCPUを作りました。
実行できる命令はLDIとADDの2種類、レジスタは2個、命令メモリは8個、動作周波数は約0.5Hzです。扱える値は符号なし整数です。レジスタ幅が4bitでLDIのオペランドが2bitの即値を取ることが出来るので0~15(\(2^4\))の範囲で0~3(\(2^2\))の加算を行うことが出来ます。
4bitCPU
CPU
原始的なCPUは以下の部品で作ることが出来ます。
- 命令メモリ
- プログラムカウンタ
- 全加算器
- レジスタファイル
- ALU(AND、SUB、OR、ADDとかの演算が出来る)
- セレクタ
- 符号拡張機
CPUは命令が格納された命令メモリから順番に命令を読み込み、命令を解釈して様々な処理をを行います。一般にCPUでの演算は汎用レジスタ同士で行われます。これはレジスタへのアクセス速度がメモリへのアクセスに比べて非常に早いためです。
今日よく使われているIntelやAMDのx86-64アーキテクチャでは汎用レジスタは16個搭載されています。今回作成した4bitCPUでは汎用レジスタは2つです。
命令セット
命令を作成するために各bitをどのように使うかを決定します。
今回作成した4bitCPUは命令長が4bitです。そのため、今回の設計ではオペランドに1bit、レジスタに1bit割り振りました。よって命令と汎用レジスタ数はそれぞれ2個(\(2^1\))ずつとなっています。使用出来る命令はADDとLDIです。
命令 | 命令機能 |
---|---|
ADD Rdest | Rdest <- R0 + R1 |
LDI Rdest, imm2 | Rdest <- imm2 |
ADD命令はレジスタ同士を加算し、レジスタに書き戻します。オペコードは0で、オペランドに書き込み先レジスタ(Rdest)を指定します。普通のCPUであればRdestだけでなくRsrcも指定しますが今回はレジスタが2つしかないので省略しています。
LDI命令は1~3の整数値をレジスタに書き込みます。オペコードが1でオペランドに書き込み先レジスタ(Rdest)と即値を取ります。即値は2bitなので1~3を指定することが出来ます。
命令 | バイナリ表記 |
---|---|
ADD R0 | 0 0 X X |
LDI R1, 2 | 1 1 1 0 |
命令の表記例です。Xは未使用を表します。
bitの割り振りとしてはオペコードを2bitにして即値を1bitにするほうが実行できる命令の数が増え、汎用性の高いCPUを作ることが出来ましたが実装を簡略化するために今回のような設計にしました。
組み合わせ回路
CPUは沢山の組み合わせ回路で構成されます。組み合わせ回路とはAND回路やOR回路、NOT回路などや、これらを組み合わせて作ることが出来る回路のことです。
例えばAND回路、OR回路、NOT回路を組み合わせることで半加算器を作ることができ、半加算器2つとOR回路を組み合わせることで全加算器を作ることが出来ます。
マインクラフトにはレッドストーン回路と呼ばれるものがあります。これを用いることで組み合わせ回路を作ることが出来ます。
組み合わせ回路を作ることができればCPUを作ることが出来るわけです。
回路
先ほど決めた命令にしたがって計算できるように回路を作成します。
回路の実装は以下のようになりました。 先ほど説明した原始的なCPUと異なる点として、実装を簡単にするためにプログラムカウンタの代わりにシフトレジスタを使いました。また命令が2つしかないのでALUの代わりに全加算器を用い、セレクタで命令を判定しています。 配線は白がクロック、赤がリセットです。命令メモリにはレバーで命令を手打ちします。
回路はクロックに同期して命令メモリの命令を順番に実行します。黄色い枠のセレクタは命令のオペランドで書き込む値の選択を行い、水色の枠のセレクタは書き込み先レジスタを選択します。
さいごに実際に計算を行います。
命令 | バイナリ表記 | R0(予測値) | R1(予測値) |
---|---|---|---|
LDI R0, 01 | 1001 | 0001 | 0000 |
LDI R1, 10 | 1110 | 0001 | 0010 |
ADD R0 | 00XX | 0011 | 0010 |
LDI R2, 11 | 1111 | 0011 | 0011 |
ADD R0 | 00XX | 0110 | 0011 |
ADD R0 | 00XX | 1001 | 0011 |
左の4つの明かりがR0、右の4つのあかりがR1です。明かりがついているときが1で消えているときが0に対応します。 正しく計算が行われていることがわかると思います。
おわりに
今回作成したCPUは非常に単純なものでしたが実際に計算を行うことが出来ました。回路の動作が目に見える形で実行され計算が行われるのは見ていて面白かったです。
CPUに興味の湧いた方や気になる方が入れば下記のサイト上で簡単なCPUが作れるみたいなので遊んでみるといいと思います。