マスタークロックからレジスタを作る 【コンピューターアーキテクチャ】

👀 概要

論理回路とは、0 と 1 (あるいは、true,false) の組み合わせによって計算や判断を行う電子回路。 この論理回路を組み合わせて、コンピューターを作ることができる。 この記事は、その過程を説明する試みです。

参考 : https://web-docs.gsi.de/~vpenso/notes/posts/code/nand2tetris/#part-1 参考 : https://www.youtube.com/playlist?list=PLrDd_kMiAuNmllp9vuPqCuttC1XL9VyVh

📖 関連ページ

👦 対象読者

  • とにかく低レイヤーが好きな人
  • システム開発ですぐに役に立つことを知りたい」という方の需要は満たせません...。

🔗 参考リンク

内容

入力信号を与えると、即座に出力が得られるものは 組み合わせ回路 と呼ばれます。 瞬間的に、時間の概念がありません。 これまで考慮してきた NAND , MULTI_PREXCER , ALU には時間の概念が必要でした。

しかし、コンピューターにおけるメモリーの機能は、時間の概念が必要です。 例えば、 x+17 の値を一時的に保存したとして、どこかで再利用するためには、前に保存した値を再度取り出す必要があります。

コンピューターにおける時間の概念は ticktock と呼ばれる一連のバイナリ信号を生成するクロックを用いてモデル化されます。 この一連のバイナリを、サイクルと呼びます。

サイクル

時間の概念は数学で言えば、一方向に進む「矢印」として比喩的に表現される。 現実の時間の概念は連続的であるが、0と1のコンピューターではこれは扱いづらいものになってしまう。

そこで、コンピューターでは時間を連続的ではなく、サイクルと呼ばれる一定感覚の区間に分割される。 コンピューターではサイクルの間隔が最小単位であり、これ位以上は分割できない。

参考 : https://basics.k-labo.work/2017/10/11/%E3%83%97%E3%83%AD%E3%82%BB%E3%83%83%E3%82%B5%E3%81%AE%E6%80%A7%E8%83%BD/

私たちはサイクルnとn+1のみ知っていればよく、その間のサイクルの最小単位は知る必要はない。 当然、ゲートに1の信号が流そうとした時、0から1まで出力が安定するまで相当時間(ロード時間)がかかる。 しかし、1サイクルの時間は、そのロード時間よりも意図的に長くしているので、サイクルの間隔ごとに、ゲートの出力は0か1で安定している。

この方式がうまく機能するためには、サイクル長を適切に設定する必要がある。 具体的には、サイクル長は「システムで発生し得る最大の時間遅延」よりも長くする必要がある。 一方で、サイクルが短ければ短いほど、コンピューターは早くなる。(ここはトレードオフ)

マスタークロック

サイクルを実際に実現するには、二つのフェーズを交互に動く発信機を使うのが必要である。 二つのフェーズは「0/1」または「tick/tock」のように表せる。

ハードウェアの回路を使用し、同じクロック信号をシステム内の全てのメモリチップに同時に送信する、全てのチップに繋がったクロックは マスタークロック と呼ばれる。

フリップフロップとは

フリップフロップはデジタル回路で「1ビットの記憶」をする基本的な回路です。

  • フリップフロップにおけるinとoutは出力値であり、tは現在の時間単位を表す。
  • 関数は out(t) = in(t-1) で表される。

各時間単位の終了時に、フリップフロップは時間単位の入力を出力することだけを理解しておけば良い

引用元 https://www.build-electronic-circuits.com/d-flip-flop/

コンピューターのすべてのメモリチップ(レジスタ、RAM、カウンター)は、DFF回路を元に作る。

組み合わせ論理回路と順序回路

今回作っているフリップフロップのような回路には、時系列データが備わっている。 このような回路を、順序回路と呼ぶ。

逆に、基本ゲートからALUに至るまで、クロックサイクルの中の入力結果に応じてすぐに結果を出力するものを組み合わせ論理回路と呼ぶ。

引用元 https://www.momoyama-usagi.com/entry/info-junjo1

順序論理の設計では、フリップフロップ回路と組み合わせ論理かいろを組み合わせて使用する。 これにより順序回路チップは、過去の入出力だけでなく、過去の入出力にも反応する能力を持つ。

一つ疑問が残る。 コンピューター全体を同期して実行させなければならないのに、近くにあるDFFと遠くにあるDFFで同期がずれてしまった場合、コンピューターは役に立たない値しか出力しないのではないか?

例えば、ALUにx+yを計算させたいとする。 ここで、xは近くにあるレジスタに格納された値で、yは遠く離れたレジスタの値であるとする。 様々な物理的な制約により、xとyがALUに引き出されるまでに到着する時間は異なるのではないか?

ALUは組み合わせカイロであるから、時間という概念はない。 どのような信号であれ、その入力へたどり着いた信号は、即座にその加算が求められる。 そのため、ALUの出力が「x+y」の値に落ち着くには、わずかな時間が必要である。 その時間に到達するまで、ALUは「ゴミ」を出力し続ける。

この課題をどう解決するかというと、クロックサイクルである。

時間を離散的に表すことで、ALUから出力される「ごみ」は参照されず、クロックサイクルが有効なタイミングで、ALUは有効な値が出力される。 すなわち、私たちがやることは、コンピューターのクロックを作る時に、クロックサイクルの長さを適切に設定すれば良いのだ。

クロックサイクルの終わりには、ALUの値は正しく、その間の値は無視される。これが、独立したハードウェアを同期したシステムに変えるトリックである。

1ビットレジスタ

1ビットレジスタには2つの入力と1つの出力を行う。

  • 入力
    • in : 0または1。保存しておきたい値を入れる。入れた値は1クロック後、outで出力される。
    • load : トリガー、 この値が1の時、inの値が1クロック後、outで出力される
  • 出力
    • out : loadのトリガーが1の時、1クロック前のinの値が出力される

inとoutについては、ほぼほぼ問題ない。入力と出力である。

注意しておきたいのは、load についてで、inについては常に入力が垂れ流されている状況だが、loadが1になった時に、次のターンで現在のinの値をoutに反映させるということ。

つまり、load は状態を変更させるためのスイッチである。

このレジスタをまとめて16個同時に扱うのが、16ビットレジスタである。

参考 : https://mrce.in/ebooks/Computing%20Systems%20Elements%202nd%20Ed.pdf

16bitレジスタ

16ビットレジスタは、1ビットレジスタを16個集めたものである。

ただし、load引数は共通であり、load 引数の合図で16個の値全て 書き換わる。

page:https://minegishirei.hatenablog.com/entry/2025/03/16/134211

Dear My Frends.: 個人開発宣伝ラボ - 個人開発者が間違った施策で時間を溶かさないための、心理学と実務知見のナレッジ共有コミュニティ