塩見周子の徒然日記

自分のことを塩見周子と思い込んでいるオタクです

Logisimで遊んだ

Logisimたらいう回路を作って実際にその挙動を確かめられるシミュレータをインスコしたので、これまでのハードウェア構成法の復習(?)も兼ねて遊んでみた。というか挙動をこの目で確かめられてないのでこの際に確かめてみようってワケ。


作ってみたのはこいつら
・ハーフアダー(HA)
・フルアダー(FA)
・3ビットリプルキャリーアダー
・7ビットスライスアダー
・4ビットバイナリカウンタ
・4ビットジョンソンカウンタ
・4ビットリングカウンタ


※GIFにするのがめんどいので静止画です。すんません。

・ハーフアダー
半加算器ともいう。二つのビットの足し算をして、繰り上がりがおこるかどうかの判定をしてる。下の写真は0+1を計算してる様子。上の方が下位ビットを表しており、演算結果が01(十進法では1)なので上が立ってる。1+1なら結果は10になるので下のビットが立つ。
実装は簡単で、下位ビットと上位ビットの導出をそれぞれ分けて行えば良い。(下位ビットはXOR、上位はAND)
f:id:saguh:20191124023126p:plain


・フルアダー
全加算器ともいう。さっきのハーフアダーの拡張みたいな感じで、これは三つのビットの足し算の結果を返す。ハーフアダーを2つ組み合わせて使うとフルアダーになる(というかこれがハーフアダーの名の由来)。下の写真では1+1+1をしている(出力は11(十進法で3になっている)。
f:id:saguh:20191124025931p:plain


・3ビットリプルキャリーアダー
二進法で3桁の数字(つまり0~7)を表す二つの数字の足し算を行う。流れとしては、まず一の位の足し算を行い、その結果を受けて(繰り上がりも含めて)次に二の位、それから四の位と足し算を行う。繰り上がりの結果を持ち越す為にフルアダーを横に並べて使っているところがポイント。下の画像では7+3(つまり111+010。a1,a2,a3はそれぞれ前者の一、二、四の位。b1,b2,b3はそれぞれ後者の一、二、四の位)を行なっている様子。結果として1010(十進法だと10)が計算されてる。
※最初のFAの入力の一つはGroundに接続(つまり0が入っている)されている。
f:id:saguh:20191124030727p:plain


・7ビットスライスアダー
7個のビットの足し算を行い、その結果を0~7を表すビットとして返す。4つのフルアダーで実現される。
三段構成になっていて、一段目(FA2個)で6つのビットを3つ、3つにわけて足し算を行う。
二段目で、一段目の結果の一の位(2つ)と、最初に足されなかったビット1つの足し算をFAで行う。この出力で一の位が確定する。
三段目で、一段目の結果の二の位(2つ)と、二段目の結果の二の位の合計3つをFAで足し合わせて、二の位と四の位を確定させる、という流れでやっている。
下の画像では6つの1の足し算を行なっている様子。結果として110(十進法だと6)が出力されている。
f:id:saguh:20191124031758p:plain


・4ビットバイナリカウンタ
まずはカウンタのお話から。カウンタはその名の通り「数える」ことができる機構であり、それを回路で実現することを考える。
回路は電気信号のやりとりで動いていて、単位時間あたりのやりとりの回数(もしくはやりとり自体)を「クロック」と呼ぶ。
このクロックを「0,1のスイッチ」とみなして、これのオンオフでカウンタを動かしていくことを基本としている。

バイナリカウンタは、「n個の『ラッチ』と呼ばれる機構を用いて、0~2^n-1までを表現できるカウンタ」である。ラッチは「1ビットの状態を保存できる機構」であり、ここで保存された0,1が、表したい数字のビット列を構成している。フリップフロップとも呼ばれる。(某アイドル育成ゲームの曲ではない)
このバイナリカウンタで用いるラッチは「JKラッチ」と呼ばれるもので、このラッチは2つの入力J,Kがどちらも1である場合、出力(保存された状態)をクロックに合わせて変化させることができる。(クロックが1->0->1->0->1->0->.....と変化すると、出力Qが1->0->1->......と変化する感じ)この性質を用いて、クロックの立ち上がり(01の周期のうち、1になる時)ごとに各ラッチのバイナリの状態を変化させていくのが、バイナリカウンタの基本原理である。

[以下はLogisimの使い方であげた2つめのサイトから引用した。]
一番左のSマークがクロックで、このクロックの立ち上がり(電気が通る=1=薄い緑)で、一番左側のJKフリップフロップが動作します。クロックが薄い緑になるたびに、JKフリップフロップの出力Qが、薄い緑(=ON)または濃い緑(=OFF)になります。

出力Qを次のJKフリップフロップのクロック入力に繋げているのがポイントです。出力Qと出力~Q(Qの否定を表す。図中のQの下にある薄い「0」のところ。Qが1なら~Qは0、Qが0なら~Qは1)が交互になるという事は、入力信号に対してQは1/2でしかONにならなくなります。よって右隣りのJKフリップフロップは1/2の速度の動作になっていきます。

                  • -

以下はバイナリカウンタで2を数えている時の状態。2つ目のラッチだけQが0になっていて、そこだけ(~Q=1より)ビットが立ち上がっている。この後、クロックが再び立ち上がると、1つ目のラッチのQが0になり、~Qが1になることで一の位のビットが立つ。よって、0011(つまり3)を表すことになる。
f:id:saguh:20191124035316p:plain

3の次は4になる。以下の画像は3を数えた後の状態で(クロックが立ち上がって、再び0になった)次にクロックが再び立ち上がると、まず1つ目のQ(出力)が反転し、それが2つ目のラッチのクロックとして機能して2つ目のラッチのQ(出力)が反転して1になる。すると、さらに3つ目のラッチに入るクロックが立ち上がることになるので、3つ目のラッチのQも反転する。よって、1,2つ目のラッチの~Qは0になり、3つ目のラッチの~Qは1になる。以上より、0011だったビットが0100に変化し、4を表すことになる。
f:id:saguh:20191124035939p:plain


↓ほらね?
f:id:saguh:20191124040111p:plain


・4ビットジョンソンカウンタ
ジョンソンカウンタは、n個のラッチで2n個の状態を表現する。例えば、4ビットであれば、0000->1000->1100->1110->1111->0111->0011->0001->0000->......という風な変化を経ることで8つの状態を表すことができる。

構造は、Dラッチ(Dフリップフロップ)というラッチをつなげて作る。Dラッチは入力がDとクロックの二つ(ジョンソンカウンタを作る際には三つだが、これは後述する)と、出力Qの一つからなる。Dが1になったら、次のクロックの立ち上がりで出力Qが1に、逆にDが0になったらQは0になるという、DとQが1クロック分遅れた動きをする。(クロックが0の時、D,Qには影響がない)

ジョンソンカウンタは出力Qをそのまま追って見ていけばよく、ラッチの出力Qが後ろにつながるラッチの入力Dになっている(ム○デ人間とか言わない)。ただ、注意するのは最後のラッチの出力Qを先頭に巻き戻すのではなく、~Qの方を先頭の入力Dにするところである。これをしないと例で挙げたぐるっと一周しなくなってしまう。

下の図では、次に動くのは3つ目のラッチのQである。これからクロックが再び立ち上がることで、入力Dが1クロック分遅れてQに伝わり、その結果として出力を4つ並べると1110になる。
f:id:saguh:20191124050543p:plain

上の図では、Dラッチの二つの入力に加えて下から1が入力されている。実はこれがなくても正常に動作するのだが、これがないとこのカウンタがバグった時に元に戻らなくなってしまう。ジョンソンカウンタはn状態のうち、2n状態しか使わず、残りの2^n-2n個の状態は使われない。
もしジョンソンカウンタの内部状態がなにかの拍子でその使われない状態に遷移してしまった場合、本来実現すべき数字表現ができなくなるループに陥ることが考えられる。(例えば、4ビットの場合、0100->1010->1101->0110->1011->0101->0010->1001->0100->......というループになった場合、これは正常な動作ではない)
これを回避するために、もしこのようなまずいループに陥った時に一旦リセットをかける意味で、Dラッチの下から1が入力されている。これが1になる時、ラッチの出力Qは強制的に0になる(つまりジョンソンカウンタの0000に状態がリセットされる)。
※本当はリセットの時だけ1になるべきで、普段は0になっているべきなんですけど、実際に動かしてみたらここが0だと回路が回らなくなってしまったのでなんか間違えてるのかも?


・4ビットリングカウンタ
n個のラッチでn状態を表現するクソ贅沢なカウンタ。各状態では必ずビットが1つだけ立っており、1000->0100->0010->0001->1000->......と状態が遷移する。

ジョンソンカウンタと同じく、前のDラッチの出力Qを後ろのDラッチの入力Dにするようにつなげて使う。最初のラッチの入力Dは、最後以外のラッチの出力QのNORを取ればよい。なぜなら、最後の出力Qが1になる時以外は必ず、最後以外のどこかのラッチの出力Qが1になっているため、NORの出力は0になり、最後が1になる時だけNORが1になり、最初に入力として1を施すという仕組みが構成されるからである。
また、これもジョンソンカウンタと同じように、バグった時用のリセット手段として、Dラッチの下から1を入力しておく。
f:id:saguh:20191124053500p:plain
上の画像は0001の時の様子。NORが働いて最初のラッチの入力に1が入り、次のクロックの立ち上がりで最初のラッチの出力Qが1になり、1000に移行する。




Logisimの使い方↓
論理回路シミュレータ Logisim の使い方
hajimete-program.com



実際にLogisimで回路を書いている人の様子↓
www.youtube.com


回路関連で参考になりそうなページ↓
daisan-y.private.coocan.jp