1. 順序回路
これまで学んだ組合せ回路は、入力が決まれば出力が一意に決まる回路でした。例えば、論理回路の簡単化と回路設計の章で設計した半加算器・全加算器やデータセレクタがその例で、加算器に「3」と「5」を入力すれば、必ず「8」が出力されます。過去にどんな入力があったかは、出力に影響しません。
しかし、コンピューターが計算を行う際には、以下のような状況があります。
-
「3 + 5 =」を計算 → 結果「8」
-
続けて「+ 2 =」を計算 → 結果「10」
この2番目の計算では、前回の結果「8」を覚えておく必要があります。つまり、過去の状態を記憶する機能が必要になります。
このように、「現在の入力」だけでなく「過去の状態」も考慮して出力を決める回路を順序回路と呼びます。
-
100円を入れる → 「100円投入済み」状態
-
さらに50円を入れる → 「150円投入済み」状態
-
120円の商品ボタンを押す → 商品が出る + 30円のお釣り
この動作では、自動販売機が「これまでにいくら投入されたか」を記憶しています。
順序回路は、組合せ回路と記憶装置(メモリ)から構成される回路です。多くの場合、状態を更新するタイミングを揃えるためにクロックを併用します(同期式順序回路)。上図にあるように、組合せ回路への外部からの入力に加えて、記憶装置に蓄えた前回の組合せ回路の計算結果を入力として加えます。そうして、得られた出力を記憶装置に蓄え、次の計算で、組合せ回路への入力の一部として用います。こうして、時間とともに状態が遷移することになります。
-
記憶装置: 前回の計算結果を保存
-
クロック: いつ状態を更新するかのタイミング信号
-
フィードバック: 記憶した値を次の計算の入力として使用
コンピューターは、内部の記憶装置に状態を記録しながら、その記録をまた利用して処理をしていますので順序回路です。この章では、状態を記憶するためのメモリを実現する論理回路について学びます。
2. メモリの実現
2.1. 記憶装置の種類
パソコンを買うときに、メモリ(RAM)が8GBあるとか16GBあるとかいうときのメモリは、主記憶装置を指します(メモリ容量の表記では、慣習としてGBが \(2^{30}\) バイト単位のGiBを表すことに注意)。主記憶装置は、コンピューターの心臓部である中央処理装置(CPU: Central Processing Unit)で処理するプログラムや計算のためのデータを蓄えたり、結果を書き込んだりします。磁気テープなどのように決まった順序通りにデータを読み込んだり書き込んだりするシーケンシャル・アクセス・メモリ(Sequential Access Memory)ではなく、記憶装置の領域の様々な場所に番地を介してアクセスできるため、RAM(Random Access Memory)と呼ばれるメモリの一種です。
一般的なパソコンの主記憶に使われるDRAMは、電源が入っているときだけデータを記憶することができます。このように、電源が切れると記憶を保持できない記憶装置を、揮発性メモリといいます。代表的なDRAMの1ビットの記憶セルは、1つのキャパシタ(コンデンサ)と1つのトランジスタによって最小単位が構成されています。キャパシタは、2つの導体を絶縁体で挟んだ構造をしており、電荷を蓄えることができます。この電荷が蓄えられている(充電)か、いない(放電)かで、1ビットのデータ(1か0)を保持します。蓄えた電荷はトランジスタなどの漏れ電流によって少しずつ失われるため、放電しきる前に、繰返しデータを書き込み直す必要があります(例えば64ミリ秒以内に全行をリフレッシュする製品がありますが、必要な間隔は温度や製品仕様によります)。この動作をリフレッシュといいます。頻繁に再充電をしなくてはならない性質のために、キャパシタにより記憶保持をするタイプのメモリは DRAM(Dynamic RAM)と呼ばれています。
CPUの処理速度と比較すると、DRAMの読み書きに要する時間は非常に長く、読み出しを要求してから値が届くまで、CPUの数百クロック分待つこともあります。ただし、複数の要求を並行して処理できるので、「数百クロックに1回しか読めない」という意味ではありません。待ち時間(レイテンシ)と、単位時間に運べる量(帯域幅)は別です。すぐに読みたい本があって、図書館で予約したら借りられるまで1ヶ月待たされるようなものです。いったん借りてきた本は、家の手近な本棚において、貸出期間中はいつでも読める状態にしておきたいですよね。コンピューターでも事情は似たようなもので、主記憶装置ほどの容量はないけれども、より高速なメモリをCPUと主記憶装置の間に配置して効率を上げています。このような記憶装置をキャッシュといいます。この用途で用いられるのが、これから紹介する SRAM(Static RAM)です。SRAM は DRAM よりも読み書きは高速です。一方で、SRAMの方が記録密度は低く、記憶容量あたりの単価は高いため、一般に主記憶装置としては用いられていません。
|
コラム: コアメモリと「コアダンプ」
半導体メモリが普及する前、1950年代から1960年代の主記憶装置は磁気コアメモリでした。これは、フェライト(磁性体)でできた小さなドーナツ状のリング(コア)に細い導線を手作業で通したもので、リングの磁化の向きで1ビットを記憶します。電源を切っても磁化は残るため不揮発性です。コアに導線を通す作業の多くは手作業で、1970年にはIBMだけで年間200億個ものコアを生産していたとされます。 1970年にIntelが発売した 1103 は、容量1Kビット(1024ビット)の世界初の商業的に成功したDRAMでした。1ビットあたり約1セントという価格で、1972年には世界で最も売れた半導体メモリチップになりました。これをきっかけに主記憶は磁気コアメモリから半導体メモリへと置き換わり、1970年代の終わりにはコアメモリはほぼ使われなくなります。なお、現在のDRAMで標準的な「1トランジスタ+1キャパシタ」のセル構造は、IBMのRobert Dennardが1968年に特許を取得したもので、1103自体はまだ3トランジスタ方式でした。 プログラムが異常終了したときに、デバッグのためメモリの内容をファイルに書き出すことを、今でも「コアダンプ(core dump)」と呼びます。この「コア」は、磁気コアメモリの名残です。 |
2.2. SRAMの構成要素
以降では、出力を入力に戻して1ビットを保持する仕組みを、SRラッチなどで学びます。典型的なSRAMセルは、2つのインバーターと読み書き用トランジスタなどから構成されます。以下のNORゲートによるSRラッチやDフリップフロップは、保持の原理を学ぶための回路であり、SRAMセルそのものの回路図ではありません。
1ビットを記憶する回路
1ビットを記憶する記憶装置を設計します。まず、下の図のようにNOTゲートを2つつなぐと、左と右で2つの状態が存在することがわかります。この2状態で、1ビット、つまり0と1を記憶する装置を設計します(下図参照)。
そこで、上図の下側のNOTゲートの方向を上側のNOTゲートと同じ方向にしてから、値を読み取る出力線を外にのばします。\(Q\) と \(\overline{Q}\) のように、2つの出力は反転して相補的な関係にあります(下図参照)。アルファベットの \(Q\) が用いられるのは慣習です。コンピューター科学分野では、状態を \(Q\) でよく表現します。メモリのビット状態を表すので、\(Q\) というわけです(図と Q の書体が異なるのはご容赦ください)。
次に、2つのNOTゲートをNORゲートに置き換えます。NORゲートの2つの入力に同じ値 \(x\) を入れると、\(\overline{x+x}=\bar x\) となり、NOTゲートと同じ働きをします(下図参照)。
このままでは、1ビットを記憶させることができませんので、NORゲートの空いている方の入力から外へ線をのばし、上側の値を \(R\)、下側の値を \(S\) とします。それぞれ、記憶させるビットの Reset と Set を表しています(下図参照)。
この回路を、SRラッチとよびます。ビットの保持をドアの開閉になぞらえて、英語でかんぬきを意味するラッチを用います。 上図の論理回路の振る舞いについて、見ていきましょう。これまでの組合せ回路とまったく勝手が違うのは、出力側の線が入力に戻ってきていることです。NORゲートは、入力が1つでも1であれば、出力は0になること、入力が両方とも0のときのみ出力は1になることを思い出しておいてください。
-
\((S,R)=(1,0)\): 「1を記憶させろ」という命令(Set)
-
\((S,R)=(0,1)\): 「0を記憶させろ」という命令(Reset)
-
\((S,R)=(0,0)\): 「今の状態を保持しろ」という命令(保持)
-
\((S,R)=(1,1)\): 「1も記憶、0も記憶」→ 矛盾するので禁止
これらを1つずつ確かめます。以下の図では、値が1の配線を青、0の配線を赤で示しています。
- 《1》 \((S,R)=(0,1)\)のとき
-
\(R=1\) より \(Q=0\)、となり、下のNORゲートの入力は、\((Q,S)=(0,0)\) と確定するので、\(\overline Q=1\) となります。
- 《2》 \((S,R)=(1,0)\)のとき
-
回路の対称性より、上の例と逆になりますので、直ちに \(Q=1\)、\(\overline Q=0\) となることがわかります。
- 《3》 \((S,R)=(1,1)\)のとき
-
両方のNORゲートの入力に1があるため、NORゲートの出力は両方とも0に確定します。よって、\((Q,\overline Q)=(0,0)\) となります。このとき、\(Q=\overline Q\) となり、記号の意味と矛盾しているように見えます。この状態から両入力を同時に0に戻すと、回路のわずかな遅延差などで最終的な保持値が変わり、準安定状態になる可能性もあります。このため、通常の記憶動作では禁止入力とします。
- 《4》 \((S,R)=(0,0)\)のとき
-
上下のNORゲートの出力は、\(Q\) または \(\overline Q\) の値が決まらなければ、確定することができません。そのため、さらに次のように場合分けをします。
- 《4.1》 \(Q=0\) のとき
-
下のNORゲートの入力は\((Q,S)=(0,0)\) となり、\(\overline Q=1\) となります。このとき、上のNORゲートの入力は\((R,\overline Q)=(0,1)\) となり、出力が \(Q=0\) と矛盾しないことも確認してください。
- 《4.2》 \(Q=1\) のとき
-
下のNORゲートの入力は\((Q,S)=(1,0)\) となり、\(\overline Q=0\) となります。このとき、上のNORゲートの入力は\((R,\overline Q)=(0,0)\) となり、出力が \(Q=1\) と矛盾しないことも確認してください。
以上の振る舞いを下の表にまとめました。ただし、状態変数 \(Q\) に、以前の状態から次の状態が決まることを明示するために時間の添字をつけています。
| 場合分け | \(S\) | \(R\) | \(Q_{t+1}\) | \(\overline Q_{t+1}\) | |
|---|---|---|---|---|---|
《4》 |
0 |
0 |
\(Q_t\) |
\(\overline Q_t\) |
状態維持 |
《1》 |
0 |
1 |
0 |
1 |
Reset |
《2》 |
1 |
0 |
1 |
0 |
Set |
《3》 |
1 |
1 |
0 |
0 |
禁止 |
これは、時刻 \(t\) の出力 \(Q_t\) をフィードバックして、\(S\)と\(R\) の値と合わせて入力として、次の時刻 \(t+1\) の出力 \(Q_{t+1}\) を決めるため、入力が \(S\), \(R\), \(Q_t\) のとき、\(Q_{t+1}\) を出力とする論理関数と考えることができます。これを表にしてみると、次のようになります。
| 場合分け | \(S\) | \(R\) | \(Q_t\) | \(Q_{t+1}\) | |
|---|---|---|---|---|---|
《4》 |
0 |
0 |
0 |
0 |
状態維持 |
《4》 |
0 |
0 |
1 |
1 |
状態維持 |
《1》 |
0 |
1 |
0 |
0 |
Reset |
《1》 |
0 |
1 |
1 |
0 |
Reset |
《2》 |
1 |
0 |
0 |
1 |
Set |
《2》 |
1 |
0 |
1 |
1 |
Set |
《3》 |
1 |
1 |
0 |
* |
禁止 |
《3》 |
1 |
1 |
1 |
* |
禁止 |
この表で、出力の値が「*」となっている部分は、入力 \((S,R)=(1,1)\) を禁止することにしているので、禁止している入力の出力が0でも1でも気にしないという意味でドントケア(don’t care)と呼ばれます。この表をもとに、カルノー図を作成すると下図のようになります。論理回路の簡単化と回路設計の章ではカルノー図とドントケアを使って組合せ回路を簡単化しましたが、ここでは同じ手法を、出力が入力に戻ってくる順序回路の式(特性方程式)の導出に応用します。
カルノー図で、ドントケアを囲んでいるのは、ここが0でも1でも構わないため都合よく解釈すればよいからです(とにかく、できるだけ広く囲めるようにすればよい)。すると、以下の式が導出されます。
これを、SRラッチの特性方程式といいます。特性方程式によって、SRラッチの振る舞いの見通しがよくなりました。「\(S=1\) なら1になる。そうでなければ、\(R=0\) のときだけ今の値 \(Q_t\) を保つ」と読めます。
状態の変化を、状態を丸、入力による移り変わりを矢印で表したものを状態遷移図といいます。SRラッチの状態遷移図を下図に示しました。禁止入力 \((S,R)=(1,1)\) は描いていません。
|
コラム: SRラッチでスイッチの「チャタリング」を取り除く
SRラッチは、メモリの中だけで使う部品ではありません。身近な応用にチャタリング除去(debounce)があります。 機械式のスイッチやボタンは、押した瞬間に金属の接点が物理的に何度か跳ね返り、ほんの数ミリ秒のあいだ ON/OFF を細かく繰り返します(チャタリング)。この信号をそのままコンピューターに入れると、1回押しただけなのに何回も押したと誤認されてしまいます。 そこで、切り替え式のスイッチをSRラッチにつなぎます。両方の接点に同時に触れない方式を使い、接続されていない入力はプルダウン抵抗で0に保ち、接続された入力は1になる回路を考えます。入力を単に宙に浮かせるだけでは0にはなりません。接点がいったん \(S\) 側に触れて \(Q=1\) になれば、その後に接点が跳ね返って宙に浮いても \((S,R)=(0,0)\)(保持)になるだけで、\(Q\) は1のまま安定します。ラッチの「いちど決めた値を保持する」性質が、跳ね返りのノイズを吸収してくれるわけです。この章で作った回路が、そのまま実世界のノイズ対策に使われています。 |
2.3. ゲーテッドSRラッチ
SRラッチは、そのままでは入力の値の変化がそのまま反映されてしまいます。入力の値が変化するとき、出力の値が安定しない現象があり、このような信号がそのまま再び入力に伝わるのは好ましくありません。そのため、入力から値を読み取るタイミングを制御できるようにSRラッチの前に門(ゲート)になる回路を入れたのがゲーテッドSRラッチです。
この回路は、\(E=1\) のときのみ、入力 \(S\), \(R\) の値をSRラッチの入力として伝え、\(E=0\)のときは、\((S',R')=(0,0)\) がSRラッチの入力となります。つまり、SRラッチでは以前記憶した値が保持され変化しません。この動作は、ANDゲートでは入力に1つでも0の値があれば、出力が0となることから明らかです。記号 \(E\) は、SRラッチの機能を「有効にする」ということで、enable に由来します。
2.4. ゲーテッドDラッチ
ゲーテッドSRラッチでは、\(E=0\) のときに値が保持されるようになったため、入力に \((S,R)=(0,0)\) を想定する必要がなくなりました。\(S\)と\(R\)でコントロールするのは、値のセットかリセットのみでよくなったため、\(D=S=\overline R\) としてしまいます。そうすると、SRラッチで禁止としていた入力パターンが入る事もなくなります。\(D\) は、入力するデータを表す信号なので、記号Dを用いています。この回路をゲーテッドDラッチとよびます(左下図参照)。また、この回路をまとめて右下図のように表現します(この図では、\(D\) と \(E\) の相対的な位置は入れ替わっています)。
この回路の振る舞いを確認しておきます。\(E=1\) のときのみ、\(D\) の値を \(Q\) に伝え、\(E=0\) のときは、入力 \(D\) の値を無視して、直前の \(Q\) の値を保持し続けます。表にまとめると次のようになります(\(\ast\) は0でも1でも同じという意味です)。
| \(E\) | \(D\) | \(Q_{t+1}\) | |
|---|---|---|---|
0 |
\(\ast\) |
\(Q_t\) |
保持 |
1 |
0 |
0 |
0を記憶 |
1 |
1 |
1 |
1を記憶 |
このような動作を時系列で観察したのが下の図です(タイミングチャートとよびます)。矩形波が高い値のとき1、低い値のとき0を表しています。上端の0〜14の数字は時刻を表しています。
まず、時刻0から3までの間、\(D=1\) となっていることに着目してください。時刻0から1までは、\(Q\) に \(D\) の値が反映されていません。ところが、時刻1で、\(E=1\) となったタイミングで \(D\) の値が読み込まれ、\(Q=1\) となっています。\(E=1\) の間は、\(D\) の値は即座に \(Q\) に伝播しますので、時刻3で \(D=0\) となったとたんに \(Q=0\) となっていることがわかります。
時刻9で \(E\)が1から0になる前に、\(D=1\) の値が \(Q\) に読み込まれているため、時刻10から11まで \(D=0\) となった後も、\(Q\) に値は保持され1のままです。また、時刻12で \(E\) が1から0になる前に、\(D=0\) の値が読み込まれているため、時刻13から \(D=1\) となった後も、\(Q=0\) のままで、値が保持されます。
2.5. Dフリップフロップ
透過的動作の問題点
ゲーテッドDラッチには重要な問題があります。\(E=1\)の間、入力\(D\)の変化がそのまま出力\(Q\)に伝わってしまいます。これを「透過的(transparent)」と呼びます。
しかし、デジタル回路では「特定の瞬間の値だけを読み取りたい」場合が多くあります。例えば、ネットワークから送られてくるデータを正確なタイミングで読み取る場合などです。
エッジトリガー方式の考案
そこで考案されたのがエッジトリガー方式のDフリップフロップです。Dフリップフロップは、ゲーテッドDラッチを左下図のように2段につないで、入力を受け付けるタイミングを制御する\(E\) 部分への入力を、1段目のラッチには反転させて入力し、2段目のラッチではそのまま入力しています。CLK信号はクロックを表し、固定周期で0と1を繰り返す信号です。この左下図の回路を、まとめて右下図のように表します。
(図では最終出力を \(Q_2\)、1段目の出力を \(Q_1\) と表記していますが、本文の \(Q\) は図の \(Q_2\) にあたります)
Dフリップフロップの名前の由来は、データ(Data)を保持するからとも、入力データを時間をおいて出力するからともいわれています(後者の場合は、delayのD)。フリップフロップ(flip-flop)はパタパタと変わる様子を意味します(英語でビーチサンダルを "flip-flops" と呼ぶのも、歩くときのパタパタという音に由来します)。
2つの門のアナロジー
Dフリップフロップは、ゲーテッドDラッチを2段つないだものでした。この2段重ねの動きは、銀行やビルの入口にある二重扉(宇宙船のエアロックや、運河の水位を調整する閘門(こうもん)も同じ仕組みです)に例えると分かりやすくなります。
二重扉では、外側の扉と内側の扉が同時には開きません。外から入った人は、いったん扉のあいだの小部屋に入り、外側の扉が閉まってから、はじめて内側の扉が開いて中へ進めます。こうして、外と内が一直線につながってしまうこと(素通し)を防いでいます。
Dフリップフロップでも、1段目のラッチが「外側の扉」、2段目のラッチが「内側の扉」にあたります。ここでいう「扉が開く」とは、ラッチが透過状態(\(E=1\))になって値がそのまま通り抜けることを、「扉が閉じる」とは、ラッチが保持状態(\(E=0\))になって値をせき止め、中の値を保つことを指します。
2つの扉は、クロック \(\mathrm{CLK}\) によって逆向きに開閉します。1段目には反転した \(\overline{\mathrm{CLK}}\) が、2段目にはそのままの \(\mathrm{CLK}\) が入るためです。
| \(\mathrm{CLK}\) | 1段目の門(外扉) | 部屋の中 \(Q_1\) | 2段目の門(内扉) | 出力 \(Q\) |
|---|---|---|---|---|
0 |
\(E=\overline{\mathrm{CLK}}=1\) → 開 |
\(D\) の値が入ってくる |
\(E=\mathrm{CLK}=0\) → 閉 |
直前の値を保持 |
1 |
\(E=\overline{\mathrm{CLK}}=0\) → 閉 |
せき止められ保持 |
\(E=\mathrm{CLK}=1\) → 開 |
\(Q_1\) の値が出ていく |
\(\mathrm{CLK}\) が0から1に変わる瞬間に、外扉が閉まると同時に内扉が開きます。このとき、部屋にあった値(=立ち上がりの瞬間の \(D\))だけが出口へ押し出され、それ以降は外から新しい値が入れません。この回路では、こうして「立ち上がりの瞬間の \(D\) だけを読み取って記憶する」エッジトリガーの動作が実現されます(実際の集積回路のフリップフロップには、別の構成のものもあります)。
Dフリップフロップは、CLK(図の▷の端子)の値が0から1に変化する瞬間だけ、\(D\) から値を読み込み、その値を記憶し続けます。
表にまとめると次のようになります。ラッチの表と違い、「いつ」値を取り込むかがクロックの変化で決まります。
| \(\mathrm{CLK}\) | 出力 \(Q\) |
|---|---|
0から1に変わる瞬間(立ち上がり) |
直前の \(D\) の値になる |
それ以外(0のまま、1のまま、1から0に変わる) |
直前の値を保持 |
\(n\) 回目の立ち上がりの直後の出力を \(Q_{n+1}\)、その立ち上がりの直前の入力を \(D_n\) と書くと、\(Q_{n+1}=D_n\) と表せます。これがDフリップフロップの特性方程式です。時刻の刻みを「クロックの立ち上がりごと」と考えると、Dフリップフロップは入力を1クロック分遅らせて出力する回路だといえます。
1段目(外扉)の出力 \(Q_1\)(=部屋の中の値)と、最終出力 \(Q\) の関係を時系列で見ると下図のようになります。\(\mathrm{CLK}=0\) の間は外扉が開いていて \(Q_1\) が \(D\) を追いかけますが、出力 \(Q\) が変わるのは立ち上がりの瞬間だけです。
\(\mathrm{CLK}=0\) の区間で \(D\) が一時的に変化しても(図の時刻4〜5で \(D\) が一度0に下がっています)、立ち上がりの瞬間に \(Q_1\) にあった値だけが \(Q\) に伝わります。これが、ゲーテッドDラッチ(透過的)との決定的な違いです。
以下が、タイミングチャートの例です。
CLKの立ち上がり(赤い縦の点線)で、\(D\)の値を読み取り、\(Q\) に保持していることが読み取れるでしょうか。このタイミングチャートでは、\(Q\) に値が反映されるタイミングがやや遅くなっていることがわかるように誇張して時間の遅れを表現しています。これまで示したタイミングチャートでも厳密にはこのような遅延は存在していましたが、この図では説明のためにこの遅延をはっきりわかるように示しています。論理演算素子を通過する度にこのような遅延が生じます。これは、前章「論理回路の簡単化と回路設計」の「論理回路の遅延時間」の節で学んだ、ゲートの伝搬遅延に対応します。遅延の具体的な値は素子や負荷などで変わります。フリップフロップは複数のゲートを段に重ねた回路なので、入力から出力までにこの遅延が積み重なります。
エッジトリガーの利点
-
データを取り込む時間を限定できる: 立ち上がりの瞬間の前後のごく短い時間だけ \(D\) が安定していれば、それ以外の時間に \(D\) が変化しても出力に影響しない(必要な時間の条件は、下のコラムのセットアップ時間・ホールド時間)
-
タイミング制御: いつデータを取り込むかを、クロックで正確に制御できる
-
同期設計: 複数のフリップフロップを同じクロックで同期動作させられる
これにより、コンピューターの中の膨大な数のフリップフロップが、クロックに合わせて足並みをそろえて動作できるのです。
|
コラム: 一瞬どっちつかずになる「準安定状態」
フリップフロップが値を正しく読み取るには、立ち上がりの少し前から少し後まで \(D\) の値が安定している必要があります(この時間の余裕をセットアップ時間・ホールド時間といいます)。もし \(D\) が変化するタイミングとクロックの立ち上がりがちょうど重なってしまうと、出力が0でも1でもない中途半端な電圧でしばらくフラフラする準安定状態(metastability)に陥ることがあります。これは、SRラッチで \((S,R)=(1,1)\) から両入力を同時に0に戻したときの問題(競合状態)と似た現象で、どちらも2つの安定状態のどちらに落ち着くかがすぐには決まらない状態です。 準安定状態がいつ解消するかは確率的にしか決まりません。鉛筆を芯の先で立てようとすると、倒れる向きが決まるまで一瞬ぐらつくのに似ています。とくに、別々のクロックで動く回路どうしをつなぐ場面(非同期)で問題になり、フリップフロップを2段重ねて誤動作の確率を十分小さくする、といった対策がとられます。ただし、2段の同期化は主に1ビットの信号の取り込みに使う方法であり、確率を厳密に0にするものでも、複数ビットを必ず一括して正しく取り込む方法でもありません。 |
|
エッジトリガーは、クロック信号の立ち上がり(または立ち下がり)の瞬間にだけ動作することを意味します。これは運動会のスタートに例えることができます。「ヨーイ、ドン!」の「ドン!」の瞬間だけでスタートし、その前の「ヨーイ」では動かないのと同じです。 |
|
コラム: フリップフロップのはじまり
2つの素子を互いに接続して2つの安定状態をつくる、というSRラッチの考え方は、コンピューターよりもずっと古くからありました。1918年、イギリスの物理学者William EcclesとFrank Jordanは、2本の真空管を組み合わせた回路の特許を出願しました。Eccles-Jordan回路(トリガー回路)と呼ばれるこの回路が、フリップフロップの祖先です。 おもしろいことに、2人はこれをコンピューターの部品として考えていたわけではなく、特許では、電信や電話の信号を中継・増幅する継電器(リレー)として説明しています。1919年に発表した論文では、この回路を「トリガー継電器」(信号をきっかけに状態が切り替わるリレー)と呼んでいます。その後、1932年にはイギリスのWynn-Williamsがこの種の回路を使って、放射線の粒子を2進法で数える計数器(scale of two counter)を作っています。1948年には、情報理論をつくったClaude Shannonが論文の中で、2つの安定状態をもつリレーやフリップフロップ回路は1ビットの情報を蓄えられる、と書いています。 この回路は、第二次世界大戦中の1943年にイギリスで暗号解読のために作られた Colossus や、アメリカの ENIAC にも使われ、初期のコンピューターの記憶素子となりました。いま手元のスマートフォンやPCの中で動いている膨大な数のフリップフロップは、100年前の真空管2本の回路の子孫です。 |
2.6. シフトレジスタ
Dフリップフロップは、非常に用途の広いメモリ回路です。ここでは、Dフリップフロップを使ったシフトレジスタという回路を1つ紹介します。
上図のように、Dフリップフロップを直列につないだだけです。この回路は以下のように、入力の値をクロックの周期に合わせて、左から右のDフリップフロップに順番に伝えていきます。
ところで、\(D_{\text{in}}\) の値が、CLKが0から1になったとたんに、\(Q_0\) から \(Q_3\) まで瞬時に伝わってしまうことはないのでしょうか。各Dフリップフロップは、クロックの立ち上がりの瞬間に、その直前に入力されていた値を取り込みます。立ち上がりの瞬間に2段目のDフリップフロップが取り込むのは、変化する前の \(Q_0\) の値です。そのため、\(Q_0\) の新しい値が \(Q_1\) に反映されるのは、次の立ち上がりのときになります。こうして、値は1クロックにつき1段ずつ右へ進んでゆくのです。
シフトレジスタの応用としては、直列に並んだビット列を、一定の桁数で一度に取り出す「直列入力-並列出力」があります。 たとえば図では4ビットたまった時点で、一斉に他の処理の入力として4ビットの数を送り出す場合に使えます。
ネットワーク上を流れるデータは、0と1が逐次的に伝えられています。一方でコンピューター内では8ビットや64ビットといったまとまりで処理されます。そのため、逐次的に流れてきたデータをまとめて次の処理に伝送する回路が必要となるわけです(シリアルパラレル変換)。
下のアニメーションは、6段のシフトレジスタの動作です。入力 \(D_{\text{in}}\) のビットが、1クロックごとに左から右へ1段ずつ送られていきます。6クロック後には、直列に入ってきた6ビットがそろって並列に取り出せます。
また、2進法の数は桁を1つずらすと2倍または2分の1(右へずらしたときの端数は切り捨て)にすることに相当しますので、計算にも用いることができます。
2.7. 周波数分割(2進カウンタ)
以下のアニメーションの動作をみてみてください。5個のDフリップフロップを数珠つなぎにし、各段は自分の反転出力 \(\overline Q\) を \(D\) に戻して、クロックが来るたびに0と1がパタパタ入れ替わる(トグルする)ようにしてあります。さらに、各段の \(\overline Q\) を次の段のクロック入力につないであり、下の桁が1から0に戻る瞬間に、上の桁へ桁上げが伝わります。
各ランプは2進数の各桁で、左が下位桁 \(Q_0\)、右が上位桁 \(Q_4\) です(右側のパネルに10進数の値も示しました)。信号の伝わる順に桁を並べているため、最上位桁を左端に書く通常の2進法の表記とは桁の並びが左右逆になっている点に注意してください。1クロックごとに値が1つずつ上がり、5桁で0〜31を一周します。
\(Q_0\) はクロックの半分の周波数で点滅し、\(Q_1\) はさらにその半分(クロックの4分の1)…というように、1桁上がるごとに周波数が半分になります。これが「周波数分割」とよばれるゆえんです。ある周波数のクロックから、その2分の1、4分の1、8分の1…の信号を取り出せるため、分周回路として時計やタイマーにも使われます。
3. ここから先の話
ここまでで、ようやく演算とメモリの構成のごく一部に触れることができました。ここから先のコンピューターの構成については、本書では触れません。コンピューターをより深く理解するためには、さらに以下のような内容について学ぶことが必要です。
-
コンピューターがメモリ上に展開された機械語(CPUが解釈できる命令列)のプログラムを解釈して、計算結果をメモリ上に出力する方法や、そのための高速化の手法
-
コンピューターのハードウェアの入出力や、メモリ管理やCPUへの仕事の割当といった基本的な資源管理、アプリケーションとハードウェアとの仲介をするためのソフトウェアであるオペレーティング・システムの仕組み
-
人間が理解しやすいプログラミング言語を、CPUが実際に解釈できる命令列に変換するコンパイラやインタプリタと呼ばれるソフトウェアの仕組み
4. 練習問題
順序回路は、図を眺めるだけではなかなか身につきません。以下の問題を、自分の手で一段ずつ追いかけてみてください。タイミングチャートを描く問題では、\(Q\) の初期値は0とし、ゲートの遅延は考えません(入力の変化と同じ時刻に \(Q\) を変化させて描いてかまいません)。
以下のSRラッチの状態変化を追跡せよ。
初期状態: \(Q=0\)
入力系列: \((S,R)\) = (1,0) → (0,0) → (0,1) → (0,0) → (1,1)
各段階での\(Q\)の値と、最後の入力が問題となる理由を説明せよ。
解答
特性方程式 \(Q_{t+1} = S + \overline R\cdot Q_t\) にしたがって、一段ずつ追います。
| ステップ | \((S,R)\) | 命令 | \(Q\) | |
|---|---|---|---|---|
初期 |
– |
– |
0 |
|
1 |
(1,0) |
Set |
1 |
\(Q=1\) に書き込み |
2 |
(0,0) |
保持 |
1 |
直前の値を維持 |
3 |
(0,1) |
Reset |
0 |
\(Q=0\) に書き込み |
4 |
(0,0) |
保持 |
0 |
直前の値を維持 |
5 |
(1,1) |
禁止 |
0 |
両入力が1の間は両出力0。解除後は不定 |
最後の \((S,R)=(1,1)\) では、両方のNORゲートに1が入るため、出力は両方とも0になり、\((Q,\overline Q)=(0,0)\) となります。これは「\(Q\) とその否定 \(\overline Q\) が同じ値」という、記号の意味に反する状態です。
さらに問題なのは、この後に \((S,R)=(0,0)\)(保持)へ移ったときです。両方のNORゲートが同時に0から切り替わろうとして、どちらの出力が先に確定するかで最終状態が0になるか1になるか決まりません(競合状態、レースコンディション)。前章「論理回路の簡単化と回路設計」の「論理回路の遅延時間」の節で学んだように、ゲートには遅延時間があり、2つのNORゲートの遅延がぴったり同じになることはありません。そのわずかな差で勝負が決まってしまうため、結果が予測できないのです。値が予測できないため、\((S,R)=(1,1)\) は禁止入力とします。
ステップ5の時点の \(Q=0\) は、特性方程式 \(S+\overline R\cdot Q_t\) の値(1)とは一致しません。特性方程式は、\((S,R)=(1,1)\) をドントケアとして作った式なので、禁止入力に対する出力は表していません。
SRラッチの特性方程式 \(Q_{t+1} = S + \overline R\cdot Q_t\) が、本文の表(SRラッチの動作(2))を再現することを確かめよ。また、\((S,R)=(1,1)\) の2行をドントケアとして扱ったことが、この式にどう表れているか説明せよ。
解答
\((S,R,Q_t)\) の8通りを代入します(\((1,1,\ast)\) 以外はSRラッチの動作(2)と一致)。
| \(S\) | \(R\) | \(Q_t\) | \(S+\overline R\cdot Q_t\) | SRラッチの動作(2) |
|---|---|---|---|---|
0 |
0 |
0 |
\(0+1\cdot0=0\) |
0 |
0 |
0 |
1 |
\(0+1\cdot1=1\) |
1 |
0 |
1 |
0 |
\(0+0\cdot0=0\) |
0 |
0 |
1 |
1 |
\(0+0\cdot1=0\) |
0 |
1 |
0 |
0 |
\(1+1\cdot0=1\) |
1 |
1 |
0 |
1 |
\(1+1\cdot1=1\) |
1 |
1 |
1 |
0 |
\(1+0\cdot0=1\) |
\(\ast\) |
1 |
1 |
1 |
\(1+0\cdot1=1\) |
\(\ast\) |
下の2行(禁止入力)では、式の値はどちらも1になります。これは、カルノー図でドントケアを「1」とみなして囲み、\(S=1\) の領域をまとめて1つの項\(S\) にしたことの結果です。ドントケアを「0」とみなせば、\(\overline R\cdot(S+Q_t)\) という形にもできます。どちらの式も、禁止入力以外の6行では同じ値になります。「都合よく解釈してよい」とは、式が簡単になる方を選んでよいという意味です。
ゲーテッドDラッチについて、入力 \(E\)、\(D\) と現在の出力 \(Q_t\) の8通りの組合せに対して、次の出力 \(Q_{t+1}\) を示す表(特性表)を作れ。さらに、カルノー図を用いて特性方程式(\(Q_{t+1}\) を \(E\)、\(D\)、\(Q_t\) の積和形で表した式)を求めよ。
解答
\(E=0\) の4行では \(Q_{t+1}=Q_t\)(保持)、\(E=1\) の4行では \(Q_{t+1}=D\) です。
| \(E\) | \(D\) | \(Q_t\) | \(Q_{t+1}\) | |
|---|---|---|---|---|
0 |
0 |
0 |
0 |
保持 |
0 |
0 |
1 |
1 |
保持 |
0 |
1 |
0 |
0 |
保持 |
0 |
1 |
1 |
1 |
保持 |
1 |
0 |
0 |
0 |
\(D\) を取り込む |
1 |
0 |
1 |
0 |
\(D\) を取り込む |
1 |
1 |
0 |
1 |
\(D\) を取り込む |
1 |
1 |
1 |
1 |
\(D\) を取り込む |
行に \(ED\)、列に \(Q_t\) をとってカルノー図を描くと、次のように2つの枠で囲めます。
「\(E=1\) なら \(D\)、\(E=0\) なら \(Q_t\)」を式にしたものです。前章の2入力データセレクタの式 \(y=\bar s\cdot d_0 + s\cdot d_1\) と比べると、選択信号 \(s\) が \(E\)、\(d_0\) が \(Q_t\)、\(d_1\) が \(D\) にあたります。ゲーテッドDラッチは、「新しい値 \(D\)」と「今の値 \(Q_t\)」のどちらを次の値にするかを \(E\) で選ぶ回路だと見ることができます。
SRラッチと違って禁止入力がないので、ドントケアはありません。
ゲーテッドDラッチについて、\(E\) と\(D\) が下表のように変化するとき、\(Q\) の値を埋めよ。初期状態は \(Q=0\) とする。
| 時刻 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
\(E\) |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
\(D\) |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
\(Q\) |
解答
| 時刻 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
\(E\) |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
\(D\) |
1 |
0 |
1 |
1 |
0 |
0 |
1 |
0 |
\(Q\) |
0 |
0 |
1 |
1 |
1 |
0 |
1 |
1 |
\(E=1\) のときは\(Q\) が\(D\) をそのまま映し(透過)、\(E=0\) のときは直前の\(Q\) を保持します。波形で表すと下図のようになります(黄色の帯が答えの\(Q\))。
ポイントは、時刻0、時刻3〜4、時刻7です。ここは\(E=0\) なので、\(D\) がどんな値でも(時刻0の\(D=1\)、時刻3〜4の\(D=1\to0\)、時刻7の\(D=0\))、\(Q\) は直前の値(初期値0、時刻2・時刻6で取り込んだ1)を保持し続けます。
ゲーテッドDラッチのタイミングチャートを完成させよ(\(Q\) の波形を描け)。
解答
\(E=1\) の時間帯(下図の赤で示した区間)だけ\(D\)の値をそのまま\(Q\)に反映し、それ以外の時間は値を保持することに注意すれば、下図のようになります。
\(E=1\) の区間の途中で \(D\) が変わると、\(Q\) もその場で変わります。1つ目の区間では、\(D\) が区間の途中で0に下がるので、\(Q\) も途中で0に戻ります。2つ目の区間は、区間の終わり近くで \(D\) が1になり、\(E\) が0に下がった後もその1を保持します。
Dフリップフロップのタイミングチャートを完成させよ(\(Q\) の波形を描け)。\(\mathrm{CLK}\) と \(D\) の波形は、問題5の \(E\) と \(D\) と同じ形である。
解答
問題5とは異なり、赤い縦線(クロックの立ち上がりの瞬間)での\(D\)の値だけを読み込み、それ以外の時間は入力が変化しても出力を保持することに注意すれば、下図のようになります。
4回の立ち上がりでの \(D\) の値は、順に1, 0, 0, 1 です。3回目の立ち上がりの前に \(D\) は一度1になっていますが、立ち上がりの瞬間には0に戻っているので読み込まれません。
ゲーテッドDラッチ(\(E=\mathrm{CLK}\))と立ち上がりエッジトリガーのDフリップフロップに、同じ\(\mathrm{CLK}\) と\(D\) を与える。立ち上がりエッジは時刻1と時刻5にあるとする。初期状態は \(Q=0\) とする。両者の\(Q\) を埋め、なぜ違いが出るかを説明せよ。
| 時刻 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
\(\mathrm{CLK}\) |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
\(D\) |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
ラッチの \(Q\) |
||||||||
フリップフロップの \(Q\) |
解答
| 時刻 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
\(\mathrm{CLK}\) |
0 |
1 |
1 |
0 |
0 |
1 |
1 |
0 |
\(D\) |
1 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
ラッチの \(Q\) |
0 |
1 |
0 |
0 |
0 |
0 |
1 |
1 |
フリップフロップの \(Q\) |
0 |
1 |
1 |
1 |
1 |
0 |
0 |
0 |
波形で重ねて描くと下図のようになります(緑がラッチ、青がフリップフロップ(FF)。赤い点線が立ち上がりエッジ)。
ゲーテッドDラッチは\(\mathrm{CLK}=1\) の間ずっと透過なので、時刻1〜2で\(D\) が1から0に下がると\(Q\) もそれを追って下がります。同様に時刻6〜7の\(D\) の0→1も追います。
Dフリップフロップは立ち上がりの瞬間(時刻1と時刻5)の\(D\) だけを読み取ります。時刻1では\(D=1\) なので\(Q=1\)、時刻5では\(D=0\) なので\(Q=0\) です。立ち上がりでない間に\(D\) がどう変化しても無視されます。
つまり「クロックが1の間ずっと反応する(透過的)」のがラッチ、「クロックが0から1に変わる一瞬だけ反応する」のがフリップフロップです。
4段シフトレジスタ(出力 \(Q_0,Q_1,Q_2,Q_3\))を考える。全段0で初期化し、直列入力 \(D_{\text{in}}\) が各クロックの立ち上がり直前に次の値をとる。
| クロック | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
\(D_{\text{in}}\) |
1 |
0 |
1 |
1 |
0 |
0 |
各クロック後の \((Q_0,Q_1,Q_2,Q_3)\) を求めよ。また、クロック1で入れた最初のビットが \(Q_3\) に到達するのは何クロック目か。
解答
立ち上がりごとに、\(Q_0\leftarrow D_{\text{in}}\)、\(Q_1\leftarrow Q_0\)、\(Q_2\leftarrow Q_1\)、\(Q_3\leftarrow Q_2\) が同時に起こります(すべて直前の値を使う点に注意)。
| 初期 | clk1 | clk2 | clk3 | clk4 | clk5 | clk6 | |
|---|---|---|---|---|---|---|---|
\(Q_0\) |
0 |
1 |
0 |
1 |
1 |
0 |
0 |
\(Q_1\) |
0 |
0 |
1 |
0 |
1 |
1 |
0 |
\(Q_2\) |
0 |
0 |
0 |
1 |
0 |
1 |
1 |
\(Q_3\) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
クロック1のビット(1)は、1クロックごとに1段ずつ右に進み、クロック4で \(Q_3\) に到達します。このとき \((Q_3,Q_2,Q_1,Q_0)=(1,0,1,1)\) となり、クロック1〜4で入れた 1,0,1,1 が4ビットまとめて取り出せます。逐次的に入ってきたビット列を、一定の桁数のまとまりとして取り出す「直列入力-並列出力」の動作です。
よくある誤りは、\(Q_0\) の新しい値がそのまま同じクロックで \(Q_1\) にも伝わると考えることです。本文で説明したとおり、各段は立ち上がりの直前の値を取り込むので、1クロックで進むのは1段だけです。
(a) DRAMはリフレッシュが必要だが、SRAMは(電源が入っている限り)不要である。この違いを、両者の1ビットの記憶方法の違いから説明せよ。
(b) 64ビットのデータを保持するレジスタには、Dフリップフロップが最低何個必要か。
解答
(a) DRAMはキャパシタに蓄えた電荷で1ビットを表します。電荷は漏れ電流によって少しずつ失われるため、放電しきって0と1の区別がつかなくなる前に、書き直す(リフレッシュ)必要があります。一方SRAMは、互いに帰還する2つのインバーター(NOTゲート)のラッチ構造で、電源がある限り安定状態が自分自身で保たれます。書き直さなくても状態が崩れないため、リフレッシュは不要です(その代わりSRAMは1ビットあたりのトランジスタ数が多く、記録密度は低くなります)。
(b) Dフリップフロップ1個が1ビットを保持します。64ビットなら 64個 です。
以上です