CPUをつくろう



## 🔹【1】ALU構成の前提

### ▫️目的：

* 8ビット演算（A\[7:0], B\[7:0]）に対応する算術・論理演算を全加算器ベースで実現

### ▫️使用する主な構成部品：

* **全加算器（Full Adder） × 8**：1ビットずつ加算
* **ビット反転器（NOT）**
* **AND, OR, XORゲート**
* **MUX（演算切り替え）**

---

## 🔹【2】全加算器の基本構造

1ビットの全加算器の論理式：

* 和 (Sum):

  $$
  S = A \oplus B \oplus C_{\text{in}}
  $$
* 桁上がり (Carry-out):

  $$
  C_{\text{out}} = (A \land B) \lor (B \land C_{\text{in}}) \lor (A \land C_{\text{in}})
  $$

これを8段に接続して、A\[7:0], B\[7:0] を下位ビットから上位ビットへ伝播させる。

---

## 🔹【3】ALUでの加算（A + B）

### ▫️構成：

* 全加算器を8段に直列接続（LSB→MSB）
* 入力：`A[7:0]`, `B[7:0]`, `Cin = 0`

### ▫️演算：

* 各ビットで `S = A_i ⊕ B_i ⊕ C_in` を計算し、次段に `C_out` を送る。

---

## 🔹【4】ALUでの減算（A - B）

### ▫️考え方：

減算は、**加算器を用いて以下で実装**：

$$
A - B = A + (\overline{B} + 1)
$$

### ▫️手順：

* `B` を全ビット反転（NOTゲート）
* 入力キャリー `Cin = 1` に設定
* 全加算器に A と `NOT(B)` を加算

---

## 🔹【5】論理演算（A AND B, A OR B, A XOR B, NOT A）

### ▫️構成：

* 各ビットごとに単独ゲートで演算
* 全加算器は使用しない（MUXでバイパス）

| 演算  | 式           | 実現方法       |
| --- | ----------- | ---------- |
| AND | `A_i ∧ B_i` | ANDゲート     |
| OR  | `A_i ∨ B_i` | ORゲート      |
| XOR | `A_i ⊕ B_i` | XORゲート     |
| NOT | `¬A_i`      | NOTゲート（単項） |

---

## 🔹【6】ALU制御信号による演算切替

演算モードを選ぶためにMUXを使用：

| ALU制御 | 演算内容         |
| ----- | ------------ |
| `00`  | A AND B      |
| `01`  | A OR B       |
| `10`  | A + B        |
| `11`  | A - B（B反転＋1） |

制御線でMUXに入力される演算結果を選択。

---

## 🔹【7】ブロック図（簡略）

```
       A[7:0] ---------------------+
                                   |
                                [MUX]-----> 各種ゲート or 加算器 -----> 出力 S[7:0]
                                   |
       B[7:0] --[NOT or 原信号]----+

                ↑
              制御信号（演算種別・B反転・Cin）
```

---

## 🔹【8】演算の統合（まとめ）

| 演算種別    | B変換 | Cin | ゲート or 加算器 |
| ------- | --- | --- | ---------- |
| A + B   | B   | 0   | 加算器        |
| A - B   | ¬B  | 1   | 加算器        |
| A AND B | -   | -   | ANDゲート     |
| A OR B  | -   | -   | ORゲート      |
| A XOR B | -   | -   | XORゲート     |

---

---

## 🔹【フリップフロップ（Flip-Flop）とD型フリップフロップ（D-FF）】

**– ビットを記憶する最小単位の構造と原理 –**

---

### ◆ 1. フリップフロップとは？

* **定義**：フリップフロップ（Flip-Flop）は**1ビットの情報を記憶**する\*\*順序回路（sequential circuit）\*\*である。
* **役割**：入力の変化に応じて出力を「保持」「更新」することで、**記憶素子**として使われる。
* **分類**：

  * SRフリップフロップ（Set-Reset）
  * D型フリップフロップ（Delay／Data）
  * T型（Toggle）
  * JK型

---

### ◆ 2. D型フリップフロップ（D-FF）とは？

#### 🔸特徴：

* 入力 `D` をクロック（CLK）の立ち上がり（または立ち下がり）でそのまま出力 `Q` に転送
* 同時に、前の値は破棄されて、新しい値が保持される

#### 🔸論理記号：

```
   ┌───────┐
 D │       │ Q
──▶│   D   ├──▶
   │  FF   │
CLK│       │
──▶│       │
   └───────┘
```

---

### ◆ 3. D型FFの動作表

| CLKエッジ | D | Q（出力） |
| ------ | - | ----- |
| ↑      | 0 | 0     |
| ↑      | 1 | 1     |
| ↑      | x | D     |
| ―      | x | 前のQ   |

* **↑：立ち上がりエッジ**（rising edge）
* **Qは保持**される（次のクロックまで）

---

### ◆ 4. 記憶の基本：1ビット記憶素子

* **1つのD型FF = 1ビットの記憶セル**
* 8ビットレジスタ → D-FF × 8本を並列接続
* クロックを揃えて動作を同期（synchronous system）

---

### ◆ 5. D型FFの回路構成（内部構造）

内部では**NANDゲート×4 or NORゲート×4**を組み合わせた**マスタ・スレーブ構造**

```
D ──┬─────┐
    │     │
    ▼     ▼
  Latch ─► Latch（2段階：Master → Slave）
    ▲     ▲
CLK ──────┘（反転させて片方ずつON）

```

---

### ◆ 6. 応用例

| 応用          | 内容                          |
| ----------- | --------------------------- |
| レジスタ        | 複数ビットの保持（例：8bit → D-FF × 8） |
| カウンタ        | クロックに合わせて数値を更新              |
| シフトレジスタ     | 右/左にビットをずらして記憶              |
| 状態遷移回路（FSM） | 状態を記憶・遷移                    |

---

### ◆ 7. D型FFのVerilogコード例（1ビット）

```verilog
module dff (
  input clk,        // クロック入力
  input d,          // データ入力
  output reg q      // 出力（記憶値）
);
  always @(posedge clk) begin
    q <= d;         // クロック立ち上がり時にDの値をQに保存
  end
endmodule
```

---

### ◆ 8. Python模擬（動作確認）

```python
class DFlipFlop:
    def __init__(self):
        self.q = 0

    def clock(self, d):
        self.q = d  # クロックで入力Dを保存

# 使い方
dff = DFlipFlop()
dff.clock(1)
print(dff.q)  # 出力: 1
```

---

### ◆ まとめ：D型FFの重要性

| 特徴      | 説明                           |
| ------- | ---------------------------- |
| 最小記憶単位  | 1ビット単位の記憶素子（状態を保持）           |
| 同期動作    | クロックによって値が更新されることで制御がしやすい    |
| 汎用性が高い  | レジスタ、カウンタ、FSM、シフトレジスタなどに応用可能 |
| 論理回路の基本 | 論理ゲートとD型FFで任意の同期回路を構成できる     |

---

---

## 🔹【レジスタ構造】

**– 8ビットをまとめて記憶する基本構成 –**

---

### ◆ 1. レジスタとは？

* **定義**：複数の**D型フリップフロップ（D-FF）を並列接続**し、ビット列（多ビットデータ）をまとめて一括記憶する**記憶回路（Register）**
* **用途**：CPU内部やデジタル回路で**一時的なデータ保存**、演算対象の保持などに使用

---

### ◆ 2. 8ビットレジスタの構造

#### 🔸構成：

* **D型FF × 8個**（1つにつき1ビット）
* **共通のクロック（CLK）**
* 入力：`D[7:0]`
* 出力：`Q[7:0]`

#### 🔸構造図（概念）：

```
 D[7] ──▶ [D-FF] ──▶ Q[7]
 D[6] ──▶ [D-FF] ──▶ Q[6]
 D[5] ──▶ [D-FF] ──▶ Q[5]
   ⋮
 D[1] ──▶ [D-FF] ──▶ Q[1]
 D[0] ──▶ [D-FF] ──▶ Q[0]

       ▲
     共通クロック CLK
```

---

### ◆ 3. 動作原理

* クロックの立ち上がり（または立ち下がり）で、`D[7:0]` のデータが**一括で記憶**
* 各D-FFは入力 `D[i]` を `Q[i]` に転送
* 記憶されたデータはクロックが入らない限り保持される

---

### ◆ 4. レジスタのVerilog記述（8ビット）

```verilog
module register8 (
    input wire clk,           // クロック信号
    input wire [7:0] d,       // 入力データ（8ビット）
    output reg [7:0] q        // 出力データ（8ビット）
);
    always @(posedge clk) begin
        q <= d;               // クロック立ち上がりで記憶
    end
endmodule
```

---

### ◆ 5. 応用機能（追加制御）

| 機能    | 内容                        |
| ----- | ------------------------- |
| リセット  | 初期化：`q <= 8'b00000000;`   |
| イネーブル | 有効時のみ保存：`if (en) q <= d;` |
| ラッチ   | クロック非同期で保持                |

---

### ◆ 6. Pythonによるシミュレーション例

```python
class Register8Bit:
    def __init__(self):
        self.q = [0] * 8

    def clock(self, d):
        self.q = d[:]  # 入力dは8ビットリスト

# 使用例
reg = Register8Bit()
reg.clock([1,0,1,0,1,0,1,0])  # D7-D0 に格納
print(reg.q)  # → [1, 0, 1, 0, 1, 0, 1, 0]
```

---

### ◆ 7. 使用例と意義

| 応用装置      | レジスタの役割        |
| --------- | -------------- |
| 汎用レジスタ    | 計算用の一時記憶       |
| アキュムレータ   | 演算結果の保存        |
| フラグレジスタ   | 状態（符号、キャリー等）記録 |
| プログラムカウンタ | アドレス管理用        |

---

### ◆ まとめ：8ビットレジスタの特徴

| 項目     | 内容                       |
| ------ | ------------------------ |
| 記憶素子   | D型フリップフロップ × 8個          |
| 記憶可能単位 | 8ビット（1バイト）               |
| 入出力    | 並列ビット列（D\[7:0], Q\[7:0]） |
| 制御信号   | クロック、（必要に応じて）イネーブル・リセット  |
| 主な用途   | CPU内データ保存、演算保持、状態遷移など    |

---

---

## 🔹【ラッチとクロック・同期制御・RAMの構造】

**– 記憶回路の基礎からアドレス指定によるメモリ動作まで –**

---

### ◆ 1. ラッチ（Latch）とクロック（Clock）

#### 🔸【ラッチ：非同期記憶素子】

* **定義**：クロック信号を必要とせず、**制御信号（Enable）に応じて即時データを記憶**する
* **代表的：Dラッチ**
* **動作例**：

| Enable | D | Q（出力） |
| ------ | - | ----- |
| 0      | x | 保持    |
| 1      | 0 | 0     |
| 1      | 1 | 1     |

> ラッチは**制御信号が1のときだけ更新され、0で保持**する。

---

#### 🔸【フリップフロップ：クロック同期素子】

* クロック信号（立ち上がりや立ち下がり）でのみ**出力が更新**
* \*\*同期回路（Synchronous circuit）\*\*の基本要素

---

### ◆ 2. クロック信号による同期制御

#### 🔸クロック（CLK）の役割：

| 機能        | 内容                             |
| --------- | ------------------------------ |
| 更新タイミング制御 | FFやレジスタにデータを書き込むタイミングを制御       |
| データ整合性維持  | 各回路ブロックの動作を「時間的に統一」            |
| シーケンス制御   | クロックに合わせて処理が順に実行（→順序回路、状態遷移制御） |

#### 🔸クロックと非同期制御の違い：

| 項目   | ラッチ（非同期）        | FF（同期）        |
| ---- | --------------- | ------------- |
| 更新条件 | 制御信号（Enable等）   | クロック信号（CLK）   |
| 安定性  | タイミング依存で不安定になる  | クロックにより安定     |
| 使用箇所 | 少量の構成回路（FIFOなど） | 大規模回路、CPU内部など |

---

### ◆ 3. メモリ（RAM）の構造

#### 🔸RAM：Random Access Memory

* **定義**：読み書きがランダムアクセスで可能な**揮発性記憶素子**
* **基本構成**：

  * アドレス線（Address）：どの記憶セルにアクセスするか指定
  * データ線（Data）：そのセルの内容（読み出し or 書き込み）
  * 制御線（Read/Write Enable）

#### 🔸構造ブロック図（概念）

```
      アドレス入力（Address）────┐
                                 ▼
                        +-----------------+
                        |  アドレスデコーダ |
                        +--------┬--------+
                                 ▼
                 +------------+------------+------------+
                 | セル[0]    | セル[1]    | … セル[N]  |
                 +------------+------------+------------+
                     ▲             ▲              ▲
                     │             │              │
            書き込み/読み出し     …             データI/O
```

---

### ◆ 4. アドレスとデータの対応表（例：8ビット × 8アドレス）

| Address (10進) | Address (2進) | Data (8bit) |
| ------------- | ------------ | ----------- |
| 0             | 000          | `11001010`  |
| 1             | 001          | `01100101`  |
| 2             | 010          | `11110000`  |
| 3             | 011          | `00001111`  |
| 4             | 100          | `10101010`  |
| 5             | 101          | `01010101`  |
| 6             | 110          | `10000001`  |
| 7             | 111          | `11111111`  |

---

### ◆ 5. RAMの読み書き制御

#### 🔸書き込み動作：

1. アドレスを指定：`Addr = 3`
2. 書き込みデータ入力：`Data = 10101010`
3. 書き込み許可信号：`WriteEnable = 1`
4. クロックにより FF に保存

#### 🔸読み出し動作：

1. アドレスを指定：`Addr = 3`
2. 読み出し許可：`ReadEnable = 1`
3. セルの内容 `10101010` を出力

---


---

### ◆ まとめ：記憶回路の階層構造

| 段階    | 内容              | 要素              |
| ----- | --------------- | --------------- |
| ビット記憶 | 1ビット単位の記憶素子     | ラッチ, D-FF       |
| レジスタ  | 多ビットの一括記憶       | D-FF列           |
| メモリ   | アドレス指定での大量データ管理 | RAM, ROM, SRAM等 |
| 同期制御  | 全体の時間整合         | クロック + FF構成     |

---

---

## 🔹 第5章：命令と演算の制御 — 命令セットから制御ユニットまでの体系的設計

| 単元  | 内容                       | 実装・演習例                                     |
| --- | ------------------------ | ------------------------------------------ |
| 5.1 | **命令セット（ISA）設計**         | 命令形式とオペコードの割当。<br>例：`LOAD`, `ADD`, `STORE` |
| 5.2 | **命令デコーダ**               | 命令ビット列を解釈し、制御信号を出力                         |
| 5.3 | **プログラムカウンタ（PC）**        | 命令アドレスを保持・更新（基本は `PC+1`）                   |
| 5.4 | **制御ユニット（Control Unit）** | クロックごとに制御信号を発行、ALUやメモリ等を制御                 |

---

## ◆ 5.1 命令セット（ISA: Instruction Set Architecture）

### ▫️命令形式の例（8ビット命令）：

| フィールド  | ビット数 | 内容                |
| ------ | ---- | ----------------- |
| OPCODE | 3    | 命令種別（LOAD, ADDなど） |
| Rdst   | 2    | 宛先レジスタ            |
| Rsrc   | 2    | ソースレジスタ           |
| 未使用    | 1    | 予約ビット（将来拡張用）      |

### ▫️命令例：

| 命令                | 意味           | バイナリ例（8bit）   |
| ----------------- | ------------ | ------------- |
| LOAD R1, \[0x02]  | メモリからR1に読み出し | `000 01 10 0` |
| ADD R0, R1        | R0 ← R0 + R1 | `001 00 01 0` |
| STORE R0, \[0x03] | R0の値をメモリに書込  | `010 00 11 0` |

---

## ◆ 5.2 命令デコーダ

### ▫️目的：

* **命令ビット列を解析し、制御信号群に変換**

### ▫️入力：

* 命令（例：`8'b00100010`）

### ▫️出力例（制御信号）：

| 信号       | 内容               |
| -------- | ---------------- |
| ALUOp    | 演算種別（例：ADD, SUB） |
| RegWrite | レジスタ書込み有効信号      |
| MemRead  | メモリ読み出し有効信号      |
| MemWrite | メモリ書込み有効信号       |
| ALUSrc   | ALUの片方の入力に即値を使うか |

### ▫️Verilog例：

```verilog
always @(*) begin
    case (opcode)
        3'b000: begin  // LOAD
            RegWrite = 1;
            MemRead = 1;
            ALUOp = 3'b000;
        end
        3'b001: begin  // ADD
            RegWrite = 1;
            ALUOp = 3'b001;
        end
        3'b010: begin  // STORE
            MemWrite = 1;
        end
    endcase
end
```

---

## ◆ 5.3 プログラムカウンタ（PC）

### ▫️役割：

* 現在の命令アドレスを保持
* クロックごとに次の命令へ（`PC ← PC + 1`）

### ▫️拡張動作：

* 分岐命令時に `PC ← 新アドレス`
* `ジャンプ／条件分岐` もここで制御

### ▫️Verilog例：

```verilog
always @(posedge clk) begin
    if (reset)
        PC <= 0;
    else if (branch)
        PC <= target_address;
    else
        PC <= PC + 1;
end
```

---

## ◆ 5.4 制御ユニット（Control Unit）

### ▫️役割：

* **マイクロ命令を発行して各モジュールを制御**
* 命令の種類・タイミングに応じて制御信号を生成

### ▫️構成：

| コンポーネント | 内容                       |
| ------- | ------------------------ |
| 命令レジスタ  | フェッチした命令を一時保持            |
| デコーダ    | 命令を解読し、必要な制御信号へ変換        |
| タイミング生成 | 各ステップに応じたマイクロ命令制御を行う FSM |

### ▫️出力する制御信号の例：

* `RegDst`：レジスタ宛先選択
* `MemToReg`：メモリ→レジスタ
* `ALUControl`：ALUの動作選択
* `Jump, Branch`：ジャンプ／分岐制御

---

## ✅ まとめ表（命令制御と回路構成の対応）

| 項目        | 内容                 | 対応する回路モジュール        |
| --------- | ------------------ | ------------------ |
| 命令セット     | ISA設計（命令種別とフォーマット） | 命令ROM、定義仕様書        |
| 命令デコーダ    | 命令から制御信号へ          | デコーダ回路（case文）      |
| プログラムカウンタ | 実行中の命令番地を管理        | アドレスカウンタ（+1 or 分岐） |
| 制御ユニット    | 全体を統括する信号生成        | 状態遷移FSM＋制御信号群      |

---

---

## 🔷 第6章：CPU全体の統合 〜演算・命令制御・実装〜

| 単元  | 内容                    | 実装・演習例                                      |
| --- | --------------------- | ------------------------------------------- |
| 6.1 | **データパス構成**           | ALU・レジスタ・メモリ間のデータ流れ設計                       |
| 6.2 | **クロック制御**            | 命令サイクル（Fetch → Decode → Execute）            |
| 6.3 | **Pythonシミュレータで動作確認** | 自作命令（LOAD, ADD, STORE）で8bit計算を模擬            |
| 6.4 | **アセンブリ言語風コード**       | `LOAD R1, #5` や `ADD R1, R2` など高レベル命令の設計と実行 |

---

## ◆ 6.1 データパス構成（Data Path）

### ▫️構成要素：

| モジュール | 役割          |
| ----- | ----------- |
| ALU   | 加算・論理演算等    |
| レジスタ群 | R0〜R7など内部保持 |
| メモリ   | 命令とデータを保持   |
| MUX   | データの選択      |
| デコーダ  | 命令解釈        |

### ▫️データ流れ（例：`ADD R1, R2`）

1. 命令メモリから`ADD R1, R2`取得
2. R1, R2からデータ読み出し
3. ALUで加算 → 結果をR1に格納

---

## ◆ 6.2 クロック制御と命令サイクル

### ▫️命令サイクル（Instruction Cycle）：

| フェーズ       | 動作内容                     |
| ---------- | ------------------------ |
| Fetch      | PCが指す命令をメモリから取得（命令レジスタへ） |
| Decode     | 命令をデコードし、制御信号へ変換         |
| Execute    | ALUやレジスタが動作、結果を保存        |
| Write Back | 必要に応じてレジスタやメモリに書き戻し      |

### ▫️制御ユニット：FSMによる制御信号の遷移（各状態ごとに信号を分離）

---

## ◆ 6.3 Pythonシミュレータで動作確認（8ビットCPU）

### ▫️命令例：

```python
program = [
    "LOAD R1, 5",   # R1 ← 5
    "LOAD R2, 10",  # R2 ← 10
    "ADD R1, R2",   # R1 ← R1 + R2
    "STORE R1, 0"   # MEM[0] ← R1
]
```

### ▫️Pythonコード例（簡易CPU）：

```python
class CPU:
    def __init__(self):
        self.reg = [0]*8
        self.mem = [0]*256
        self.pc = 0

    def execute(self, instr):
        op, *args = instr.split()
        if op == "LOAD":
            reg = int(args[0][1])
            self.reg[reg] = int(args[1])
        elif op == "ADD":
            r1 = int(args[0][1])
            r2 = int(args[1][1])
            self.reg[r1] += self.reg[r2]
        elif op == "STORE":
            r = int(args[0][1])
            addr = int(args[1])
            self.mem[addr] = self.reg[r]

    def run(self, program):
        for instr in program:
            self.execute(instr)

cpu = CPU()
cpu.run(program)
print(cpu.mem[0])  # 出力: 15
```

---

## ◆ 6.4 アセンブリ言語風コード（独自ISA）

### ▫️設計思想：

* 人間が読みやすい形式でマシン命令を抽象化
* 最終的には命令ビット列に変換される（アセンブル）

### ▫️例（高レベル命令 → バイナリ命令）：

| アセンブリ           | 内容           | バイナリ形式（仮）           |
| --------------- | ------------ | ------------------- |
| `LOAD R1, #5`   | 即値5をR1に      | `000 01 000 000101` |
| `ADD R1, R2`    | R1 ← R1 + R2 | `001 01 10 000000`  |
| `STORE R1, [0]` | R1をメモリ0に格納   | `010 01 000 000000` |

> ※ 最終的にこの形式を命令メモリに格納 → CPUが順次実行

---

## ✅ 第6章まとめ：CPU設計の総合演習

| 項目       | 内容                  |
| -------- | ------------------- |
| データパス    | ALU, レジスタ, メモリの接続設計 |
| 命令サイクル   | 各命令の動作分解 → FSMで制御   |
| Python模擬 | 命令列を読み取り、逐次実行・動作確認  |
| アセンブリ化   | 実装可能な高水準命令で動作を記述・検証 |

---