# 手搓 CPU - 未來無限可期
微算機專題,用電子元件自製 CPU,並結合 pic18 的應用。
題目:微處理器創新整合應用
[實體 DEMO]:12/18
[上傳書面報告]:12/21
## 架構:
控制單元、IO 單元、ALU、Register、Memory、指令集、Program counter
以 8bit 為 word
### pic18f4520:
作為我們與 CPU 互動的介面,有一顆負責將指令燒錄進 Program Memory,或者作為直譯器,以 UART 操作 CPU(超他媽炫砲)
另一顆則負責用我們專門設計的 register,與 CPU 互動
### 實際空間分配

### Register
以 DFF 實現
提供 8 個 Reg
Reg[0] 是 0x00
Reg[1] 實作特殊功能用,暫且保留(如 BANK)
Reg[2:5] 單純 register
Reg[6] 對 CPU 來說 Read Only,由外部決定
Reg[7] 其值專門給外部讀取
|WriteToReg|CP|IN|D|Q|
|------|------|------|------|------|
|0|-|X|X|$Q_{n-1}$|
|1|↑|X|IN|D|
控制是否要發出正緣訊號給 DFF
##### latch-based clock gating
### ALU:
8 bit input
提供運算:
|id|name|實作方式|包含指令|
|------|------|------|------|
|0|A and B|||
|1|A xor B|||
|2|not A|||
|3|A or B|||
|4|A add B|||
|5|A sub B|(not B) add A with carry|NEG (0 - B)|
|6|lrotate A|||
|7|rrotate A|||
### PC(Program counter)
找到 instruction 的位置並從 program memory 抓進 instruction register
jump 等指令會賦值 pc = x,或者一般執行時 pc += 1
### Data Memory
#### sram(program memory 用):
- 兩個
- 第一個:RD為I/O,RB為地址線
- 第二個:RC0~5、RE 1, 2(6, 7的位置)為I/O,RB為地址線
- RC6, 7是RX, TX要用來debug所以先不用
- ~~RA 要調設定好麻煩~~
#### IO 問題
如何確保寫的時候能將 B 寫進去,而讀的時候 B 能不影響 output?
把 SN74HC245N 當 tri-state buffer 控制 IO 要不要吃輸入
平時要把 CS 設定好,需要用時再開啟
以 74HC74 做微狀態機
要保證:
CPU 給對的訊號在 CS 打開前
在沒有連續 LOAD/STORE 前應該都做得到?
- 非 LOAD/STORE
1. SRAM_CS = 0
- LOAD:
- STATE 0:
SRAM_CS = 1 ; 關閉 SRAM
CPU_OE = 1 ; CPU 停止輸出
- STATE 1:
SRAM_OE = 0 ; SRAM 驅動資料線
SRAM_CS = 0 ; 開啟 SRAM
- STORE
- STATE 0:
SRAM_CS = 1 ; 關閉 SRAM
SRAM_OE = 1 ; SRAM 不驅動資料線
- STATE 1:
CPU_OE = 1 ; CPU 開始輸出
SRAM_CS = 0 ; 開啟 SRAM
### pipeline:
範例(by 祭祖簡報):

我們的 4 stage pipeline 結構:

由於我們使用 Bank 而不是 offset 來支援 data memory 的存取,所以 ex 和 mem 可以平行的在同一 stage 處理,也降低了硬體設計的複雜度。
#### 各階段要往後送的資料:
| 階段 | 內容 | Register 需求 |
| --- | --- | --- |
| IF / ID | 指令本身(Instruction):<br>下一階段需要知道指令是什麼,才能解碼。<br>PC(Program Counter):<br>用於計算 branch/jump 目標或更新<br>|3 個|
| ID / EX&MEM |A, B 兩個的數值,對 ALU 是兩個運算元。對 MEM 來說 B 是 addr 的目標,A 是低 8 位元的 addrs。<br>A 與 B 的 id,讓 Forwarding 判斷是否要跟 EX&MEM/WB 取值。<br>target id:<br>WB 階段要知道要寫回哪個暫存器,也讓 Forwarding 知道能否使用。<br>B_src:<br>B是否來自 register,若不是則不能 Forwarding(A 一定來自 register 所以不需要)<br>ALU control:<br>(做什麼運算)。<br>MemRead / MemWrite:<br>是否讀寫記憶體<br>RegWrite:<br>是否要寫回暫存器<br>PC:<br>用於 EX 階段做 branch 計算。|6~8 個|
| EX&MEM / WB |result:<br>LOAD -> Memory 讀的資料。<br>算數 -> ALU 結果。<br>RegWrite:<br>WB 是否寫回暫存器。<br>target id:<br>WB 回哪。|2 個|
#### Forwarding:
ALU 要看他的 input 是否是後面 EX&MEM 的結果,要確保他們是要 Write Back 的。

if (EX&MEM/WB.RegWrite && A.rs == EX&MEM/WB.rd && A_is_reg) ALU_INPUT = EX&MEM/WB.data
else ALU_INPUT = ID/EX.A.data
#### Hazard detection:
如果 Branch 會發生,要將原本做的事清理乾淨(前兩個 STAGE 的控制訊號必須清 0)
實作方式:ID/EX&M 控制訊號設為全 0,IF/ID 的指令給一組沒實際作用的
### 指令集:
#### 硬體端
如果是 IMM 類型指令,其 imm 在 Ex/MEM 階段一定是 B
如果是 REG 類型指令,reg_1 為 A,reg_2 為 B
如果有 MEM 操作,mem_addr 必定是 B
如果是 條件分支(B2),由 A 與 B 比較,硬體會另外實作 PC+offset
指令 decoder 概念圖
|類型|opcode|rd|A|B|offset|
|-|-|-|-|-|-|
|IMM|00xxx[0-4]|5~7|Reg[5-7]|8~F|-|
|REG|01xxx,xx[0-4,8-9]|5~7|Reg[A-C]|Reg[D-F]|-|
|LOADI|10000[0-4]|5~7|-|8~F|-|
|STOREI|10001[0-4]|-|Reg[5-7]|8~F|-|
|LOAD|10010[0-4]|5~7|-|Reg[D-F]|-|
|STORE|10011[0-4]|-|Reg[5-7]|Reg[D-F]|-|
|B1|10100xxx[0-7]|-|-|-|8~F|
|B2|11X[0-1,F]|-|Reg[5-7]|Reg[2-4]|sign_ex(8-E)|
|IF/ID|值|大小(bit)|
|-|-|-|
|instruction|`instruction`|16|
|PC|`PC`|8|
|ID/EX&MEM|值|大小(bit)|產生單元|進度|
|-|-|-|-|-|
|isBranch|`Conditional_Branch \| Unconditional_Branch`|1|Control|存在|
|Unconditional_Branch|`101`|1|IF/ID|存在|
|Conditional_Branch|`11`|1|IF/ID|存在|
|Conditional_Branch_Type|`[F]`|1|IF/ID|存在|
|offset|`[8,E]+(Conditional_Branch&[E] \| !Conditional_Branch&[F])`|8|Sign_ex|正確|
|NEW_PC|`PC + offset`|8|PC_adder|正確|
|is_WB|`[0]`|1|IF/ID|存在|
|WB_rd|`[5~7]`|3|IF/ID|存在|
|MemRead|`1x0x0`|1|Control|存在|
|MemWrite|`1x0x1`|1|Control|存在|
|ALU_op|`[2~4]`|3|IF/ID|存在|
|A_isreg|`true`|1|-|存在|
|B_isreg|`(x1 \| 10x1)`|1|Control|存在|
|A_regid|`(01)&[A-C] \| (1\|0)&[5-7]`|3+1|Control|存在|
|B_regid|`(11)&[2-4]\|(0\|0)&[D-F]`|3+1|Control|存在|
|A_value|`Reg[A_regid]`|8|register|可存在|
|B_value|`((!b_isreg)&[8~F])\|:(b_isreg&Reg[b_regid]`|8|register/imm MUX|可存在|
|EX&MEM/WB|值|大小(bit)|
|-|-|-|
|is_WB|`[0]`|1|
|WB_rd|`[5~7]`|3|
|WB_VALUE|`WB_VALUE`|8|
|WB_rd(8bit)|WB_rd|8|
共同前綴:00
| 指令 | 說明 | opcode | type |
|------|------|------|------|
| ANDI,breg_rd,imm | `Reg[reg_rd] &= imm` |000|IMM|
| XORI,reg_rd,imm | `Reg[reg_rd] ^= imm` |001|IMM|
| ORI,reg_rd,imm | `Reg[reg_rd] \|= imm` |011|IMM|
| ADDI,reg_rd,imm | `Reg[reg_rd] += imm` |100|IMM|
| SUBI,reg_rd,imm | `Reg[reg_rd] -= imm` |101|IMM|
共同前綴:01
| 指令 | 說明 | opcode | type |
|------|------|------|------|
| NOT,reg_rd,reg | `Reg[reg_rd] = !Reg[reg]` |010|IMM|
| LROTATE,reg_rd,reg | `Reg[reg_rd] = Reg[reg]<<1` |110|IMM|
| RROTATE,reg_rd,reg | `Reg[reg_rd] = Reg[reg]>>1` |111|IMM|
| AND,reg_rd,reg_1,reg_2 | `Reg[reg_rd] = Reg[reg_1]&Reg[reg_2]` |000|REG|
| XOR,reg_rd,reg_1,reg_2 | `Reg[reg_rd] = Reg[reg_1]^Reg[reg_2]` |001|REG|
| OR,reg_rd,reg_1,reg_2 | `Reg[reg_rd] = Reg[reg_1]\|Reg[reg_2]` |011|REG|
| ADD,reg_rd,reg_1,reg_2 | `Reg[reg_rd] = Reg[reg_1]+Reg[reg_2]` |100|REG|
| SUB,reg_rd,reg_1,reg_2 | `Reg[reg_rd] = Reg[reg_1]-Reg[reg_2]` |101|REG|
共同前綴:10
| 指令 | 說明 | opcode | type |
|------|------|------|------|
| LOADI,reg_rd,imm_mem | `Reg[reg_rd] = Mem[bank,imm_mem]` |000|LOADI|
| STOREI,reg,imm_mem | `Mem[bank,imm_mem] = Reg[reg]` |001|STOREI|
| LOAD,reg,reg_mem | `Reg[reg_rd] = Mem[bank,Reg[reg_mem]]` |010|LOAD|
| STORE,reg,reg_mem | `Mem[bank,Reg[reg_mem]] = Reg[reg]` |011|STORE|
| JUMP,imm| `PC += imm` |100|B1|
共同前綴:11
| 指令 | 說明 | opcode | type |
|------|------|------|------|
| JUMP-IF-EQ,reg_1,reg_2,imm2| `if(Reg[reg_1] == Reg[reg_2]) PC += imm2` |0|B2|
| JUMP-IF-LESS,reg_1,reg_2,imm2| `if(Reg[reg_1] < Reg[reg_2]) PC += imm2` |1|B2|
> 可以用來實作 jump-if-zero、jump-if-greater 等
指令長度
opcode:5
reg_addr:3
imm:8
imm2:7
### 時序上會有問題的部分?
Program Memery 的讀取
Data Memory 的讀寫
Register 的讀 (WriteBack) 寫(ID)
統一有 clock1 與 clock2
clock2 = !clock1
clock 上緣觸發 register 將對的值設定好
clock 下緣觸發 register 的寫入 clock
$clock_i$ = clock nor ($write_i$ or $!is\_reg$)
### 工作頻率:
還未算最長 delay 路徑
### 元件:
74HC00 NAND

74HC02 NOR

74HC04 NOT

74HC08 AND

74HC32 OR

74HC86 XOR

74HC573 latch


74HC574 DFF


[74HC139](https://www.ti.com/lit/ds/symlink/sn74hc139-q1.pdf?ts=1763995453072&ref_url=https%253A%252F%252Fwww.google.com%252F)


HM628128 Sram


74HC74 D-Trigger
74HC245


74HC283 adder

### 有用的網站
[畫方塊圖](https://app.diagrams.net/)
[元件圖](https://app.ultralibrarian.com/)
## 專題工作順序:
[專題大綱提案繳交]:11/20
[實體 DEMO]:12/18
[上傳書面報告]:12/21
