NANDゲートからRAMを構築する【Logisim編】
目次
はじめに
いつもブログをご覧いただきありがとうございます。
コーストFIRE中のIPUSIRONです😀
当記事はUdemyで"Computer Architecture and Design"のセクション1を受講したときのメモになります。
興味のある方は是非講座を受講してみてください。
Udemy講座の紹介
なお、Udemyで講座を購入する際には、ポイントサイトを経由することを強くおすすめします。
参考図書
ANDゲートとNOTゲートからNANDゲートを作成する
NANDゲートからRSラッチを作成する
NANDゲートをたすき掛けしたような回路です。
講座では"Active Low RS Latch"と呼んでいます。
sはセット(set)、rはリセット(reset)になります。
nqはqの上にバーがかぶせた形で表現されることもあります。
s | r | q | nq | condition |
---|---|---|---|---|
0 | 0 | 1 | 1 | Not allowed(禁止) ※本来qとnqはお互いに逆転していないとダメなので、q=nq=1は矛盾。 |
0 | 1 | 1 | 0 | Set(セット) 今回の回路はActive Lowなので、「s=0」⇒「q=1」 |
1 | 0 | 0 | 1 | Reset(リセット) 今回の回路はActive Lowなので、「r=0」⇒「q=0」 |
1 | 1 | 1 | 0 | No change(保持) |
1 | 1 | 0 | 1 | No change(保持) ※s=r=1のときは、qについて上とこの行の2状態を取り得る。 |
RSラッチからDラッチを作成する
アクティブLowだと、s(あるいはr)が0のときにセット(あるいはリセット)になります。
直感的にわかりやすいように、s(あるいはr)が1のときにセット(あるいはリセット)にしたいものとします。
このタイプをアクティブHighとします。
まずはRSラッチをアクティブHighにするのを目標にします。
アクティブLowのRSラッチをアクティブHigh化する
s | r | e | q | nq | condition |
---|---|---|---|---|---|
0 | 0 | 1 | 0 | 1 | No change |
0 | 0 | 1 | 1 | 0 | No change ※「s=r=0」⇒「s’=r’=1」⇒「アクティブLowのRSラッチの2入力が1」であり、上とこの行の2状態を取り得る。 |
0 | 1 | 1 | 0 | 1 | Reset ※r=1でリセット有効なので、アクティブHigh |
1 | 0 | 1 | 1 | 0 | Set ※s=1でセット有効なので、アクティブHigh |
1 | 1 | 1 | 1 | 1 | Not Allowed ※避けたい。 |
* | * | 0 | 1 | 0 | No change ※必ず「s=r=1」 |
* | * | 0 | 0 | 1 | No change ※必ず「s=r=1」 |
なお、e=0のときは、s’=r’=1になるので、アクティブLowのRSラッチの保持状態に該当します。
禁止状態を避けるように工夫するとDラッチになる
sからNOTゲートで分岐して、前段のNANDの入力とするようにします。
この回路では、s=r=1やs=1=0には絶対にならないので、先ほどの真理表のおける禁止状態を取らないので安心です。
s | r | e | q | nq | condition |
---|---|---|---|---|---|
0 | 1 | 1 | 0 | 1 | Reset ※r=1でリセット有効なので、アクティブHigh |
1 | 0 | 1 | 1 | 0 | Set ※s=1でセット有効なので、アクティブHigh |
* | * | 0 | 1 | 0 | No change |
* | * | 0 | 0 | 1 | No change |
この回路をDラッチといいます。
「sの1⇔0」で「qが1⇔0」を制御できます。「s=q」となっているので直感的にわかりやすいです。
※アクティブHighにした効能です。
eはビット保持の役目を持つといえます。
ゲートを減らす
前述のDラッチは5つの論理ゲートが存在しました。
実はちょっと回路を調整すると、1つのNOTゲートを削除できます。
①NOTゲートを削除した代わりに、ワイヤリングを変更します。
s | r | e | q | condition |
---|---|---|---|---|
0 | 1 | 1 | 0 | Reset ※r=1でリセット有効なので、アクティブHigh |
1 | 0 | 1 | 1 | Set ※s=1でセット有効なので、アクティブHigh |
* | * | 0 | * | No change ※保持⇒1ビットを記憶⇒記憶しているものをqから出力 |
②nqを削除します。
※使うときだけワイヤリングすればよいだけです。
「NORのたすき掛けバージョンのRSラッチ」から「アクティブHigh(レベルトリガー型の)Dタイプフリップフロップ」を作る話【参考】
ベースとする回路が若干異なりますが、話の流れとしてはこちらとほぼ同じです。
Dラッチから1ビットメモリーセルを作成する
Dラッチは1ビットを保持できるので、1ビットメモリーセルに相当します。
1ビットメモリーセルの内部回路は4つのNANDゲートで構成されたDラッチです。つまり、論理ゲートで構成されているため、メモリーの種類としてはSRAMになります。
今回のメモリーを図記号にしておきます。
Dラッチの入力sがi、入力eがs(記憶)、出力qがoに対応します。
そして、青い四角が入力、丸が出力を示しています。
1ビットメモリーセルから8ビットメモリーセルを作成する
1バイト(8ビット)分を保存するには、1ビットメモリーセルを並列に8個並べます。
入力が8ビットのSplitter、出力が8ビットのPinになります。
各メモリーセルの入力sは共通とすれば、一気に全ビットを記憶できます。
この回路の挙動を確認してみます。
①入力を0000 0111にします。s=0なので、まだ各1ビットメモリーセルの出力oはすべてEです。
②s=1にすると、全1ビットメモリーセルは入力の各iを記憶します。それと同時にoから出力します。つまり、出力は0000 0111になっています。
※「s=1」⇒「ビットを記憶+同時に出力」
③s=0にしても、何も変わりません。つまり、出力は0000 0111に維持されています。
※「s=0」⇒「入力値は無視。記憶したビットを出力し続ける」
④入力を0000 1000に変更します。まだ出力は0000 0111のままです。
⑤s=1にすると、各1ビットメモリーセルは記憶して、出力は0000 1000になります。
8ビットメモリーセルをブロック化する
この8ビットメモリーセルをブロック化します。
入力i,s、出力sはすべて8ビットです。
8ビットメモリーセルから8ビットレジスターを作る
8ビットメモリーセルを拡張して8ビットレジスターを作ります。
そのためには、8ビットイネーブル回路を用意しておきます。
8ビットイネーブル回路を準備する
8ビットイネーブル回路は、入力8ビット全体をそのまま出力するか、ゼロビット列を出力するかを、1ビットの入力で制御します。
その制御のための入力をe(Enableを意味する)とします。
ANDゲートを並列化し、片方を入力の各ビット値、もう片方を共通の入力e(制御入力)とするわけです。
複雑そうに見えて回路は単純です。
これを利用しやすいように図記号にします。
8ビットメモリーセルと8ビットイネーブル回路を連結して8ビットレジスターを作る
8ビットメモリーセルと8ビットイネーブル回路が完成しました。
次のように連結します。
- s=1のとき、入力8ビットを記憶。
- e=1のとき、記憶している8ビットを出力する。一方、e=0のときは、0ビット列のみを出力する。
この回路を図記号にします。
コントロールバッファーで出力を分離できるようにする
2つのレジスターがあり、出力oを共有した場合を考えます。
どちらかのレジスターの値を取得したいとします。取得したいレジスターの入力eに1を与えて、それ以外にはeに0を与えます。
ここではレジスターAにe=1を与えたとします。すると、内部で記憶している8ビット値が出力されます。
それと同時に、レジスターBにe=0を与えているので、0ビット列が出力されます。
2つのビット列が混合してしまい、意味不明になります。
これでは困るので、各レジスターの出力oは、e=1のときのみが導通するようにすればよいのです。
それを実現する基本回路がコントロールバッファーです。
コントロールバッファー(スリーステートバッファー)はスイッチのように機能する
コントロールバッファー(制御バッファー)を使うと回路を分離できます。スリーステートバッファーとも呼ばれます。
物理的なスイッチのように機能します。
LogisimではGatesライブラリーにControlled Bufferという名で用意されています。
コントロールバッファーを追加した8ビットレジスター
図記号にします。
8ビットレジスターからメモリーを構築する
1個の8ビットレジスターで1バイト(8ビット)を記憶できます。
目的のCPUは256バイトを記憶できるものとします。つまり、256個の8ビットレジスターが並びます。
たくさんあるのでうまく選ぶ方法を考える必要があります。
ここではよくあるメモリーマトリックスの概念を利用します。
レジスターを16行×16列に並べるのです。こうすれば、行と列を指定すれば、256個のレジスターから1個を選ぶことができます。
※交点が256個あり、この交点が1つのレジスターを指定するものと考えてください。
10進数の16(=24)は4ビット(つまり2進4桁)で表現できます。
デコーダーを準備する
4ビット値を指定して、16本のうち1本だけをONにするには、4ビットデコーダーがあれば実現できます
デコーダーの基本回路は次の記事を参照してください。
3ビットデコーダー(入力3ビット、出力8ビット)と4ビットでコーダー(入力4ビット、出力16ビット)を必要としますが、講座では用意された回路を使う方法が紹介されています。
Logisimのメニューの「Project」>「Load Library」>「Logisim Library」を選びます。ここで講座で配布されている"CPU_DESIGN.circ"ファイルを読み込みます。
4ビットデコーダーの回路を表示させます。画面に収まりきらないと思いますが、左下にある上下矢印でズームアウト・ズームインができます。
3ビットデコーダーと4ビットデコーダーの回路は次のとおりです。
4ビットデコーダーでメモリーセルの外観を設計する
デコーダーの出力は0スタートなので、前述のメモリーセルの番号もずらしてあります。
ポイントは行と列のラインが交差している部分は結線していないということです。
行と列からレジスターを確定する回路を検討する
2行2列に単純化したメモリーマトリックスで考えてみます。
2行のラインのうち1つだけが1,2列のラインのうち1つだけが1になります。行と列の2つが1になるところだけを有効にするわけなので、ANDゲートが次のように配置すればよさそうです。
なお、vはvertical("垂直"の意味)、hはhorizontal("水平"の意味)を意味しています。
1セル内の回路を設計する
ここまできたら8ビットレジスターとの接続を考察してみます。
結論から言えば、1つのメモリーセルに注目すると次の回路になります。
①に注目してください。
ここが交点が確定したときに、レジスターを確定する回路になります。
交点確定のラインと、レジスターの入力s,eそれぞれに対して、ANDゲートを通すようにしています。特別難しいことはありません。
次に②に注目します。
メモリーマトリックスにはたくさんのレジスターが並んでいます。記憶を初期化するのに、1つずつレジスターを確定して0ビット列を記憶させる処理は効率が悪いといえます。
そのために、リセット用の回路を組み込んであります。RESETが1になると、(交点確定ラインが0であっても)レジスターが記憶状態になります。そのときに入力iに0ビット列(初期化なら)を与えればよいのです。
メモリーセル上には複数のレジスターがあるので、このRESETラインは共通になります。
以上の回路を1バイトレジスターと呼ぶことにします。
図記号にすると次のようになります。
256バイトメモリーを完成させる
※実際に256バイトメモリーにすると、Logisimの動作が遅くなるので、あえて32個(2行×16列)の1バイトレジスターしか配線されていません。
回路の左上を拡大して解説します。
アドレスの上位4ビットが行用、下位4ビットが列用です。
この回路は2行×16列のメモリーセルしか利用しないので、アドレス値には0000 0000b~0001 1111bを使います。
図記号は次のようになります。
おわりに
以降ALU作成に続きます。