# RISC-V CPU Project
## Links
Files:
https://drive.google.com/drive/folders/1dtr3nY3f3Z_RMh9FDAcq3bSkW_cG-gb6?usp=share_link
Github:
https://github.com/Tyan-0978/RISC-V_CPU
## File Architecture
- cpu.v
- inst_memory.v
- inst_dec.v
- reg_file.v
- **alu/**
- alu.v
- logic.v
- int_add_sub.v
- int_mul.v
- int_div.v
- fp_add_sub.v
- fp_mul.v
- fp_div.v
- data_memory.v
## 分工
1. 曾
- 讀 RISC-V spec,整理各個指令的功能
- 寫 inst_dec.v
2. 陳
- inst_memory.v
- data_memory.v
- reg_file.v
3. 田
- alu/
## Test
```
addi x11 x0 10
ecall 11
```
00A00593
00058073
```
addi a1 x0 10
addi a2 x0 20
add a3 a1 a2
ecall a3
```
00A00593
01400613
00C586B3
00061073
```
addi a1 x0 10 # num of iteration
addi a2 x0 0 # index
addi a3 x0 0 # a
addi a4 x0 1 # b
fib:
add a5 a3 a4
add a3 a4 x0
add a4 a5 x0
addi a2 a2 1
bne a2 a1 fib
ecall a4
```
00A00593
00000613
00000693
00100713
00E687B3
000706B3
00078733
00160613
FEB618E3
00070073
```
addi a1 x0 10
addi a2 x0 0
addi a3 x0 1
addi a4 x0 1
fact:
mul a4 a3 a4
addi a3 a3 1
addi a2 a2 1
bne a2 a1 fact
ecall a4
```
```verilog
0: read_data = 32'h00A00593;
1: read_data = 32'h00000613;
2: read_data = 32'h00100693;
3: read_data = 32'h00100713;
4: read_data = 32'h02E68733;
5: read_data = 32'h00168693;
6: read_data = 32'h00160613;
7: read_data = 32'hFEB61AE3;
8: read_data = 32'h00070073;
```
Modulo
```
addi a1 x0 1000
addi a2 x0 0
addi a3 x0 7
addi a4 x0 101
mod:
mul a3 a3 a3
rem a3 a3 a4
addi a2 a2 1
bne a2 a1 mod
ecall a3
```
```verilog
0: read_data = 32'h3E800593;
1: read_data = 32'h00000613;
2: read_data = 32'h00700693;
3: read_data = 32'h06500713;
4: read_data = 32'h02D686B3;
5: read_data = 32'h02E6E6B3;
6: read_data = 32'h00160613;
7: read_data = 32'hFEB61AE3;
8: read_data = 32'h00068073;
```
## ISA
### RV32I
#### integer
- computational
- reg-imm
- reg-reg
- NOP
`ADDI x0, x0, 0`
#### control
- unconditional jumps
- JAL
- JALR (jump)
- conditional branches
- BEQ/BNE
- BLT
- BGE
#### Load/Store
- LOAD
- STORE
#### memory XXX
- FENCE
- 
-
- FENCE.I
- 
#### control & status reg (CSR) XXX
- CSR
- timers & counters
#### environment call

- ECALL
- request the operating system
- EBREAK
- give control to the debugging environment
### RV32M
### RV32A XXX
### RV32F XXX
#### single precision floating point
## I/O Ports
### cpu.v
```verilog
module cpu (
input i_rst_n,
input i_clk,
input i_start,
// ecall pins
output o_ecall_ready,
output [31:0] o_ecall_data
);
```
### reg_file.v
```verilog
module reg_file(
input i_rst_n,
input i_clk,
input i_reg_write,
input [ 4:0] i_write_rd,
input [31:0] i_write_data,
input [ 4:0] i_read_rs1,
input [ 4:0] i_read_rs2,
output [31:0] o_rs1_data,
output [31:0] o_rs2_data
);
```
### inst_memory.v
nios_system n1(
.clocks_ref_clk_clk(CLOCK_50),
.clocks_ref_reset_reset(~KEY[0]),
.clocks_sdram_clk_clk(DRAM_CLK),
.sdram_s1_address(address),
.sdram_s1_byteenable_n(byteenable_n),
.sdram_s1_chipselect(chipselect),
.sdram_s1_writedata(writedata),
.sdram_s1_read_n(read_n),
.sdram_s1_write_n(write_n),
.sdram_s1_readdata(readdata),
.sdram_s1_readdatavalid(readdatavalid),
.sdram_s1_waitrequest(waitrequest),
.sdram_wire_addr(DRAM_ADDR),
.sdram_wire_ba(DRAM_BA),
.sdram_wire_cas_n(DRAM_CAS_N),
.sdram_wire_cke(DRAM_CKE),
.sdram_wire_cs_n(DRAM_CS_N),
.sdram_wire_dq(DRAM_DQ),
.sdram_wire_dqm(DRAM_DQM),
.sdram_wire_ras_n(DRAM_RAS_N),
.sdram_wire_we_n(DRAM_WE_N)
);
---
### alu/
#### alu
```verilog
module alu (
input i_rst_n,
input i_clk,
// control
input [ 2:0] i_op_mode,
input [ 1:0] i_func_op, // functional options
input i_fp_mode, // 0: integer, 1: FP
input i_stall,
output o_stall,
// operands & result
input [31:0] i_a,
input [31:0] i_b,
output [31:0] o_result
);
```
- `[2:0] i_op_mode`:
- `0`: idle (do nothing)
- `1`: logic operation (AND, OR, XOR)
- `2`: shift operation
- `3`: comparison
- `4`: integer addition/subtraction
- `5`: integer multiplication
- `6`: integer division
- `7`: integer modulo operation
:::success
:::spoiler logic
```verilog
module logic (
input [1:0] i_mode, // 0: AND, 1: OR, 2: XOR
input [31:0] i_a,
input [31:0] i_b,
output [31:0] o_result
);
```
- type: combinational
- input
- `[1:0] i_mode`
- `0`: AND
- `1`: OR
- `2`: XOR
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `[31:0] o_result`
:::
:::success
:::spoiler shift
```verilog
module shift (
input i_mode, // 0: logical, 1: arithmetic (keep sign)
input i_direction, // 0: left, 1: right
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_result
);
```
- type: combinational
- input
- `i_mode`
- `0`: logical
- `1`: arithmetic (keep sign)
- `i_direction`
- `0`: left
- `1`: right
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `[31:0] o_result`
:::
:::success
:::spoiler comp
```verilog
module comp (
input i_eq, // 0: without equal, 1: with equal
input [1:0] i_mode, // 00: <, 01: >, 1x: ==
input [31:0] i_a,
input [31:0] i_b,
output [31:0] o_result
);
```
- type: combinational
- input
- `i_eq`
- `0`: no equal sign (<, >, !=)
- `1`: with equal sign (<=, >=, ==)
- `[1:0] i_mode`
- `00`: smaller than (<)
- `01`: larger than (>)
- `1x`: equal (==)
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `[31:0] o_result`
:::
:::success
:::spoiler int_add_sub
```verilog
module int_add_sub (
input i_mode, // 0: add, 1: subtract
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_result
);
```
- type: combinational
- input
- `i_mode`
- `0`: add
- `1`: subtract
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `[31:0] o_result`
:::
:::success
:::spoiler int_mul
```verilog
module int_mul (
input i_rst_n,
input i_clk,
input i_valid,
output o_valid,
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_result
);
```
- type: sequential
- input
- `i_rst_n`
- `i_clk`
- `i_valid`
- `0`: no input
- `1`: valid input
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `o_valid`
- pull to `1` when multiplication finished
- `[31:0] o_result`
:::
:::success
:::spoiler int_div
```verilog
module int_div (
input i_rst_n,
input i_clk,
input i_valid,
output o_valid,
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_quotient,
output signed [31:0] o_remainder
);
```
- type: sequential
- input
- `i_rst_n`
- `i_clk`
- `i_valid`
- `0`: no input
- `1`: valid input
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `o_valid`
- pull to `1` when division finished
- `[31:0] o_quotient`
- `[31:0] o_remainder`
:::
:::success
:::spoiler fp_add_sub
```verilog
module int_add_sub (
input i_mode, // 0: add, 1: subtract
input [31:0] i_a,
input [31:0] i_b,
output [31:0] o_result
);
```
- type: combinational
- input
- `i_mode`
- `0`: add
- `1`: subtract
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `[31:0] o_result`
:::
:::success
:::spoiler fp_mul
```verilog
module fp_mul (
input i_rst_n,
input i_clk,
input i_valid,
output o_valid,
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_result
);
```
- type: sequential
- input
- `i_rst_n`
- `i_clk`
- `i_valid`
- `0`: no input
- `1`: valid input
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `o_valid`
- pull to `1` when multiplication finished
- `[31:0] o_result`
:::
:::success
:::spoiler fp_div
```verilog
module fp_div (
input i_rst_n,
input i_clk,
input i_valid,
output o_valid,
input signed [31:0] i_a,
input signed [31:0] i_b,
output signed [31:0] o_result
);
```
- type: sequential
- input
- `i_rst_n`
- `i_clk`
- `i_valid`
- `0`: no input
- `1`: valid input
- `[31:0] i_a`
- `[31:0] i_b`
- output
- `o_valid`
- pull to `1` when division finished
- `[31:0] o_result`
:::
### inst_dec.v
- input
- `[31:0] i_inst_data`
- output
- `[4:0] o_rd`
- `[4:0] o_rs1`
- `[4:0] o_rs2`
- `[31:0] o_imm`
- `[31:0] o_jump_imm`
- `[2:0] o_funct3`
- `o_ecall`
- `o_alusrc`
- `o_mem_to_reg`
- `o_reg_write`
- `o_mem_read`
- `o_mem_write`
- `o_branch`
- `[2:0] o_op_mode`
- `[2:0] o_func_op`
- `o_fp_mode`