# 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 - ![](https://i.imgur.com/o3yvFDr.png) - - FENCE.I - ![](https://i.imgur.com/eTKo2On.png) #### control & status reg (CSR) XXX - CSR - timers & counters #### environment call ![](https://i.imgur.com/XJBP7kF.png) - 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`