**TO DO**
- [x] Adder.v
- [x] ALU_Ctrl.v
- [x] ALU.v
- [x] MUX_2to1.v
- [x] MUX_3to1.v
- [x] Decoder.v
- [x] Sign_Extend.v
- [x] Simple_Single_CPU.v
- [x] Shift_Left_Two_32.v
### Sign Extend

不太確定 always block 是用來幹嘛的
```verilog
// student ID : 314551134
module Sign_Extend(
data_i,
data_o
);
// I/O ports
input [16-1:0] data_i;
output [32-1:0] data_o;
// Internal Signals
assign data_o[15:0] = data_i[15:0];
assign data_o[31:16] = {16{data_i[15]}};
// Main function
always @(*) begin
end
endmodule
```
Testbench:
```shell
Test Sign_Extend:
data_i (hex) | data_o (hex)
--------------|----------------
1234 | 00001234
ffff | ffffffff
fffe | fffffffe
7fff | 00007fff
8000 | ffff8000
Sign_Extend_tb.v:41: $finish called at 5000 (1ps)
```
### Shift_Left_Two_32

verilog 支援 `<<` bit operation
```verilog
// student ID
module Shift_Left_Two_32(
data_i,
data_o
);
// I/O ports
input [32-1:0] data_i;
output [32-1:0] data_o;
// Internal Signals
assign data_o = data_i << 2;
// Main function
always @(*) begin
end
endmodule
```
Testbench:
```shell
Test Shift_Left_Two_32:
data_i (hex) | data_o (hex)
----------------|----------------
00000001 | 00000004
00000003 | 0000000c
ffffffff | fffffffc
80000000 | 00000000
12345678 | 48d159e0
Shift_Left_Two_32_tb.v:38: $finish called at 5000 (1ps)
```
### MUX_2to1
```verilog
// student ID
module MUX_2to1(
data0_i,
data1_i,
select_i,
data_o
);
parameter size = 0;
// I/O ports
input [size-1:0] data0_i;
input [size-1:0] data1_i;
input select_i;
output [size-1:0] data_o;
// Internal Signals
assign data_o = (select_i) ? data1_i : data0_i;
// Main function
always@(*)begin
end
endmodule
```
Testbench:
```shell
Test MUX_2to1:
select | data0_i | data1_i | data_o
-------|----------|----------|---------
0 | a5 | 3c | a5
1 | a5 | 3c | 3c
0 | 55 | ff | 55
1 | 55 | ff | ff
0 | 00 | ff | 00
1 | 00 | ff | ff
MUX_2to1_tb.v:49: $finish called at 6000 (1ps)
```
帶參數的,用法:
```verilog
// 設定 size
parameter size = 8;
reg [size-1:0] data0_i;
reg [size-1:0] data1_i;
reg select_i;
wire [size-1:0] data_o;
// 宣告待測 MUX
MUX_2to1 #(.size(size)) uut (
.data0_i(data0_i),
.data1_i(data1_i),
.select_i(select_i),
.data_o(data_o)
);
```
### MUX_3to1
For 2-bits Control signals
```verilog
// student ID
module MUX_3to1(
data0_i,
data1_i,
data2_i,
select_i,
data_o
);
parameter size = 0;
// I/O ports
input [size-1:0] data0_i;
input [size-1:0] data1_i;
input [size-1:0] data2_i;
input [2-1:0] select_i;
output [size-1:0] data_o;
// Internal Signals
assign data_o = (select_i == 2'b00) ? data0_i :
(select_i == 2'b01) ? data1_i : data2_i;
// Main function
always@(*)begin
end
endmodule
```
Testbench:
```shell
Test MUX_3to1:
sel | data0 | data1 | data2 | data_o
----|-------|-------|-------|--------
00 | a5 | 3c | f0 | a5
01 | a5 | 3c | f0 | 3c
10 | a5 | 3c | f0 | f0
11 | a5 | 3c | f0 | f0
00 | 00 | ff | 7e | 00
01 | 00 | ff | 7e | ff
10 | 00 | ff | 7e | 7e
MUX_3to1_tb.v:53: $finish called at 7000 (1ps)
```
### Adder
一般的 Adder 沒在管 Overflow 的
```verilog
// student ID
module Adder(
src1_i,
src2_i,
sum_o
);
// I/O ports
input [32-1:0] src1_i;
input [32-1:0] src2_i;
output[32-1:0] sum_o;
// Internal Signals
assign sum_o = src1_i + src2_i;
// Main function
endmodule
```
Testbench:
```shell
Test 32-bit Adder:
src1_i | src2_i | sum_o
--------------|---------------|--------------
00000001 | 00000002 | 00000003
ffffffff | 00000001 | 00000000
80000000 | 80000000 | 00000000
12345678 | 11111111 | 23456789
00000000 | 00000000 | 00000000
Adder_tb.v:41: $finish called at 5000 (1ps)
```
### Decoder (Main Control)
#### Spec.
1. Input : opcode
2. output : RegDst, ALUSrc, MemtoReg, RegWrite, MemRead, MemWrite, Branch, ALUop, jump
#### Instruction Set
- R-type : add, sub, AND, OR, ==NOR==, slt, ==sll==, ==srl==, ==sllv==, ==srlv==, ==jr==
- I-type : lw, sw, beq, bne, ==addi==
- J-type : j, ==jal==
#### Some Note
- addi: `ALUop = 00` 才會跟著做加法
- jal:`Reg[31] = PC + 4` and perform jump, ($31 same as $ra)
- jr:PC = Reg[rs]
- 不細分 R-type,全部輸出一樣的,再讓 ALU control 根據 function code 來輸出對應的 control signal
#### 2-bits control signals
1. RegDst
| RegDst_o | Target | Instruction |
| --------- | ------- | ---------------- |
| `00` | `rt` field | I-type: addi, lw |
| `01` | `rd` field | R-type |
| `10` | `$31` | jal |
| `11` | Preserve | Preserve |
2. MemtoReg
| MemtoReg_o | Source | Instruction |
| ----------- | ---------------- | ---------------- |
| `00` | ALU or Shifter | R-type, addi|
| `01` | memory read data | lw |
| `10` | `PC + 4` | jal |
| `11` | Preserve | |
3. Branch
| Branch_o | Instruction |
| -------- | --- |
| `00` | Non-branch |
| `01` | beq |
| `10` | bne |
| `11` | Preserve |
Branch Taken Timing
- beq :`branch = 01 and zero = 1`
- bne :`branch = 10 and zero = 0`
#### Truth Table
| Instruction | RegDst | ALUSrc | MemtoReg | RegWrite | MemRead | MemWrite | Branch | ALUop | jump |
| ----------- | ------ | ------ | -------- | -------- | ------- | -------- | ------ | ----- | ---- |
| R-type | 01 | 0 | 00 | 1 | 0 | 0 | 00 | 10 | 0 |
| addi | 00 | 1 | 00 | 1 | 0 | 0 | 00 | 00 | 0 |
| lw | 00 | 1 | 01 | 1 | 1 | 0 | 00 | 00 | 0 |
| sw | x | 1 | x | 0 | 0 | 1 | 00 | 00 | 0 |
| beq | x | 0 | x | 0 | 0 | 0 | 01 | 01 | 0 |
| bne | x | 0 | x | 0 | 0 | 0 | 10 | 01 | 0 |
| j | x | x | x | 0 | 0 | 0 | 00 | x | 1 |
| jal | 10 | x | 10 | 1 | 0 | 0 | 00 | x | 1 |
#### PLA (Programmable Logic Array)

```verilog
// student ID : 314551134
module Decoder(
instr_op_i,
ALU_op_o,
ALUSrc_o,
RegWrite_o,
RegDst_o,
Branch_o,
Jump_o,
MemRead_o,
MemWrite_o,
MemtoReg_o
);
// I/O ports
input [6-1:0] instr_op_i;
output [2-1:0] ALU_op_o;
output [2-1:0] RegDst_o, MemtoReg_o;
output [2-1:0] Branch_o;
output ALUSrc_o, RegWrite_o, Jump_o, MemRead_o, MemWrite_o;
// Instruction opcode parameters
parameter Rtype = 6'b000000;
parameter ADDI = 6'b001001;
parameter LW = 6'b101100;
parameter SW = 6'b100100;
parameter BEQ = 6'b000110;
parameter BNE = 6'b000101;
parameter J = 6'b000111;
parameter JAL = 6'b000011;
assign RegDst_o = (instr_op_i == Rtype) ? 2'b01 :
(instr_op_i == JAL) ? 2'b10 : 2'b00;
assign ALUSrc_o = (instr_op_i == ADDI || instr_op_i == LW || instr_op_i == SW);
assign MemtoReg_o = (instr_op_i == LW) ? 2'b01 :
(instr_op_i == JAL) ? 2'b10 : 2'b00;
assign RegWrite_o = (instr_op_i == Rtype || instr_op_i == ADDI ||
instr_op_i == LW || instr_op_i == JAL);
assign MemRead_o = (instr_op_i == LW);
assign MemWrite_o = (instr_op_i == SW);
assign Branch_o = (instr_op_i == BEQ) ? 2'b01 :
(instr_op_i == BNE) ? 2'b10 : 2'b00;
assign ALU_op_o = (instr_op_i == Rtype) ? 2'b10 :
(instr_op_i == BEQ || instr_op_i == BNE) ? 2'b01 : 2'b00;
assign Jump_o = (instr_op_i == J || instr_op_i == JAL);
endmodule
```
Testbench:
```shell
Time Opcode ALUop RegDst ALUSrc MemtoRegRegWriteMemRead MemWriteBranch Jump
10000 Rtype 10 01 0 00 1 0 0 00 0
20000 ADDI 00 00 1 00 1 0 0 00 0
30000 LW 00 00 1 01 1 1 0 00 0
40000 SW 00 00 1 00 0 0 1 00 0
50000 BEQ 01 00 0 00 0 0 0 01 0
60000 BNE 01 00 0 00 0 0 0 10 0
70000 J 00 00 0 00 0 0 0 00 1
80000 JAL 00 10 0 10 1 0 0 00 1
Decoder_tb.v:74: $finish called at 80000 (1ps)
```
### ALU Control
#### Spec.
1. input : ALUop, Function code
2. output : ALUCtrl_o, FURslt_o, leftRight_o, shifhterSource_o, PC_source_o
#### Control signal
| Control signal | bit|value | function |
| --------------------- | ------ | --------------------------------------------------------------- | ---------------------------------------------------------------------- |
| **FURslt\_o** | 1 bit | 0 = ALU <br>1 = Shifter | 決定最終寫回暫存器的資料是來自 ALU 還是 Shifte |
| **leftRight\_o** | 1 bit | 0 =Shift Left<br>1 = Shift Right | 告訴 Shifter 模組要將輸入資料向左移還是向右移 |
| **shifhterSource\_o** | 1 bit | 0 = shamt field<br>1 = register | 決定 Shifter 的移位位數是來自指令的shamt 還是 register |
| **JR\_source\_o** | 1 bit | 0 = PC+4<br>1 = register | 在 `jr` 指令中,讓 PC 設定成暫存器的值 |
- FURslt = Function Unit Result
#### Truth Table
| Instruction | ALUop1 | ALUop0 | F5 | F4 | F3 | F2 | F1 | F0 | Operation | Value |
|-------------|--------|--------|----|----|----|----|----|----|-----------|---------------------|
| add | 1 | 0 | 1 | 0 | 0 | 0 | 1 | 1 | 0010 | Src1 + Src2 |
| sub | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 1 | 0110 | Src1 - Src2 |
| and | 1 | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 0001 | Src1 & Src2 |
| or | 1 | 0 | 1 | 0 | 0 | 1 | 0 | 1 | 0000 | Src1 \| Src2 |
| nor | 1 | 0 | 1 | 0 | 1 | 0 | 1 | 1 | 1101 | ~(Src1 \| Src2) |
| slt | 1 | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 0111 | (Src1 < Src2):? 1:0 |
| sll | 1 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | xxxx | Shifter |
| srl | 1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | xxxx | Shifter |
| sllv | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 | xxxx | Shifter |
| srlv | 1 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | xxxx | Shifter |
| jr | 1 | 0 | 0 | 0 | 1 | 1 | 0 | 0 | xxxx | x |
| addi | 0 | 0 | x | x | x | x | x | x | 0010 | Src1 + imm1 |
| lw | 0 | 0 | x | x | x | x | x | x | 0010 | Src1 + imm1 |
| sw | 0 | 0 | x | x | x | x | x | x | 0010 | Src1 + imm1 |
| beq | 0 | 1 | x | x | x | x | x | x | 0110 | Src1 - Src2 |
| bne | 0 | 1 | x | x | x | x | x | x | 0110 | Src1 - Src2 |
| j | x | x | x | x | x | x | x | x | xxxx | x |
| jal | x | x | x | x | x | x | x | x | xxxx | x |
```verilog
// student ID
module ALU_Ctrl(
funct_i,
ALUOp_i,
ALUCtrl_o,
FURslt_o,
leftRight_o,
shifhterSource_o,
PC_source_o
);
// I/O ports
input [6-1:0] funct_i;
input [2-1:0] ALUOp_i;
output reg [4-1:0] ALUCtrl_o;
output reg FURslt_o; // 1-bit: 0=ALU, 1=Shifter
output reg leftRight_o;
output reg shifhterSource_o;
output reg PC_source_o;
// funct code parameters
localparam ADD = 6'b100011;
localparam SUB = 6'b100001;
localparam AND = 6'b100110;
localparam OR = 6'b100101;
localparam NOR = 6'b101011;
localparam SLT = 6'b101000;
localparam SLL = 6'b000010;
localparam SRL = 6'b000100;
localparam SLLV = 6'b000110;
localparam SRLV = 6'b001000;
localparam JR = 6'b001100;
always @(*) begin
// default value
ALUCtrl_o = 4'b0000;
FURslt_o = 1'b0;
leftRight_o = 1'b0;
shifhterSource_o = 1'b0;
PC_source_o = 1'b0;
case (ALUOp_i)
2'b10: begin // R-type
case (funct_i)
ADD: ALUCtrl_o = 4'b0010; // add
SUB: ALUCtrl_o = 4'b0110; // sub
AND: ALUCtrl_o = 4'b0001; // and
OR: ALUCtrl_o = 4'b0000; // or
NOR: ALUCtrl_o = 4'b1101; // nor
SLT: ALUCtrl_o = 4'b0111; // slt
SLL: begin
FURslt_o = 1'b1; // Shifter
leftRight_o = 1'b0; // <<
shifhterSource_o = 1'b0; // shamt
ALUCtrl_o = 4'bxxxx;
end
SRL: begin
FURslt_o = 1'b1; // Shifter
leftRight_o = 1'b1; // >>
shifhterSource_o = 1'b0; // shamt
ALUCtrl_o = 4'bxxxx;
end
SLLV: begin
FURslt_o = 1'b1;
leftRight_o = 1'b0; // <<
shifhterSource_o = 1'b1; // register
ALUCtrl_o = 4'bxxxx;
end
SRLV: begin
FURslt_o = 1'b1;
leftRight_o = 1'b1; // <<
shifhterSource_o = 1'b1; // register
ALUCtrl_o = 4'bxxxx;
end
JR: begin
PC_source_o = 1'b1; // PC = register value
ALUCtrl_o = 4'bxxxx;
end
default: ALUCtrl_o = 4'b0000;
endcase
end
2'b00: begin // addi, lw, sw
ALUCtrl_o = 4'b0010; // add
end
2'b01: begin // beq, bne
ALUCtrl_o = 4'b0110; // sub
end
default: begin // j, jal
ALUCtrl_o = 4'bxxxx;
end
endcase
end
endmodule
```
### ALU
```verilog
// student ID
module ALU(
src1_i,
src2_i,
ctrl_i,
result_o,
zero_o,
overflow
);
// I/O ports
input [32-1:0] src1_i;
input [32-1:0] src2_i;
input [4-1:0] ctrl_i;
output reg[32-1:0] result_o;
output zero_o;
output overflow;
// Internal signals
parameter ADD = 4'b0010;
parameter SUB = 4'b0110;
parameter AND = 4'b0001;
parameter OR = 4'b0000;
parameter NOR = 4'b1101;
parameter SLT = 4'b0111;
assign zero_o = (result_o == 32'b0);
assign overflow = ~((ctrl_i == SUB) ^ (src1_i[31] ^ src2_i[31])) & (src1_i[31] ^ result_o[31]) & (ctrl_i == SUB | ctrl_i == ADD);
// Main function
always @(*) begin
case (ctrl_i)
ADD: result_o = src1_i + src2_i;
SUB: result_o = src1_i - src2_i;
AND: result_o = src1_i & src2_i;
OR: result_o = src1_i | src2_i;
NOR: result_o = ~(src1_i | src2_i);
SLT: result_o = src1_i < src2_i;
default: result_o = 32'b0;
endcase
end
endmodule
```
### Single Cycle Machine