2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Turbowarpでnandgameのcpuを再現してみた

Last updated at Posted at 2025-04-27

注意
この記事はnand gameのネタバレ(答え)を含みます。

1 きっかけ

cpuの勉強をしたくてnand gameで遊んでいたところ 「これTurbowarpでも作れんじゃね」と思い勉強の実践も兼ねて作ってみることにした。

turbowarpには『ビット操作』という便利な拡張機能があるが負の値を-111111...と表現してしまうので16bitの論理ゲートなどは1bitずつ変換してくっつけたもので表すことにする。

2.今回作るcpuの構造

スクリーンショット 2025-03-19 15.54.24.png
主に、RAM、コントロールユニット、クロック回路、カウンター、rom でできている
(めっちゃわかりにくい)

2.1 memory

このmemoryは二つのレジスタと一つのRAMでできているようだ。

これをさらに分解していく

スクリーンショット 2025-03-19 15.57.55.png

register

スクリーンショット 2025-03-19 16.00.53.png
N bitレジスタはDFFがN個でできているようだ。 (この場合はN=2)
しかし画像中のD-FFDラッチを使用していて、そのDラッチは出力を入力に代入するという方法でできているので今の私の技術力では再現することができない...

なので私は、レジスタをブロックで直接作ることにした。
そして完成したのがこれだ。
block_2025_3_19-16_13_48.png

このIDというものは複数のレジスタを区別する役割がある。

一応これでもちゃんとnandgameと同じように動作する。

途中で値が変わっても一番最初に記録した値が出る。
説明;
registerA_---1番最初の入力を記録する変数

registerB_---値をセットしたか(clが1の時,registerC_を変更しないようにするため)

registerC_---値をセットしたときregisterA_を記録する変数

registerD_---出力用の変数(registerC_を出力)

2.2 RAM

RAMはいくつものレジスタを組み合わせてできている。
いちいちレジスタを何個も組み合わせて作るのは効率が悪い(めんどい)ので
これも一から作っていく
block_2025_3_19-16_30_54.png

今回は保存、出力先をRAMというリストにしてみた。
registerのブロックの出力先(register_D)を リストRAMにしただけ。
仕組みは同じ。

2.3 counter

スクリーンショット 2025-03-19 16.19.17.png
見ての通りカウンターも一部出力を入力に代入しているところがあるので一から作った。
結果↓
block_2025_3_19-16_22_10 (1).png

説明;
カウンタ1 特に意味はない 制作過程で出てきたやつ 今は修正済み。

カウンタ2 Xを書き込み中か(clが更新されたか)

カウンタ3モード判別
0の時インクリメントモード
a,bの時setモード

カウンタ4 Xの値の保存

カウンタ5 カウンタに書き込み可能か(clが更新されたか)

2.4 control unit

さぁここからが本番だ。
control unitはCPUにとって心臓部なのでパーツも多いし複雑になってくる。
なので、重要なもののみを解説することにする。

ここはわかりやすいように本来の順番で解説していこう。

論理ゲート どれも基本的な仕組みは同じだ。 最初にも言った通り一つひとつ変換して出力する。

説明;

〇〇出力
〇〇 counter変換するビット
〇〇 answer変換結果

and

block_2025_4_27-13_08_13 (1).png

or

block_2025_4_27-13_12_02 (1).png

xor

block_2025_4_27-13_12_06 (1).png

not

block_2025_4_27-13_11_44 (1).png


計算

HA

半加算機(Half Adder)は1ビットの2つの入力された値を加算、出力(2ビット)する回路だ。

block_2025_4_27-9_56_13 (1).png

これを再現している↓

スクリーンショット 2025-04-27 9.57.09.png

FA

全加算機(Full Adder)は2つの入力された値と繰り上げ(両方1ビット)を加算、出力(2ビット)する回路だ。

半加算機が三つでできる(頑張れば二つで行けるらしい)
block_2025_4_26-22_52_57 (1).png

非常にわかりにくい。
丁寧によんでいけばこうなっているとわかるだろう。
スクリーンショット 2025-04-26 22.57.36.png

ちなみに、
x=a
y=b
z=c
である。

MA

多ビット加算器(Multi-bit Adder)は多数のビットを加算、出力する回路である。

今回は16ビットcpuなので16個必要だ。
しかし、ram同様いちいちパーツを組み合わせて作るのは効率が悪い(めんどい)のでこれも一から作っていく。↓
block_2025_4_27-12_55_34 (1).png
説明;
adder answer :1ビット加算機の結果
adder counter:何ビット目を計算するか
adder :出力
adder carry :「1ビット加算機の結果」の繰り上げの値
手順;
//start
①16ビット目を加算する。adder carryを設定する。
//↑loop↓
②15ビット目、adder carryを加算する。 adder carryを更新する。
③14ビット目、adder carryを加算する。 adder carryを更新する。
④13ビット目、adder carryを加算する。 adder carryを更新する。
...(1ビット目まで繰り返す)

Increment

block_2025_4_26-22_30_24 (2).png

インクリメントは入力された数+1を出力する回路だ。
加算機を利用している。

Sub

block_2025_3_19-22_59_03 (1).png

Subtraction(減算)はX-Yの結果を出力する回路だ。
これの考え方を変えるとX+(-Y)となり加算器と2の補数を使って結果を出すことができる。
2の補数とは、二進数で負の数を表す代表の方法である。
2の補数は負の数にしたい値を反転(not)して1を足せばできる。

参考https://www.seplus.jp/dokushuzemi/ec/fe/fenavi/kind_basic_theory/basic-theory2/

EZ(eq)

Equal to Zeroの略でX=0の時1を出力する回路だ。
block_2025_3_19-22_48_34 (1).png

LZ(lt)

Less than Zeroの略でX<0の時1を出力する回路だ。
block_2025_3_19-22_43_18 (1).png

第15ビットを符号ビットとして利用している。
符号ビットが1の時は数値が負の数だということを表している。


切り替え&スイッチ

セレクタ

block_2025_3_19-21_14_08.png

セレクターはsが1の時d1を、0の時d0の値を出力する回路である。

スイッチ

block_2025_3_19-21_13_35.png
スイッチはsが1の時dの値をc1に、0の時dの値をc0に出力する回路である。
(今回はc1c0を一つの値としてまとめた)


演算装置

ビット演算装置

このビット演算装置の入力は二つのオペコード(op0,op1)と二つの16ビットの値(X,Y)の4つで構成されていて出力は、一つだけである。

入出力の関係は以下のようになる。

op1 op0 出力(j)
0 0 X AND Y
0 1 X OR Y
1 0 X XOR Y
1 1 Xをビット反転

これをturbowarpで実装するとこうなる
block_2025_3_19-21_56_15 (1).png

算術演算装置

この算術演算装置の入力も二つのオペコード(op0,op1)と二つの16ビットの値(X,Y)の4つで構成されていて出力は、一つだけである。

op1 op0 出力(R)
0 0 X + Y
0 1 X - Y
1 0 X + 1
1 1 X - 1

これをturbowarpで実装するとこうなる
block_2025_3_19-22_04_27 (1).png

算術論理演算装置(ALU)

この算術論理演算装置はさっき紹介した二つの演算装置を一つにまとめたもので、入力は二つのオペコード(op1,op0),二つのフラグ(sw,zx),回路選択用の入力(u)の5つから構成されていて、出力は一つだけである。
uが1の時は算術演算装置の結果を、0の時はビット演算装置の結果を出力する。
これをturbowarpで実装すると...?
block_2025_3_19-22_11_01.png
(自分で作ったのに意味わからん)

条件(condition)

この『条件』は最大3つのフラグを使用してXがそのフラグの条件を全て満たしているかを判断する回路だ。

フラグ 条件
lt 0未満
eq 0と等しい
gt 0より大きい

わかりやすくするために例を挙げよう
X ≧ 0 の時1を出力させたい場合eqgtを1にすればいい
(≧を分解すると=と>に分かれ、それを条件とするフラグはeqgtしかないためだ)

lt eq gt 1を出力する条件
0 0 0 絶対に出力は0
0 0 1 X > 0
0 1 0 X = 0
0 1 1 X ≧ 0
1 0 0 X < 0
1 0 1 X ≠ 0
1 1 0 X ≦ 0
1 1 1 絶対に出力は1

これをturbowarpで実装するとこうなる(今気づいたけどltがitになっている↓)
block_2025_3_19-22_31_34 (1).png

3.おまけ

1.今回使用した拡張機能

・ビット操作
・Lilyの道具箱
・カスタム定義

2.実際にできたcpu(+エディター)のファイル
[製作中]

3.機械語の解説
[製作中]

4.終わりに

今回はnand gameのHardwareレベルをクリアして学んだことを活かしてこの作品(CPU)を作ったが、今度はSoftwareレベルをクリアしてこの作品をもっとアップデートしていきたいと思っている。

最後まで見てくれてありがとうございました。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?