シリーズ「コンピュータの記憶のしくみ」 第7回
回路が「ずらす」とは?
隣に、つなぐ
前回の最後に、こう問いかけた。 覚えている数を、クロックが来るたびに 1 桁ずつ横へ送るには、どうすればいいだろうか。
答えから書いてしまおう。
- 各桁のフリップフロップの値 D を、隣の桁の出力 Q につなぐ。
- 端の桁の D だけは、外から値を入れる「入口」にする。
- クロックの線は、今までどおり 1 本を全員に配る。
これだけである。 新しい部品は、今回も 1 つも要らない。 前回までと違うのは、線をどこにつなぐかだけだ。
こうして、クロックが来るたびに覚えている値を隣へ送っていくレジスタを、シフトレジスタという。 シフト(shift)は「ずらす」という意味だ。
まずは、触ってみてほしい。
シフトレジスタ シミュレータ
各桁の値 D は、右隣の桁の出力 Q につないであります。右端の「入口」だけは、スイッチで選べます
箱は第5回と同じ D フリップフロップ。値は右から左へ流れる
「クロックを入れる」を押してください。1 の位の 1 が、どこへ行くかを見てください
図の「クロック」の丸を押すと、1 にしたままにできる(もう一度押すと 0 に落ちる)
押して、確かめる
箱が横に 4 つ並んでいる。左端が 8 の位、右端が 1 の位だ。
0001 と書いたときの並びと同じである。
箱の中身は、どれも第5回と同じ D フリップフロップだ。 箱の右辺に値 D、左辺に出力 Q がある。 右隣の箱の Q が、まっすぐ左隣の箱の D へ入っている。 右端の丸が入口で、1 の位の D につながっている。
いまは 1 の位だけが 1。0001 を覚えている。
「クロックを入れる」を押してほしい。
1 の位にあった 1 が、2 の位へ移った。
もう一度押すと 4 の位へ、もう一度で 8 の位へ。 押すたびに、1 が 1 桁ずつ左へ歩いていく。 入口は 0 なので、空いた 1 の位には 0 が入る。
8 の位まで来た 1 は、次のクロックでどうなるか。
左隣には、もう箱が無い。
1 は左端からこぼれて、消える。 覚えている数は 0000 になる。
今度は入口を 1 にして、何回か押してみてほしい。 右から 1 が次々に入ってきて、左へ流れていく。 入口を 1 と 0 に切り替えながら押せば、好きなパターンを流し込める。
電光掲示板の文字が、右から現れて左へ流れていくのと、よく似た動きだ。
第5回では、桁を縦に積んで描いた。 横に並べると、隣どうしがつながった鎖に見えてしまうからだった。 あの回の話は「桁どうしは、つながっていない」だったので、鎖に見えては困ったのだ。
今回は、その鎖こそが主役である。だから横に並べた。
玉突きに、ならないのか
ここで、少し引っかかってほしい。
クロックが来ると、1 の位は入口の値を受け取る。 2 の位は、1 の位の値を受け取る。
けれど 1 の位の値は、たったいま入口の値に書き換わったところではないか。 それなら 2 の位が受け取るのは、書き換わったあとの値、つまり入口の値になりそうだ。
同じ理屈で、4 の位も 8 の位も、入口の値を受け取ってしまいそうに思える。 玉突き事故のように、値が端から端まで一気に走り抜けて、全部が同じ値になる。 そう考えるほうが、むしろ自然である。
ところが、シミュレータではそうならなかった。 1 回のクロックで、値はきっちり 1 桁だけ進んだ。
何が、玉突きを止めているのだろうか。
ラッチで、作ってみる
試しに、同じ配線を第3回の D ラッチ で組んでみよう。 クロックの線は、ラッチの書き込み E につなぐ。クロックが 1 のあいだ、ラッチは開いている。
上がラッチで作った鎖、下がフリップフロップで作った鎖だ。
どちらも 0000 から始めて、入口は 1 にしてある。
配線はまったく同じである。
ラッチとフリップフロップ シミュレータ
上下とも配線は同じで、入口は 1 です。長さを選んで押すと、毎回 0000 から、上と下が同時に動きます
第3回の D ラッチで作った鎖(0000)
第4回の D フリップフロップで作った鎖(0000)
長さを「3」にして、「両方にクロックを入れる」を押してほしい。
上も下も 0001 になる。1 の位にだけ 1 が入った。ここまでは同じだ。
では、長さを「6」「9」「12」と長くしてみてほしい。
- 上(ラッチ) …
0011、0111、1111と、1 が奥まで走り込んでいく。 - 下(フリップフロップ) … 何度やっても
0001。
長さ 12 で、上は 1111 になった。
さきほど心配した玉突きが、ラッチでは本当に起きる。
第3回で見たとおり、ラッチは開いているあいだ、D を素通しにする。 入口の 1 は、1 の位のラッチを素通しで抜けて、2 の位のラッチの D に届く。 2 の位のラッチも開いているので、そこも素通しで抜けて、4 の位へ。 1 桁抜けるのに 3 ステップほどかかるので、開いている時間が長いほど、奥まで走る。
第3回では、D ラッチの出力を「+1」して D に戻したら、値が何周も回ってしまった。 開けておく長さで、答えが変わった。 今回は輪ではなく一列だが、起きていることは同じである。 あのとき「透過」と呼んだ性質が、ここでは悪さをする側に回っている。
長さ 3 のように短ければ、ラッチでも 1 桁で止まる。 けれど第4回で見たとおり、「ちょうどいい短さ」はゲートの速さしだいで、作る前には決められない。 その道が行き止まりなのは、もう知っている。
直前の値を、受け取る
では、フリップフロップは、なぜ走り抜けないのか。 中身を開いて見てみよう。
各桁のフリップフロップを、第4回と同じく、前のラッチ(上の段)と後ろのラッチ(下の段)に分けて描いた。 後ろのラッチの出力が、すきまを上って、左隣の前のラッチの D へ入っている。
シフトレジスタ シミュレータ
各桁の値 D は、右隣の桁の出力 Q につないであります。右端の「入口」だけは、スイッチで選べます
上の段が前のラッチ、下の段が後ろのラッチ(第4回)。後ろの出力が、左隣の前へ入る
「クロックを入れる」を押してください。1 の位の 1 が、どこへ行くかを見てください
図の「クロック」の丸を押すと、1 にしたままにできる(もう一度押すと 0 に落ちる)
図の左下の「クロック」の丸を押して、1 にしたままにしてほしい。
上の段の「前」が、4 つとも開になる。 開いた前のラッチは、右隣の「後ろ」の値を受け取る。 2 の位の前には 1 の位の後ろの 1 が入り、1 の位の前には入口の値が入る。
このとき、下の段の「後ろ」は 4 つとも閉だ。 前のラッチが受け取った値は、そこで止まる。 後ろのラッチは、クロックを 1 にする直前の値を、そのまま持ちつづけている。
しばらく待ってほしい。何ステップたっても、どこも動かない。 前のラッチが受け取っている相手は、閉じている後ろのラッチだからだ。 受け取った相手が動かないので、走り抜けようがない。
もう一度丸を押して、クロックを 0 に落としてほしい。
今度は前が閉じ、後ろが開く。 4 つの後ろのラッチがいっせいに、自分の前のラッチの値を受け取る。 覚えている数が、1 桁ずれた。
けれど、このとき前のラッチはもう閉じている。 ずれた値が、さらに左隣へ走り込むことはない。
1 回のクロックでやっていることは、2 段階に分かれている。
- クロックが 1 のあいだ … 全員が、隣の直前の値を、前のラッチに受け取っておく。まだ渡さない。
- クロックが 0 に落ちた瞬間 … 全員が、受け取っておいた値を同時に出す。
荷物を手から手へ渡していく、バケツリレーを思い浮かべてほしい。 ただし、全員が合図に合わせて動く、少し変わったバケツリレーだ。
1 人 1 人は、隣から受け取る手と、隣へ渡す手を、別々に持っている。 合図の前半で、隣が差し出している荷物を、受け取る手でつかむ。自分の荷物は、まだ渡す手に持ったままだ。 合図の後半で、つかんだ荷物を渡す手に持ちかえて、反対側の隣へ差し出す。
受け取る手と渡す手が分かれているから、全員が同時に動いても、荷物は 1 人ぶんずつしか進まない。 1 つの荷物が、列の端まで一気に飛んでいくことはない。
前のラッチが受け取る手、後ろのラッチが渡す手である。 第4回で、2 つの扉が同時に開かない閘門のたとえを出した。あれと同じことを、隣どうしでやっている。
隣から受け取りながら、同時に隣へ渡せるのは、書き込みが一瞬だからだ。 ラッチで作れば、値は端まで走り抜けてしまう。
第4回では、フリップフロップなら出力を自分の入力に戻せることを確かめた。 何度やっても、1 回しか進まなかった。 今回はそれが、隣どうしのあいだで起きている。 自分の出力を隣へ渡し、隣の出力を自分が受け取る。 全員が一度にそうしても、全員がちょうど 1 桁ずつ進む。
ずらすと、2 倍
ここで、覚えている数のほうに目を移したい。
最初のシミュレータで、0001 が 0010、0100、1000 と進んだ。
10 進法で読むと、1、2、4、8 である。
クロックを入れるたびに、2 倍になっていた。
計算シリーズの第6回で書いたとおり、2 進法で 1 桁左へずらすのは、2 倍することだった。 では、逆向きにずらすとどうなるか。
つなぐ向きを逆にしたシフトレジスタを用意した。 上は左へずらす。下は右へずらす。右へずらすほうは、入口が左端、こぼれるのが右端になる。 上下とも、同じ数を入れてある。クロックは 1 本を両方に配っている。
2 倍と半分 シミュレータ
上は左へ、下は右へずらすレジスタ。クロックは 1 本を両方に配っています
はじめの数は、端の入口から 1 桁ずつ流し込んでおいた。いまは入口から 0 が入る
上と下に、同じ 6(0110)が入っています。「クロックを入れる」を押してください
6(0110)のまま、「クロックを入れる」を押してほしい。
上は 1100、12。2 倍だ。
下は 0011、3。半分になった。
もう一度押すと、上は 1000、8 になる。
24 になるはずだが、16 の桁が左端からこぼれた。前回見た「15 の次は 0」と同じ話である。
下は 0001、1 になる。
3 の半分は 1.5 だが、右端からこぼれた 0.5 の桁は、どこにも残らない。
計算シリーズの第11回で見た、切り捨てそのものだ。
はじめの数を 5 にしても、同じことが起きる。5 の半分は、2 になる。
ここで、回路は掛け算も割り算もしていない。 やったのは、各桁の値を隣へ移しただけだ。
それを 2 倍や半分と読んでいるのは、桁に貼った名札のほうである。 8、4、2、1 の名札は、1 つ左へ行くたびにちょうど 2 倍になり、1 つ右へ行くたびにちょうど半分になる。 だから全員が 1 つずつ隣の席へ移れば、全体も 2 倍(半分)になる。 桁に名札を貼っているのは、回路ではなく読む側だ。計算シリーズの第4回から、ずっと言ってきたことである。
計算シリーズの第6回では、ずらすのはタダだった。 線を 1 つ隣へつなぎ替えるだけで済んだ。 前回の最後で、それはもうタダではなくなった。 クロックに合わせて、覚えている数そのものを動かさなければならない。
その代わりに、手に入れたものがある。 ずらすこと自体が、2 倍と半分という計算になっている。
3 × 5 を、回路で
材料がそろった。前回の最後に出した表を、もう一度見てほしい。 今回は、その回までにずらしてきた被乗数も書き足しておく。
| 何回目 | 見る桁 | 被乗数 → 足すもの | 合計 |
|---|---|---|---|
| 1 | 1 の位(1) | 0011 → 0011(3) | 3 |
| 2 | 2 の位(0) | 0110 → 0000(0) | 3 |
| 3 | 4 の位(1) | 1100 → 1100(12) | 15 |
| 4 | 8 の位(0) | 1000 → 0000(0) | 15 |
矢印の左が、ずらしてきた被乗数だ。
見る桁が 1 なら、それがそのまま足すものになる。0 なら、0000 に置き換わる。
2 回目は、被乗数が 0110(6)になっていても、足されるのは 0000 だ。
4 回目の 1000 は、0011 を 3 桁ずらしたものだ。
いちばん上の 1 は 4 桁からはみ出して、左端からこぼれている。
どのみち 0000 に置き換わるので、答えには効かない。
この表を、そのまま回路にする。
- 被乗数
0011は、左へずらすシフトレジスタに入れる。 クロックのたびに0110、1100と 2 倍になっていく。表の矢印の左で、ずれていく 3 である。 - 乗数
0101は、右へずらすシフトレジスタに入れる。 クロックのたびに右へずれるので、右端の 1 の位を見ていれば、1 の位・2 の位・4 の位・8 の位を順に見られる。表の「見る桁」だ。 - 合計は、前回のアキュムレータ。表の「合計」の列そのものである。
残るのは、「見る桁が 1 なら被乗数を足し、0 なら足さない」ところだ。
足さない、はどうすればいいか。前回の自動販売機で、答えはもう出ている。 0 を足せばいい。
見る桁が 1 なら被乗数をそのまま、0 なら 0000 を出す。
これは計算シリーズ第6回の「2 進法の九九」、つまり AND そのものだ。
被乗数の 4 桁それぞれと、見る桁とを AND に入れる。AND を 4 個並べればいい。
シフト加算 シミュレータ
被乗数・乗数・合計の 3 つのレジスタを、同じクロック 1 本で動かします。「クロックを入れる」を 4 回押してください
「足すもの」は AND 4 個(計算シリーズ第6回)。「合計」は第6回のアキュムレータ。はじめの数は、シミュレータが直接書き込んだ
乗数の 1 の位は 1。だから「足すもの」は 被乗数をそのまま写した 3。「クロックを入れる」で、これが合計に足される
| 何回目 | 見る桁 | 被乗数 → 足すもの | 合計 |
|---|---|---|---|
| 1 | |||
| 2 | |||
| 3 | |||
| 4 |
表は第6回の締めの表に、ずらしてきた被乗数を書き足したもの。見る桁が 0 の回は、被乗数が 0000 に置き換わる
「クロックを入れる」を、4 回押してほしい。 下の表が 1 行ずつ埋まり、4 回目で合計が 15 になる。
前回の表が、そのまま回路の上で動いた。
1 回ごとに、図の中で何が起きているかも見てほしい。 クロックが落ちた瞬間、3 つのことが同時に起きている。
- 合計が、「足すもの」を足し込む。
- 被乗数が、左へ 1 桁ずれる。
- 乗数が、右へ 1 桁ずれる。
ここで、合計が足し込んだのは、ずれる前の被乗数だ。 同じ瞬間に被乗数がずれて、「足すもの」も変わる。 それでも合計は、もう受け取り終えている。 合計の前のラッチが受け取るのは、クロックが落ちる直前の値だからだ。 さきほどのバケツリレーが、ここでも効いている。
3 つのレジスタは、互いに何も相談していない。 クロック 1 本を分け合っているだけで、表の 1 行ぶんの仕事が、そろって 1 つ進む。
最初の 3 と 5 は、どこから入れたのか
ひとつ、白状しておかなければならない。
このシミュレータの被乗数 0011 と乗数 0101 は、シミュレータが直接書き込んだものだ。
回路のほうには、最初の数を入れる口が無い。
シフトレジスタの値 D は、どの桁も隣の出力でふさがっている。 空いているのは、端の入口 1 つだけだ。 最初のシミュレータで入口から流し込んだように、1 桁ずつなら入る。 けれど 4 桁を一度に入れることはできない。 しかも、流し込んでいるあいだにもクロックは来るので、合計のほうは勝手に足し込んでしまう。
前回、アキュムレータの入口が加算器でふさがっていて、覚えている数を取り替えられなかった。 同じ問題が、今回はもっと強く出ている。
「隣の値を受け取る」ときと、「外から新しい数を受け取る」ときで、入口を切り替えられればいい。 その「選ぶ仕組み」は、次回の宿題にしておこう。
部品と、時間
計算シリーズの第6回で、2 つの方式を比べた表があった。 あの表では、シフト加算方式の「覚えておく場所」を、「要る」とだけ書いていた。
いまなら、その中身を数えられる。 フリップフロップ 1 個は、第4回のとおりゲート 9 個として数える。 時間は、このサイトのシミュレータと同じく、ゲートを 1 つ通るのを 1 ステップとして数えた。
| アレイ方式 | シフト加算方式 | |
|---|---|---|
| AND | 16 個 | 4 個 |
| 全加算器 | 12 個 | 4 個 |
| フリップフロップ | なし | 12 個 |
| ゲートの数 | 76 個 | 132 個 |
| 答えが出るまで | 17 ステップ | 52 ステップ(13 ステップ × 4 回) |
時間は、予想どおりシフト加算方式のほうがかかる。3 倍ほどだ。 1 回のクロックに要る 13 ステップは、前回のカウンタで数えたのと同じ長さである。
ところが、ゲートの数もシフト加算方式のほうが多い。 AND と全加算器は減った。 けれど覚えておく場所のフリップフロップが 12 個、ゲートにして 108 個も増えたからだ。
覚える回路は、タダではない。 4 桁では、かえって高くつく。
では、桁を増やすとどうなるか。32 桁どうしの掛け算で数えてみる。
- アレイ方式 … AND が 32 × 32 で 1024 個。32 桁の加算器が 31 個。ゲートにして、約 6000 個。
- シフト加算方式 … AND が 32 個。32 桁の加算器が 1 つ。フリップフロップが 96 個。ゲートにして、約 1050 個。
今度は逆転して、シフト加算方式は 6 分の 1 ほどで済む。 アレイ方式の部品は、桁数の 2 乗で増えていく。 シフト加算方式の部品は、桁数に比例してしか増えない。 数えてみると、7 桁あたりで入れ替わる。 その代わり、シフト加算方式は 32 回ぶんクロックを待たなければならない。
このシミュレータの作りでは、合計に残るのは 4 桁ぶんだけだ。4 桁どうしの積は、本当は 8 桁になる。 8 桁ぶん残すには、ずらす向きを工夫する作り方がある。フリップフロップの数はほとんど変わらないが、ここでは踏み込まない。
前回、覚える回路を手に入れて、回路は「時間」を使えるようになった、と書いた。 今回、それがはっきりした形になった。
部品を並べて一度に通り抜けるか、少ない部品に時間をかけて何度も通すか。 覚えておく場所のぶんを払っても、桁が大きくなるほど、時間で払うほうが得になる。 回路を作ることは、部品と時間の払い分けを決めることになった。
順番にしか、たどれない
最後に、シフトレジスタが苦手なことを見ておきたい。
シフトレジスタは、隣へ順番に送ることしかできない。 4 桁なら、8 の位の値を 1 の位まで運んでくるのに、クロックが 3 回要る。 32 桁なら、31 回だ。
もっと長い列を作って、たくさんの値を並べて覚えておいたとしよう。 10 個先の値が欲しくなったら、どうするか。 10 回クロックを入れて、手元まで流れてくるのを待つしかない。
カセットテープを思い出してほしい。 曲は、テープの上に順番に並んでいる。 5 曲目を聴きたければ、早送りして、テープが 5 曲目の頭まで流れてくるのを待つしかない。 これを頭出しという。
テープに並べておくぶんには、いくらでも覚えられる。 けれど欲しい場所へは、順番にたどっていくしかない。
たくさんの値を覚えておいて、そのうちの欲しい場所へ、一足飛びに行きたい。 10 個先の値を、10 回待たずに取り出したい。
さきほどの白状も思い出してほしい。 入れるときも、端から順番に流し込むのではなく、入れたい場所へ直接入れたい。
欲しいのは、「どこから読むか」「どこへ書くか」を選ぶ仕組みだ。
次回は、それを考えてみよう。
参考文献
- 松下俊介 著. 基礎からわかる論理回路. 第2版, 森北出版, 2021.7. 978-4-627-82842-1. https://ndlsearch.ndl.go.jp/books/R100000002-I031573740
- 馬場敬信 著. 算数で読み解くコンピュータのしくみ, 技術評論社, 2022.8. 978-4-297-12960-6. https://ndlsearch.ndl.go.jp/books/R100000002-I032268791
- ディビッド・マネー・ハリス, サラ・L・ハリス 著; 天野英晴, 鈴木貢, 中條拓伯, 永松礼夫 訳. ディジタル回路設計とコンピュータアーキテクチャ. 第2版, 翔泳社, 2017.9. 978-4-7981-4752-9. https://ndlsearch.ndl.go.jp/books/R100000002-I028478041