From bfbed38033ca7cefeb15077cd8a04e794dc6d632 Mon Sep 17 00:00:00 2001 From: TonyCrane Date: Wed, 26 Apr 2023 20:11:18 +0800 Subject: [PATCH] feat: single cycle CPU --- .gitignore | 6 +- README.md | 36 ++- src/Control.edf | 418 -------------------------- src/Control.v | 29 -- src/Control_sim.v | 319 -------------------- src/Core.v | 61 ++-- src/CoreSim.v | 24 ++ src/Core_tb.sv | 77 ----- src/IO_Manager.sv | 24 -- src/Makefile | 18 ++ src/SCPU.v | 54 ++-- src/Top.sv | 35 +-- src/components/ALU.v | 37 +++ src/components/Control.v | 75 +++++ src/components/Datapath.v | 107 +++++++ src/components/ImmGen.v | 47 +++ src/components/Regs.v | 32 ++ src/{ => headers}/AluOp.vh | 0 src/headers/Opcodes.vh | 32 ++ src/lab10.coe | 3 - src/lab10_all.coe | 3 - src/memory/RAM.v | 26 ++ src/memory/ROM.v | 14 + src/tests/bonus.asm | 21 ++ src/tests/bonus.hex | 17 ++ src/{lab10_all.asm => tests/full.asm} | 0 src/tests/full.hex | 54 ++++ src/{lab10.asm => tests/simple.asm} | 0 src/tests/simple.hex | 36 +++ src/utils/Mux2x32.v | 10 + src/utils/Mux4x32.v | 21 ++ src/utils/MuxPC.v | 36 +++ 32 files changed, 686 insertions(+), 986 deletions(-) delete mode 100644 src/Control.edf delete mode 100644 src/Control.v delete mode 100644 src/Control_sim.v create mode 100644 src/CoreSim.v delete mode 100644 src/Core_tb.sv create mode 100644 src/Makefile create mode 100644 src/components/ALU.v create mode 100644 src/components/Control.v create mode 100644 src/components/Datapath.v create mode 100644 src/components/ImmGen.v create mode 100644 src/components/Regs.v rename src/{ => headers}/AluOp.vh (100%) create mode 100644 src/headers/Opcodes.vh delete mode 100644 src/lab10.coe delete mode 100644 src/lab10_all.coe create mode 100644 src/memory/RAM.v create mode 100644 src/memory/ROM.v create mode 100644 src/tests/bonus.asm create mode 100644 src/tests/bonus.hex rename src/{lab10_all.asm => tests/full.asm} (100%) create mode 100644 src/tests/full.hex rename src/{lab10.asm => tests/simple.asm} (100%) create mode 100644 src/tests/simple.hex create mode 100644 src/utils/Mux2x32.v create mode 100644 src/utils/Mux4x32.v create mode 100644 src/utils/MuxPC.v diff --git a/.gitignore b/.gitignore index 496ee2c..a9acfe0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -.DS_Store \ No newline at end of file +.DS_Store + +src/core.vvp +src/dump.vcd +src/wave.gtkw \ No newline at end of file diff --git a/README.md b/README.md index d1ccce3..30b7ecf 100644 --- a/README.md +++ b/README.md @@ -4,4 +4,38 @@ > > **Warning**: 仅供参考,请勿抄袭 -RISC-V CPU,Verilog 实现。 \ No newline at end of file +## 实验进度 + +系统贯通课程会逐步实现一个 RISC-V 五级流水线 CPU,并实现异常处理、分支预测、Cache 等功能。本 repo 通过分支、tag 等来记录实验进度,保存各阶段成果。 + +- [x] 系统 Ⅰ lab5-1/lab5-2:单周期 CPU +- [ ] extra:单周期 CPU with 特权指令/异常处理 +- [ ] 系统 Ⅱ lab1:流水线 CPU (stall) +- [ ] 系统 Ⅱ lab2:流水线 CPU (forwarding) +- [ ] 系统 Ⅱ lab7:流水线 CPU with 特权指令/异常处理 +- [ ] 系统 Ⅲ lab1:流水线 CPU with 动态分支预测 +- [ ] 系统 Ⅲ lab2:流水线 CPU with Cache + +## 实验环境 + +课内使用 vivado 以及 Nexys A7-100T FPGA 开发板进行实验。 + +为了在非 Windows 平台开发/仿真方便,使用了 [Icarus Verilog](https://github.com/steveicarus/iverilog) 以及 [GTKWave](https://github.com/gtkwave/gtkwave/) 进行仿真。 + +## 编译与仿真 + +使用了一个 Makefile 来整合编译、仿真等操作: + +- `make`:编译、仿真,并打开 GTKWave 查看波形 +- `make compile`:编译 +- `make simulate`:仿真,并打开 GTKWave 查看波形 + +需要通过 `GTKWAVE=/path/to/your/gtkwave` 来指定 GTKWave 的路径。 + +## 声明 + +没有认真学过 verilog,写的都挺屎的,反正能跑就行,跑起来了也就懒得改了。仅供参考,参考价值或许也不那么大(x,那就仅供记录(✓ + +## LICENSE + +都是基于 [starter code](https://github.com/TonyCrane/CraneCPU/commit/08b1c5129c9c933bebcf9a755afddb13f8b7d679) 完全自己写的,就用个 MIT License 吧。 \ No newline at end of file diff --git a/src/Control.edf b/src/Control.edf deleted file mode 100644 index 3371967..0000000 --- a/src/Control.edf +++ /dev/null @@ -1,418 +0,0 @@ -(edif Control - (edifversion 2 0 0) - (edifLevel 0) - (keywordmap (keywordlevel 0)) -(status - (written - (timeStamp 2021 05 29 13 58 09) - (program "Vivado" (version "2020.1")) - (comment "Built on 'Wed May 27 19:54:49 MDT 2020'") - (comment "Built by 'xbuild'") - ) -) - (Library hdi_primitives - (edifLevel 0) - (technology (numberDefinition )) - (cell LUT6 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - (port I1 (direction INPUT)) - (port I2 (direction INPUT)) - (port I3 (direction INPUT)) - (port I4 (direction INPUT)) - (port I5 (direction INPUT)) - ) - ) - ) - (cell LUT4 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - (port I1 (direction INPUT)) - (port I2 (direction INPUT)) - (port I3 (direction INPUT)) - ) - ) - ) - (cell LUT3 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - (port I1 (direction INPUT)) - (port I2 (direction INPUT)) - ) - ) - ) - (cell LUT5 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - (port I1 (direction INPUT)) - (port I2 (direction INPUT)) - (port I3 (direction INPUT)) - (port I4 (direction INPUT)) - ) - ) - ) - (cell LUT1 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - ) - ) - ) - (cell LUT2 (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port O (direction OUTPUT)) - (port I0 (direction INPUT)) - (port I1 (direction INPUT)) - ) - ) - ) - (cell INV (celltype GENERIC) - (view netlist (viewtype NETLIST) - (interface - (port I (direction INPUT)) - (port O (direction OUTPUT)) - ) - ) - ) - ) - (Library work - (edifLevel 0) - (technology (numberDefinition )) - (cell Control (celltype GENERIC) - (view Control (viewtype NETLIST) - (interface - (port alu_src_b (direction OUTPUT)) - (port b_type (direction OUTPUT)) - (port branch (direction OUTPUT)) - (port funct7_5 (direction INPUT)) - (port mem_write (direction OUTPUT)) - (port reg_write (direction OUTPUT)) - (port (array (rename alu_op "alu_op[3:0]") 4) (direction OUTPUT)) - (port (array (rename funct3 "funct3[2:0]") 3) (direction INPUT)) - (port (array (rename mem_to_reg "mem_to_reg[1:0]") 2) (direction OUTPUT)) - (port (array (rename op_code "op_code[6:0]") 7) (direction INPUT)) - (port (array (rename pc_src "pc_src[1:0]") 2) (direction OUTPUT)) - ) - (contents - (instance (rename alu_op_0__INST_0 "alu_op[0]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h000000000A002020")) - ) - (instance (rename alu_op_1__INST_0 "alu_op[1]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h000000000A002020")) - ) - (instance (rename alu_op_2__INST_0 "alu_op[2]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h000000000A002020")) - ) - (instance (rename alu_op_3__INST_0 "alu_op[3]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0C0C0C0C0C0CFB08")) - ) - (instance (rename alu_op_3__INST_0_i_1 "alu_op[3]_INST_0_i_1") (viewref netlist (cellref LUT4 (libraryref hdi_primitives))) - (property INIT (string "16'h0080")) - ) - (instance (rename alu_op_3__INST_0_i_2 "alu_op[3]_INST_0_i_2") (viewref netlist (cellref LUT3 (libraryref hdi_primitives))) - (property INIT (string "8'h06")) - (property SOFT_HLUTNM (string "soft_lutpair1")) - ) - (instance (rename alu_op_3__INST_0_i_3 "alu_op[3]_INST_0_i_3") (viewref netlist (cellref LUT5 (libraryref hdi_primitives))) - (property INIT (string "32'hF7FFFFF7")) - (property SOFT_HLUTNM (string "soft_lutpair0")) - ) - (instance (rename alu_op_3__INST_0_i_4 "alu_op[3]_INST_0_i_4") (viewref netlist (cellref LUT4 (libraryref hdi_primitives))) - (property INIT (string "16'hCFBB")) - ) - (instance (rename alu_op_3__INST_0_i_5 "alu_op[3]_INST_0_i_5") (viewref netlist (cellref LUT4 (libraryref hdi_primitives))) - (property INIT (string "16'h7F77")) - (property SOFT_HLUTNM (string "soft_lutpair1")) - ) - (instance alu_src_b_INST_0 (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000000000007")) - ) - (instance b_type_INST_0 (viewref netlist (cellref LUT1 (libraryref hdi_primitives))) - (property INIT (string "2'h1")) - ) - (instance branch_INST_0 (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000000000040")) - ) - (instance (rename mem_to_reg_0__INST_0 "mem_to_reg[0]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000010000001")) - ) - (instance (rename mem_to_reg_1__INST_0 "mem_to_reg[1]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0300000000000001")) - ) - (instance mem_write_INST_0 (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000000000010")) - ) - (instance (rename pc_src_0__INST_0 "pc_src[0]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000000000080")) - ) - (instance (rename pc_src_1__INST_0 "pc_src[1]_INST_0") (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0000000000800000")) - ) - (instance (rename pc_src_1__INST_0_i_1 "pc_src[1]_INST_0_i_1") (viewref netlist (cellref LUT2 (libraryref hdi_primitives))) - (property INIT (string "4'h7")) - (property SOFT_HLUTNM (string "soft_lutpair0")) - ) - (instance reg_write_INST_0 (viewref netlist (cellref LUT6 (libraryref hdi_primitives))) - (property INIT (string "64'h0101440000010001")) - ) - (net (rename alu_op_0_ "alu_op[0]") (joined - (portref O (instanceref alu_op_0__INST_0)) - (portref (member alu_op 3)) - ) - ) - (net (rename alu_op_1_ "alu_op[1]") (joined - (portref O (instanceref alu_op_1__INST_0)) - (portref (member alu_op 2)) - ) - ) - (net (rename alu_op_2_ "alu_op[2]") (joined - (portref O (instanceref alu_op_2__INST_0)) - (portref (member alu_op 1)) - ) - ) - (net (rename alu_op_3_ "alu_op[3]") (joined - (portref O (instanceref alu_op_3__INST_0)) - (portref (member alu_op 0)) - ) - ) - (net (rename alu_op_3__INST_0_i_1_n_0 "alu_op[3]_INST_0_i_1_n_0") (joined - (portref I0 (instanceref alu_op_3__INST_0)) - (portref O (instanceref alu_op_3__INST_0_i_1)) - ) - ) - (net (rename alu_op_3__INST_0_i_2_n_0 "alu_op[3]_INST_0_i_2_n_0") (joined - (portref I1 (instanceref alu_op_3__INST_0)) - (portref O (instanceref alu_op_3__INST_0_i_2)) - ) - ) - (net (rename alu_op_3__INST_0_i_3_n_0 "alu_op[3]_INST_0_i_3_n_0") (joined - (portref I2 (instanceref alu_op_3__INST_0)) - (portref O (instanceref alu_op_3__INST_0_i_3)) - ) - ) - (net (rename alu_op_3__INST_0_i_4_n_0 "alu_op[3]_INST_0_i_4_n_0") (joined - (portref I4 (instanceref alu_op_3__INST_0)) - (portref O (instanceref alu_op_3__INST_0_i_4)) - ) - ) - (net (rename alu_op_3__INST_0_i_5_n_0 "alu_op[3]_INST_0_i_5_n_0") (joined - (portref I5 (instanceref alu_op_0__INST_0)) - (portref I5 (instanceref alu_op_1__INST_0)) - (portref I5 (instanceref alu_op_2__INST_0)) - (portref I5 (instanceref alu_op_3__INST_0)) - (portref O (instanceref alu_op_3__INST_0_i_5)) - ) - ) - (net alu_src_b (joined - (portref O (instanceref alu_src_b_INST_0)) - (portref alu_src_b) - ) - ) - (net b_type (joined - (portref O (instanceref b_type_INST_0)) - (portref b_type) - ) - ) - (net branch (joined - (portref O (instanceref branch_INST_0)) - (portref branch) - ) - ) - (net (rename funct3_0_ "funct3[0]") (joined - (portref I0 (instanceref alu_op_0__INST_0)) - (portref I0 (instanceref b_type_INST_0)) - (portref I2 (instanceref alu_op_3__INST_0_i_1)) - (portref (member funct3 2)) - ) - ) - (net (rename funct3_1_ "funct3[1]") (joined - (portref I0 (instanceref alu_op_1__INST_0)) - (portref I3 (instanceref alu_op_3__INST_0_i_1)) - (portref (member funct3 1)) - ) - ) - (net (rename funct3_2_ "funct3[2]") (joined - (portref I0 (instanceref alu_op_2__INST_0)) - (portref I0 (instanceref alu_op_3__INST_0_i_1)) - (portref (member funct3 0)) - ) - ) - (net funct7_5 (joined - (portref I1 (instanceref alu_op_3__INST_0_i_1)) - (portref I3 (instanceref alu_op_3__INST_0)) - (portref funct7_5) - ) - ) - (net (rename mem_to_reg_0_ "mem_to_reg[0]") (joined - (portref O (instanceref mem_to_reg_0__INST_0)) - (portref (member mem_to_reg 1)) - ) - ) - (net (rename mem_to_reg_1_ "mem_to_reg[1]") (joined - (portref O (instanceref mem_to_reg_1__INST_0)) - (portref (member mem_to_reg 0)) - ) - ) - (net mem_write (joined - (portref O (instanceref mem_write_INST_0)) - (portref mem_write) - ) - ) - (net (rename op_code_0_ "op_code[0]") (joined - (portref I0 (instanceref alu_op_3__INST_0_i_3)) - (portref I0 (instanceref pc_src_1__INST_0_i_1)) - (portref I1 (instanceref alu_op_3__INST_0_i_5)) - (portref (member op_code 6)) - ) - ) - (net (rename op_code_1_ "op_code[1]") (joined - (portref I0 (instanceref alu_op_3__INST_0_i_5)) - (portref I1 (instanceref alu_op_3__INST_0_i_3)) - (portref I1 (instanceref pc_src_1__INST_0_i_1)) - (portref (member op_code 5)) - ) - ) - (net (rename op_code_2_ "op_code[2]") (joined - (portref I2 (instanceref alu_op_3__INST_0_i_2)) - (portref I2 (instanceref alu_op_3__INST_0_i_4)) - (portref I2 (instanceref pc_src_0__INST_0)) - (portref I2 (instanceref pc_src_1__INST_0)) - (portref I3 (instanceref alu_op_0__INST_0)) - (portref I3 (instanceref alu_op_1__INST_0)) - (portref I3 (instanceref alu_op_2__INST_0)) - (portref I3 (instanceref alu_op_3__INST_0_i_5)) - (portref I3 (instanceref alu_src_b_INST_0)) - (portref I3 (instanceref mem_to_reg_0__INST_0)) - (portref I3 (instanceref mem_write_INST_0)) - (portref I3 (instanceref reg_write_INST_0)) - (portref I4 (instanceref mem_to_reg_1__INST_0)) - (portref I5 (instanceref branch_INST_0)) - (portref (member op_code 4)) - ) - ) - (net (rename op_code_3_ "op_code[3]") (joined - (portref I0 (instanceref alu_op_3__INST_0_i_4)) - (portref I0 (instanceref mem_to_reg_0__INST_0)) - (portref I0 (instanceref mem_to_reg_1__INST_0)) - (portref I1 (instanceref alu_op_0__INST_0)) - (portref I1 (instanceref alu_op_1__INST_0)) - (portref I1 (instanceref alu_op_2__INST_0)) - (portref I1 (instanceref mem_write_INST_0)) - (portref I2 (instanceref alu_op_3__INST_0_i_3)) - (portref I2 (instanceref alu_src_b_INST_0)) - (portref I2 (instanceref reg_write_INST_0)) - (portref I4 (instanceref branch_INST_0)) - (portref I4 (instanceref pc_src_1__INST_0)) - (portref I5 (instanceref pc_src_0__INST_0)) - (portref (member op_code 3)) - ) - ) - (net (rename op_code_4_ "op_code[4]") (joined - (portref I0 (instanceref alu_op_3__INST_0_i_2)) - (portref I0 (instanceref mem_write_INST_0)) - (portref I1 (instanceref alu_op_3__INST_0_i_4)) - (portref I1 (instanceref alu_src_b_INST_0)) - (portref I1 (instanceref mem_to_reg_1__INST_0)) - (portref I2 (instanceref alu_op_0__INST_0)) - (portref I2 (instanceref alu_op_1__INST_0)) - (portref I2 (instanceref alu_op_2__INST_0)) - (portref I2 (instanceref mem_to_reg_0__INST_0)) - (portref I3 (instanceref branch_INST_0)) - (portref I3 (instanceref pc_src_0__INST_0)) - (portref I3 (instanceref pc_src_1__INST_0)) - (portref I4 (instanceref reg_write_INST_0)) - (portref (member op_code 2)) - ) - ) - (net (rename op_code_5_ "op_code[5]") (joined - (portref I0 (instanceref alu_src_b_INST_0)) - (portref I1 (instanceref alu_op_3__INST_0_i_2)) - (portref I1 (instanceref pc_src_0__INST_0)) - (portref I1 (instanceref pc_src_1__INST_0)) - (portref I2 (instanceref alu_op_3__INST_0_i_5)) - (portref I2 (instanceref branch_INST_0)) - (portref I2 (instanceref mem_write_INST_0)) - (portref I3 (instanceref alu_op_3__INST_0_i_3)) - (portref I3 (instanceref mem_to_reg_1__INST_0)) - (portref I4 (instanceref mem_to_reg_0__INST_0)) - (portref I5 (instanceref reg_write_INST_0)) - (portref (member op_code 1)) - ) - ) - (net (rename op_code_6_ "op_code[6]") (joined - (portref I0 (instanceref pc_src_0__INST_0)) - (portref I0 (instanceref pc_src_1__INST_0)) - (portref I1 (instanceref branch_INST_0)) - (portref I1 (instanceref mem_to_reg_0__INST_0)) - (portref I1 (instanceref reg_write_INST_0)) - (portref I3 (instanceref alu_op_3__INST_0_i_4)) - (portref I4 (instanceref alu_op_0__INST_0)) - (portref I4 (instanceref alu_op_1__INST_0)) - (portref I4 (instanceref alu_op_2__INST_0)) - (portref I4 (instanceref alu_op_3__INST_0_i_3)) - (portref I4 (instanceref alu_src_b_INST_0)) - (portref I4 (instanceref mem_write_INST_0)) - (portref I5 (instanceref mem_to_reg_1__INST_0)) - (portref (member op_code 0)) - ) - ) - (net (rename pc_src_0_ "pc_src[0]") (joined - (portref O (instanceref pc_src_0__INST_0)) - (portref (member pc_src 1)) - ) - ) - (net (rename pc_src_1_ "pc_src[1]") (joined - (portref O (instanceref pc_src_1__INST_0)) - (portref (member pc_src 0)) - ) - ) - (net (rename pc_src_1__INST_0_i_1_n_0 "pc_src[1]_INST_0_i_1_n_0") (joined - (portref I0 (instanceref branch_INST_0)) - (portref I0 (instanceref reg_write_INST_0)) - (portref I2 (instanceref mem_to_reg_1__INST_0)) - (portref I4 (instanceref pc_src_0__INST_0)) - (portref I5 (instanceref alu_src_b_INST_0)) - (portref I5 (instanceref mem_to_reg_0__INST_0)) - (portref I5 (instanceref mem_write_INST_0)) - (portref I5 (instanceref pc_src_1__INST_0)) - (portref O (instanceref pc_src_1__INST_0_i_1)) - ) - ) - (net reg_write (joined - (portref O (instanceref reg_write_INST_0)) - (portref reg_write) - ) - ) - ) - - (property ADD (string "4'b0000")) - (property SUB (string "4'b1000")) - (property SLL (string "4'b0001")) - (property SLT (string "4'b0010")) - (property SLTU (string "4'b0011")) - (property XOR (string "4'b0100")) - (property SRL (string "4'b0101")) - (property SRA (string "4'b1101")) - (property OR (string "4'b0110")) - (property AND (string "4'b0111")) - ) - ) - ) -(comment "Reference To The Cell Of Highest Level") - - (design Control - (cellref Control (libraryref work)) - (property XLNX_PROJ_DIR (string "E:/vivado/system_lab/SCPU-RISCV")) - (property part (string "xc7a100tcsg324-1")) - ) -) diff --git a/src/Control.v b/src/Control.v deleted file mode 100644 index d54311d..0000000 --- a/src/Control.v +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. -// -------------------------------------------------------------------------------- -// Tool Version: Vivado v.2020.1 (win64) Build 2902540 Wed May 27 19:54:49 MDT 2020 -// Date : Sat May 29 13:57:02 2021 -// Host : DESKTOP-M082HN9 running 64-bit major release (build 9200) -// Command : write_verilog -mode synth_stub D:Control.v -// Design : Control -// Purpose : Stub declaration of top-level module interface -// Device : xc7a100tcsg324-1 -// -------------------------------------------------------------------------------- - -// This empty module with port declaration file causes synthesis tools to infer a black box for IP. -// The synthesis directives are for Synopsys Synplify support to prevent IO buffer insertion. -// Please paste the declaration into a Verilog source file or add the file as an additional source. -module Control(op_code, funct3, funct7_5, pc_src, reg_write, - alu_src_b, alu_op, mem_to_reg, mem_write, branch, b_type) -/* synthesis syn_black_box black_box_pad_pin="op_code[6:0],funct3[2:0],funct7_5,pc_src[1:0],reg_write,alu_src_b,alu_op[3:0],mem_to_reg[1:0],mem_write,branch,b_type" */; - input [6:0]op_code; - input [2:0]funct3; - input funct7_5; - output [1:0]pc_src; - output reg_write; - output alu_src_b; - output [3:0]alu_op; - output [1:0]mem_to_reg; - output mem_write; - output branch; - output b_type; -endmodule diff --git a/src/Control_sim.v b/src/Control_sim.v deleted file mode 100644 index 98a95a9..0000000 --- a/src/Control_sim.v +++ /dev/null @@ -1,319 +0,0 @@ -// Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. -// -------------------------------------------------------------------------------- -// Tool Version: Vivado v.2020.1 (win64) Build 2902540 Wed May 27 19:54:49 MDT 2020 -// Date : Sat May 29 14:34:39 2021 -// Host : DESKTOP-M082HN9 running 64-bit major release (build 9200) -// Command : write_verilog -mode funcsim D:/Control_sim.v -// Design : Control -// Purpose : This verilog netlist is a functional simulation representation of the design and should not be modified -// or synthesized. This netlist cannot be used for SDF annotated simulation. -// Device : xc7a100tcsg324-1 -// -------------------------------------------------------------------------------- -`timescale 1 ps / 1 ps - -(* ADD = "4'b0000" *) (* AND = "4'b0111" *) (* OR = "4'b0110" *) -(* SLL = "4'b0001" *) (* SLT = "4'b0010" *) (* SLTU = "4'b0011" *) -(* SRA = "4'b1101" *) (* SRL = "4'b0101" *) (* SUB = "4'b1000" *) -(* XOR = "4'b0100" *) -(* NotValidForBitStream *) -module Control - (op_code, - funct3, - funct7_5, - pc_src, - reg_write, - alu_src_b, - alu_op, - mem_to_reg, - mem_write, - branch, - b_type); - input [6:0]op_code; - input [2:0]funct3; - input funct7_5; - output [1:0]pc_src; - output reg_write; - output alu_src_b; - output [3:0]alu_op; - output [1:0]mem_to_reg; - output mem_write; - output branch; - output b_type; - - wire [3:0]alu_op; - wire \alu_op[3]_INST_0_i_1_n_0 ; - wire \alu_op[3]_INST_0_i_2_n_0 ; - wire \alu_op[3]_INST_0_i_3_n_0 ; - wire \alu_op[3]_INST_0_i_4_n_0 ; - wire \alu_op[3]_INST_0_i_5_n_0 ; - wire alu_src_b; - wire b_type; - wire branch; - wire [2:0]funct3; - wire funct7_5; - wire [1:0]mem_to_reg; - wire mem_write; - wire [6:0]op_code; - wire [1:0]pc_src; - wire \pc_src[1]_INST_0_i_1_n_0 ; - wire reg_write; - - LUT6 #( - .INIT(64'h000000000A002020)) - \alu_op[0]_INST_0 - (.I0(funct3[0]), - .I1(op_code[3]), - .I2(op_code[4]), - .I3(op_code[2]), - .I4(op_code[6]), - .I5(\alu_op[3]_INST_0_i_5_n_0 ), - .O(alu_op[0])); - LUT6 #( - .INIT(64'h000000000A002020)) - \alu_op[1]_INST_0 - (.I0(funct3[1]), - .I1(op_code[3]), - .I2(op_code[4]), - .I3(op_code[2]), - .I4(op_code[6]), - .I5(\alu_op[3]_INST_0_i_5_n_0 ), - .O(alu_op[1])); - LUT6 #( - .INIT(64'h000000000A002020)) - \alu_op[2]_INST_0 - (.I0(funct3[2]), - .I1(op_code[3]), - .I2(op_code[4]), - .I3(op_code[2]), - .I4(op_code[6]), - .I5(\alu_op[3]_INST_0_i_5_n_0 ), - .O(alu_op[2])); - LUT6 #( - .INIT(64'h0C0C0C0C0C0CFB08)) - \alu_op[3]_INST_0 - (.I0(\alu_op[3]_INST_0_i_1_n_0 ), - .I1(\alu_op[3]_INST_0_i_2_n_0 ), - .I2(\alu_op[3]_INST_0_i_3_n_0 ), - .I3(funct7_5), - .I4(\alu_op[3]_INST_0_i_4_n_0 ), - .I5(\alu_op[3]_INST_0_i_5_n_0 ), - .O(alu_op[3])); - LUT4 #( - .INIT(16'h0080)) - \alu_op[3]_INST_0_i_1 - (.I0(funct3[2]), - .I1(funct7_5), - .I2(funct3[0]), - .I3(funct3[1]), - .O(\alu_op[3]_INST_0_i_1_n_0 )); - (* SOFT_HLUTNM = "soft_lutpair1" *) - LUT3 #( - .INIT(8'h06)) - \alu_op[3]_INST_0_i_2 - (.I0(op_code[4]), - .I1(op_code[5]), - .I2(op_code[2]), - .O(\alu_op[3]_INST_0_i_2_n_0 )); - (* SOFT_HLUTNM = "soft_lutpair0" *) - LUT5 #( - .INIT(32'hF7FFFFF7)) - \alu_op[3]_INST_0_i_3 - (.I0(op_code[0]), - .I1(op_code[1]), - .I2(op_code[3]), - .I3(op_code[5]), - .I4(op_code[6]), - .O(\alu_op[3]_INST_0_i_3_n_0 )); - LUT4 #( - .INIT(16'hCFBB)) - \alu_op[3]_INST_0_i_4 - (.I0(op_code[3]), - .I1(op_code[4]), - .I2(op_code[2]), - .I3(op_code[6]), - .O(\alu_op[3]_INST_0_i_4_n_0 )); - (* SOFT_HLUTNM = "soft_lutpair1" *) - LUT4 #( - .INIT(16'h7F77)) - \alu_op[3]_INST_0_i_5 - (.I0(op_code[1]), - .I1(op_code[0]), - .I2(op_code[5]), - .I3(op_code[2]), - .O(\alu_op[3]_INST_0_i_5_n_0 )); - LUT6 #( - .INIT(64'h0000000000000007)) - alu_src_b_INST_0 - (.I0(op_code[5]), - .I1(op_code[4]), - .I2(op_code[3]), - .I3(op_code[2]), - .I4(op_code[6]), - .I5(\pc_src[1]_INST_0_i_1_n_0 ), - .O(alu_src_b)); - LUT1 #( - .INIT(2'h1)) - b_type_INST_0 - (.I0(funct3[0]), - .O(b_type)); - LUT6 #( - .INIT(64'h0000000000000040)) - branch_INST_0 - (.I0(\pc_src[1]_INST_0_i_1_n_0 ), - .I1(op_code[6]), - .I2(op_code[5]), - .I3(op_code[4]), - .I4(op_code[3]), - .I5(op_code[2]), - .O(branch)); - LUT6 #( - .INIT(64'h0000000010000001)) - \mem_to_reg[0]_INST_0 - (.I0(op_code[3]), - .I1(op_code[6]), - .I2(op_code[4]), - .I3(op_code[2]), - .I4(op_code[5]), - .I5(\pc_src[1]_INST_0_i_1_n_0 ), - .O(mem_to_reg[0])); - LUT6 #( - .INIT(64'h0300000000000001)) - \mem_to_reg[1]_INST_0 - (.I0(op_code[3]), - .I1(op_code[4]), - .I2(\pc_src[1]_INST_0_i_1_n_0 ), - .I3(op_code[5]), - .I4(op_code[2]), - .I5(op_code[6]), - .O(mem_to_reg[1])); - LUT6 #( - .INIT(64'h0000000000000010)) - mem_write_INST_0 - (.I0(op_code[4]), - .I1(op_code[3]), - .I2(op_code[5]), - .I3(op_code[2]), - .I4(op_code[6]), - .I5(\pc_src[1]_INST_0_i_1_n_0 ), - .O(mem_write)); - LUT6 #( - .INIT(64'h0000000000000080)) - \pc_src[0]_INST_0 - (.I0(op_code[6]), - .I1(op_code[5]), - .I2(op_code[2]), - .I3(op_code[4]), - .I4(\pc_src[1]_INST_0_i_1_n_0 ), - .I5(op_code[3]), - .O(pc_src[0])); - LUT6 #( - .INIT(64'h0000000000800000)) - \pc_src[1]_INST_0 - (.I0(op_code[6]), - .I1(op_code[5]), - .I2(op_code[2]), - .I3(op_code[4]), - .I4(op_code[3]), - .I5(\pc_src[1]_INST_0_i_1_n_0 ), - .O(pc_src[1])); - (* SOFT_HLUTNM = "soft_lutpair0" *) - LUT2 #( - .INIT(4'h7)) - \pc_src[1]_INST_0_i_1 - (.I0(op_code[0]), - .I1(op_code[1]), - .O(\pc_src[1]_INST_0_i_1_n_0 )); - LUT6 #( - .INIT(64'h0101440000010001)) - reg_write_INST_0 - (.I0(\pc_src[1]_INST_0_i_1_n_0 ), - .I1(op_code[6]), - .I2(op_code[3]), - .I3(op_code[2]), - .I4(op_code[4]), - .I5(op_code[5]), - .O(reg_write)); -endmodule -`ifndef GLBL -`define GLBL -`timescale 1 ps / 1 ps - -module glbl (); - - parameter ROC_WIDTH = 100000; - parameter TOC_WIDTH = 0; - parameter GRES_WIDTH = 10000; - parameter GRES_START = 10000; - -//-------- STARTUP Globals -------------- - wire GSR; - wire GTS; - wire GWE; - wire PRLD; - wire GRESTORE; - tri1 p_up_tmp; - tri (weak1, strong0) PLL_LOCKG = p_up_tmp; - - wire PROGB_GLBL; - wire CCLKO_GLBL; - wire FCSBO_GLBL; - wire [3:0] DO_GLBL; - wire [3:0] DI_GLBL; - - reg GSR_int; - reg GTS_int; - reg PRLD_int; - reg GRESTORE_int; - -//-------- JTAG Globals -------------- - wire JTAG_TDO_GLBL; - wire JTAG_TCK_GLBL; - wire JTAG_TDI_GLBL; - wire JTAG_TMS_GLBL; - wire JTAG_TRST_GLBL; - - reg JTAG_CAPTURE_GLBL; - reg JTAG_RESET_GLBL; - reg JTAG_SHIFT_GLBL; - reg JTAG_UPDATE_GLBL; - reg JTAG_RUNTEST_GLBL; - - reg JTAG_SEL1_GLBL = 0; - reg JTAG_SEL2_GLBL = 0 ; - reg JTAG_SEL3_GLBL = 0; - reg JTAG_SEL4_GLBL = 0; - - reg JTAG_USER_TDO1_GLBL = 1'bz; - reg JTAG_USER_TDO2_GLBL = 1'bz; - reg JTAG_USER_TDO3_GLBL = 1'bz; - reg JTAG_USER_TDO4_GLBL = 1'bz; - - assign (strong1, weak0) GSR = GSR_int; - assign (strong1, weak0) GTS = GTS_int; - assign (weak1, weak0) PRLD = PRLD_int; - assign (strong1, weak0) GRESTORE = GRESTORE_int; - - initial begin - GSR_int = 1'b1; - PRLD_int = 1'b1; - #(ROC_WIDTH) - GSR_int = 1'b0; - PRLD_int = 1'b0; - end - - initial begin - GTS_int = 1'b1; - #(TOC_WIDTH) - GTS_int = 1'b0; - end - - initial begin - GRESTORE_int = 1'b0; - #(GRES_START); - GRESTORE_int = 1'b1; - #(GRES_WIDTH); - GRESTORE_int = 1'b0; - end - -endmodule -`endif diff --git a/src/Core.v b/src/Core.v index 175c975..6155e3c 100644 --- a/src/Core.v +++ b/src/Core.v @@ -1,37 +1,11 @@ `timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 2021/05/28 18:08:36 -// Design Name: -// Module Name: Core -// Project Name: -// Target Devices: -// Tool Versions: -// Description: -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - -module Core( +module Core ( input wire clk, input wire aresetn, input wire step, input wire debug_mode, - // input wire [4:0] debug_reg_addr, // register address - - output wire [31:0] address, - output wire [31:0] data_out, - input wire [31:0] data_in, - - input wire [31:0] chip_debug_in, + input wire [4:0] debug_reg_addr, // register address output wire [31:0] chip_debug_out0, output wire [31:0] chip_debug_out1, output wire [31:0] chip_debug_out2, @@ -40,8 +14,10 @@ module Core( wire rst, mem_write, mem_clk, cpu_clk; wire [31:0] inst, core_data_in, addr_out, core_data_out, pc_out; reg [31:0] clk_div; + wire [31:0] debug_reg; assign rst = ~aresetn; + SCPU cpu( .clk(cpu_clk), .rst(rst), @@ -50,34 +26,33 @@ module Core( .addr_out(addr_out), // data memory address .data_out(core_data_out), // data to data memory .pc_out(pc_out), // connect to instruction memory - .mem_write(mem_write) + .mem_write(mem_write), + .debug_reg_addr(debug_reg_addr), + .debug_reg(debug_reg) ); always @(posedge clk) begin if(rst) clk_div <= 0; else clk_div <= clk_div + 1; end - assign mem_clk = ~clk_div[0]; // 50mhz + assign mem_clk = ~clk_div[0]; assign cpu_clk = debug_mode ? clk_div[0] : step; - // TODO: 连接Instruction Memory - Rom rom_unit ( - .a(), // 地址输入 - .spo() // 读数据输出 + ROM rom_unit ( + .address(pc_out / 4), + .out(inst) ); - // TODO: 连接Data Memory - Ram ram_unit ( - .clka(), // 时钟 - .wea(), // 是否写数据 - .addra(), // 地址输入 - .dina(), // 写数据输入 - .douta() // 读数据输出 + RAM ram_unit ( + .clk(mem_clk), + .we(mem_write), + .address(addr_out / 4), + .write_data(core_data_out), + .read_data(core_data_in) ); - // TODO: 添加32个寄存器组的输出 assign chip_debug_out0 = pc_out; assign chip_debug_out1 = addr_out; assign chip_debug_out2 = inst; - assign chip_debug_out3 = 32'hffffaaaa; + assign chip_debug_out3 = debug_reg; endmodule diff --git a/src/CoreSim.v b/src/CoreSim.v new file mode 100644 index 0000000..2dc2258 --- /dev/null +++ b/src/CoreSim.v @@ -0,0 +1,24 @@ +`timescale 1ns / 1ps + +module CoreSim; + reg clk, rst; + Core core( + .clk(clk), + .aresetn(~rst), + .step(1'b0), + .debug_mode(1'b1), + .debug_reg_addr(5'b0) + ); + + initial begin + $dumpvars(0, CoreSim); + #220 $finish; + end + + initial begin + clk = 0; + rst = 1; + #2 rst = 0; + end + always #1 clk = ~clk; +endmodule \ No newline at end of file diff --git a/src/Core_tb.sv b/src/Core_tb.sv deleted file mode 100644 index cdc579f..0000000 --- a/src/Core_tb.sv +++ /dev/null @@ -1,77 +0,0 @@ -`timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 2021/05/28 20:34:18 -// Design Name: -// Module Name: Core_tb -// Project Name: -// Target Devices: -// Tool Versions: -// Description: -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - - -module Core_tb - #(parameter T = 40)(); - // input - logic clk; - logic aresetn; - logic step; - logic debug_mode; - // logic [4:0] debug_reg_addr; // register address - logic [31:0] data_in; - logic [31:0] chip_debug_in; - // output - logic [31:0] address; - logic [31:0] data_out; - logic [31:0] chip_debug_out0; - logic [31:0] chip_debug_out1; - logic [31:0] chip_debug_out2; - logic [31:0] chip_debug_out3; - - // local - logic [31:0]pc_out, addr_out, inst; - - Core uut( - .clk(clk), - .aresetn(aresetn), - .step(step), - .debug_mode(debug_mode), - // .debug_reg_addr(debug_reg_addr), // register address - .address(address), - .data_out(data_out), - .data_in(data_in), - .chip_debug_in(chip_debug_in), - .chip_debug_out0(chip_debug_out0), - .chip_debug_out1(chip_debug_out1), - .chip_debug_out2(chip_debug_out2), - .chip_debug_out3(chip_debug_out3) - ); - - assign pc_out = chip_debug_out0; - assign addr_out = chip_debug_out1; - assign inst = chip_debug_out2; - - integer i; - initial begin - aresetn = 0; - clk = 1; - step = 0; - debug_mode = 1; - #100; - - fork - forever #(T/2) clk <= ~clk; - #(2*T) aresetn = 1; - join - end -endmodule diff --git a/src/IO_Manager.sv b/src/IO_Manager.sv index f6e232d..33adbf5 100644 --- a/src/IO_Manager.sv +++ b/src/IO_Manager.sv @@ -1,24 +1,4 @@ `timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 2021/05/28 18:16:05 -// Design Name: -// Module Name: IO_Manager -// Project Name: -// Target Devices: -// Tool Versions: -// Description: -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - module IO_Manager( input logic clk, @@ -30,7 +10,6 @@ module IO_Manager( output logic [31:0] data_in, output logic aresetn, output logic step, - output logic [31:0] chip_debug_in, // to gpio input logic [15:0] switch, @@ -79,9 +58,6 @@ module IO_Manager( end end - // chip_debug_in - assign chip_debug_in = {21'b0,switch[10:0]}; - // Reset logic reset_dbnc; diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..a5f22d9 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,18 @@ +GTKWAVE = /Users/crane/gtk/inst/bin/gtkwave + +.PHONY: all compile simulate clean + +all: compile simulate + +compile: + iverilog -o core.vvp -y . \ + -y components -y memory -y utils \ + -I headers \ + CoreSim.v + +simulate: + vvp -n core.vvp + $(GTKWAVE) dump.vcd wave.gtkw + +clean: + rm -f core.vvp dump.vcd \ No newline at end of file diff --git a/src/SCPU.v b/src/SCPU.v index 130d712..b0c1841 100644 --- a/src/SCPU.v +++ b/src/SCPU.v @@ -1,38 +1,20 @@ `timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 2021/05/28 15:11:21 -// Design Name: -// Module Name: SCPU -// Project Name: -// Target Devices: -// Tool Versions: -// Description: -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - module SCPU( - input clk, - input rst, - input [31:0] inst, - input [31:0] data_in, // data from data memory - output [31:0] addr_out, // data memory address - output [31:0] data_out, // data to data memory - output [31:0] pc_out, // connect to instruction memory - output mem_write - ); - wire [3:0] alu_op; - wire [1:0] pc_src, mem_to_reg; - wire reg_write, alu_src, branch, b_type; + input clk, + input rst, + input [31:0] inst, + input [31:0] data_in, // data from data memory + input [4:0] debug_reg_addr, + output [31:0] addr_out, // data memory address + output [31:0] data_out, // data to data memory + output [31:0] pc_out, // connect to instruction memory + output mem_write, + output [31:0] debug_reg +); + wire [3:0] alu_op; + wire [1:0] pc_src, mem_to_reg; + wire reg_write, alu_src, branch, b_type, auipc; Control control ( .op_code(inst[6:0]), @@ -45,7 +27,8 @@ module SCPU( .mem_to_reg(mem_to_reg), // 2'b00 表示写回rd的数据来自ALU, 2'b01表示数据来自imm, 2'b10表示数据来自pc+4, 2'b11 表示数据来自data memory .mem_write(mem_write), // 1'b1 表示写data memory, 1'b0表示读data memory .branch(branch), // 1'b1 表示是branch类型的指令 - .b_type(b_type) // 1'b1 表示beq, 1'b0 表示bne + .b_type(b_type), // 1'b1 表示beq, 1'b0 表示bne + .auipc(auipc) ); Datapath datapath ( @@ -56,13 +39,16 @@ module SCPU( .alu_src_b(alu_src_b), .branch(branch), .b_type(b_type), + .auipc(auipc), .alu_op(alu_op), .mem_to_reg(mem_to_reg), .inst_in(inst), .data_in(data_in), .addr_out(addr_out), .data_out(data_out), - .pc_out(pc_out) + .pc_out(pc_out), + .debug_reg_addr(debug_reg_addr), + .debug_reg(debug_reg) ); endmodule diff --git a/src/Top.sv b/src/Top.sv index 95cb1a3..ba1db0c 100644 --- a/src/Top.sv +++ b/src/Top.sv @@ -1,24 +1,4 @@ `timescale 1ns / 1ps -////////////////////////////////////////////////////////////////////////////////// -// Company: -// Engineer: -// -// Create Date: 2021/05/28 18:16:36 -// Design Name: -// Module Name: Top -// Project Name: -// Target Devices: -// Tool Versions: -// Description: -// -// Dependencies: -// -// Revision: -// Revision 0.01 - File Created -// Additional Comments: -// -////////////////////////////////////////////////////////////////////////////////// - module Top( input clk, @@ -35,11 +15,6 @@ module Top( logic aresetn; logic step; - logic [31:0] address; - logic [31:0] data_out; - logic [31:0] data_in; - - logic [31:0] chip_debug_in; logic [31:0] chip_debug_out0; logic [31:0] chip_debug_out1; logic [31:0] chip_debug_out2; @@ -50,11 +25,7 @@ module Top( .aresetn(aresetn), .step(step), .debug_mode(switch[15]), - // .debug_reg_addr(switch[11:7]), - .address(address), - .data_out(data_out), - .data_in(data_in), - .chip_debug_in(chip_debug_in), + .debug_reg_addr(switch[11:7]), .chip_debug_out0(chip_debug_out0), .chip_debug_out1(chip_debug_out1), .chip_debug_out2(chip_debug_out2), @@ -68,10 +39,6 @@ module Top( // to chip .aresetn(aresetn), .step(step), - .address(address), - .data_out(data_out), - .data_in(data_in), - .chip_debug_in(chip_debug_in), // to gpio .switch(switch), diff --git a/src/components/ALU.v b/src/components/ALU.v new file mode 100644 index 0000000..07bb0a6 --- /dev/null +++ b/src/components/ALU.v @@ -0,0 +1,37 @@ +`timescale 1ns / 1ps + +module ALU ( + input [31:0] a, + input [31:0] b, + input [3:0] alu_op, + output reg [31:0] res, + output zero +); + `include "AluOp.vh" + always @(*) begin + case (alu_op) + ADD: res <= a + b; + SUB: res <= a - b; + SLL: res <= a << b[4:0]; + SLT: begin + if (a[31] == 0 && b[31] == 1) res <= 0; + else if (a[31] == 1 && b[31] == 0) res <= 1; + else if (a[31] == b[31]) begin + if (a[30:0] < b[30:0]) res <= 1; + else res <= 0; + end + end + SLTU: begin + if (a < b) res <= 1; + else res <= 0; + end + XOR: res <= a ^ b; + SRL: res <= a >> b[4:0]; + SRA: res <= a >>> b[4:0]; + OR: res <= a | b; + AND: res <= a & b; + default: res = 0; + endcase + end + assign zero = (a-b) ? 1'b0 : 1'b1; +endmodule \ No newline at end of file diff --git a/src/components/Control.v b/src/components/Control.v new file mode 100644 index 0000000..cc06f5b --- /dev/null +++ b/src/components/Control.v @@ -0,0 +1,75 @@ +`timescale 1ns / 1ps + +module Control ( + input [6:0] op_code, + input [2:0] funct3, + input funct7_5, + output reg [1:0] pc_src, // 00 pc+4 01 JALR 10 JAL + output reg reg_write, // write register or not + output reg alu_src_b, // 0 -> from register, 1 -> from imm + output reg [3:0] alu_op, // ALUop + output reg [1:0] mem_to_reg, // 00 -> ALU, 01 -> imm, 10 -> pc+4, 11 -> RAM + output reg mem_write, // write RAM or not + output reg branch, // is branch or not + output reg b_type, // 1 -> beq, 0 -> bne + output reg auipc // is auipc or not +); + `include "AluOp.vh" + always @(*) begin + pc_src = 0; + reg_write = 0; + alu_src_b = 0; + alu_op = {funct7_5, funct3}; + mem_to_reg = 0; + mem_write = 0; + branch = 0; + b_type = 0; + auipc = 0; + + case (op_code) + 7'b0000011: begin // lw + reg_write = 1; alu_src_b = 1; alu_op = ADD; + mem_to_reg = 2'b11; + end + 7'b0100011: begin // sw + alu_src_b = 1; alu_op = ADD; mem_write = 1; + end + 7'b0010011: begin // addi slti xori ori andi slli srli + reg_write = 1; alu_src_b = 1; + case (funct3) + 3'b000: alu_op = ADD; + 3'b010: alu_op = SLT; + 3'b100: alu_op = XOR; + 3'b110: alu_op = OR; + 3'b111: alu_op = AND; + 3'b001: alu_op = SLL; + 3'b101: begin + if (funct7_5) alu_op = SRA; + else alu_op = SRL; + end + endcase + end + 7'b1100011: begin // bne beq + alu_op = XOR; branch = 1; b_type = ~funct3[0]; + end + 7'b1101111: begin // jal + pc_src = 2'b10; reg_write = 1; mem_to_reg = 2'b10; + end + 7'b0110111: begin // lui + reg_write = 1; mem_to_reg = 2'b01; + end + 7'b0110011: begin // add slt and or sll srl sltu + reg_write = 1; + end + 7'b0010111: begin // auipc + reg_write = 1; alu_src_b = 1; alu_op = ADD; + auipc = 1; + end + 7'b1100111: begin // jalr + pc_src = 2'b01; reg_write = 1; mem_to_reg = 2'b10; + alu_src_b = 1; alu_op = ADD; + end + endcase + end + +endmodule \ No newline at end of file diff --git a/src/components/Datapath.v b/src/components/Datapath.v new file mode 100644 index 0000000..117811b --- /dev/null +++ b/src/components/Datapath.v @@ -0,0 +1,107 @@ +`timescale 1ns / 1ps + +module Datapath( + input clk, + input rst, + input [1:0] pc_src, // 00 -> from pc+4, 01 -> from JALR, 10 -> from JAL + input reg_write, // write register or not + input alu_src_b, // ALUsrc + input branch, // whether branch or not + input b_type, // 0 -> bne, 1 -> beq + input auipc, // whether auipc or not + input [3:0] alu_op, // ALU operation + input [1:0] mem_to_reg, // 00 -> from ALU, 01 -> from imm, 10 -> from pc+4, 11 -> from RAM + input [31:0] inst_in, // now instruction + input [31:0] data_in, // data from data memory + output [31:0] addr_out, // data memory address + output [31:0] data_out, // data to data memory + output [31:0] pc_out, // connect to instruction memory + input [4:0] debug_reg_addr, + output [31:0] debug_reg +); + reg [31:0] pc; + wire [31:0] pc_next; + wire [31:0] write_data, read_data_1, read_data_2; + wire [31:0] alu_data_1, alu_data_2, alu_result; + wire alu_zero; + wire [31:0] imm; + wire [31:0] jal_addr, jalr_addr; + + assign pc_out = pc; + assign addr_out = alu_result; + assign data_out = read_data_2; + + always @(posedge clk or posedge rst) begin + if (rst) begin + pc <= 32'b0; + end + else begin + pc <= pc_next; + end + end + + Regs regs ( + .clk(clk), + .rst(rst), + .we(reg_write), + .read_addr_1(inst_in[19:15]), + .read_addr_2(inst_in[24:20]), + .write_addr(inst_in[11:7]), + .write_data(write_data), + .read_data_1(read_data_1), + .read_data_2(read_data_2), + .debug_reg_addr(debug_reg_addr), + .debug_reg(debug_reg) + ); + + ImmGen immgen ( + .inst(inst_in), + .imm(imm) + ); + + Mux2x32 mux2x32_1 ( + .I0(read_data_1), + .I1(pc), + .s(auipc), + .o(alu_data_1) + ); + + Mux2x32 mux2x32_2 ( + .I0(read_data_2), + .I1(imm), + .s(alu_src_b), + .o(alu_data_2) + ); + + ALU alu ( + .a(alu_data_1), + .b(alu_data_2), + .alu_op(alu_op), + .res(alu_result), + .zero(alu_zero) + ); + + Mux4x32 mux4x32 ( + .I0(alu_result), + .I1(imm), + .I2(pc + 4), + .I3(data_in), + .s(mem_to_reg), + .o(write_data) + ); + + assign jal_addr = pc + imm; + assign jalr_addr = alu_result; + + MuxPC mux_pc ( + .I0(pc + 4), + .I1(jalr_addr), + .I2(jal_addr), + .I3(jal_addr), + .s(pc_src), + .branch(branch), + .b_type(b_type), + .alu_res(alu_result), + .o(pc_next) + ); +endmodule \ No newline at end of file diff --git a/src/components/ImmGen.v b/src/components/ImmGen.v new file mode 100644 index 0000000..1d4c833 --- /dev/null +++ b/src/components/ImmGen.v @@ -0,0 +1,47 @@ +`timescale 1ns / 1ps + +module ImmGen( + input [31:0] inst, + output [31:0] imm +); + `include "Opcodes.vh" + reg [3:0] type; + reg [31:0] out; + assign imm = out; + + always @(*) begin + case (inst[6:0]) + LW: type <= I; + SW: type <= S; + ADDI: type <= I; + BNE: type <= B; + BEQ: type <= B; + JAL: type <= J; + LUI: type <= U; + ADD: type <= R; + SLT: type <= R; + SLTI: type <= I; + ANDI: type <= I; + ORI: type <= I; + AND: type <= R; + OR: type <= R; + SLL: type <= R; + XORI: type <= I; + SLLI: type <= R; + SRLI: type <= R; + SRL: type <= R; + AUIPC: type <= U; + SLTU: type <= R; + JALR: type <= I; + endcase + case (type) + R: out <= {{20{inst[31]}}, inst[31:20]}; + I: out <= {{20{inst[31]}}, inst[31:20]}; + S: out <= {{20{inst[31]}}, inst[31:25], inst[11:7]}; + B: out <= {{19{inst[31]}}, inst[31], inst[7], inst[30:25], inst[11:8], 1'b0}; + U: out <= {inst[31:12], 12'b0}; + J: out <= {{11{inst[31]}}, inst[31], inst[19:12], inst[20], inst[30:21], 1'b0}; + endcase + end + +endmodule \ No newline at end of file diff --git a/src/components/Regs.v b/src/components/Regs.v new file mode 100644 index 0000000..0c0aa73 --- /dev/null +++ b/src/components/Regs.v @@ -0,0 +1,32 @@ +`timescale 1ns / 1ps + +module Regs ( + input clk, + input rst, + input we, + input [4:0] read_addr_1, + input [4:0] read_addr_2, + input [4:0] write_addr, + input [31:0] write_data, + input [4:0] debug_reg_addr, + output [31:0] read_data_1, + output [31:0] read_data_2, + output [31:0] debug_reg +); + integer i; + reg [31:0] register [1:31]; // x1 - x31, x0 keeps zero + + genvar idx; + for (idx = 1; idx < 32; idx = idx + 1) begin + initial $dumpvars(0, register[idx]); + end + + assign read_data_1 = (read_addr_1 == 0) ? 0 : register[read_addr_1]; // read + assign read_data_2 = (read_addr_2 == 0) ? 0 : register[read_addr_2]; // read + assign debug_reg = (debug_reg_addr == 0) ? 0 : register[debug_reg_addr]; + + always @(posedge clk or posedge rst) begin + if (rst == 1) for (i = 1; i < 32; i = i + 1) register[i] <= 0; // reset + else if (we == 1 && write_addr != 0) register[write_addr] <= write_data; + end +endmodule \ No newline at end of file diff --git a/src/AluOp.vh b/src/headers/AluOp.vh similarity index 100% rename from src/AluOp.vh rename to src/headers/AluOp.vh diff --git a/src/headers/Opcodes.vh b/src/headers/Opcodes.vh new file mode 100644 index 0000000..f454bb0 --- /dev/null +++ b/src/headers/Opcodes.vh @@ -0,0 +1,32 @@ +//`ifndef OPCODES_H +//`define OPCODES_H +parameter LW = 7'b0000011, + SW = 7'b0100011, + ADDI = 7'b0010011, + BNE = 7'b1100011, + BEQ = 7'b1100011, + JAL = 7'b1101111, + LUI = 7'b0110111, + ADD = 7'b0110011, + SLT = 7'b0110011, + SLTI = 7'b0010011, + ANDI = 7'b0010011, + ORI = 7'b0010011, + AND = 7'b0110011, + OR = 7'b0110011, + SLL = 7'b0110011, + XORI = 7'b0010011, + SLLI = 7'b0010011, + SRLI = 7'b0010011, + SRL = 7'b0110011, + AUIPC = 7'b0010111, + SLTU = 7'b0110011, + JALR = 7'b1100111; + +parameter R = 3'b000, + I = 3'b001, + S = 3'b010, + B = 3'b011, + U = 3'b100, + J = 3'b101; +//`endif \ No newline at end of file diff --git a/src/lab10.coe b/src/lab10.coe deleted file mode 100644 index 4eb7585..0000000 --- a/src/lab10.coe +++ /dev/null @@ -1,3 +0,0 @@ -memory_initialization_radix = 16; -memory_initialization_vector = -07b00093, 06f08113, 06f10193, 06f18213, 06f20293, 00000313, 00400393, 09400413, 09800493, 40400513, 00000a13, 00132023, 0023a023, 00032583, 00342023, 0044a023, 00042683, 0003a603, 0004a703, ea758593, e3860613, 00c59463, 001a0a13, 00552023, 0003a583, 00052603, 14d58593, 00c59463, 001a0a13, 00032583, 00052603, 1bc58593, 00c59463, 001a0a13, 00300a93, ff4a9ee3; diff --git a/src/lab10_all.coe b/src/lab10_all.coe deleted file mode 100644 index 4eb4582..0000000 --- a/src/lab10_all.coe +++ /dev/null @@ -1,3 +0,0 @@ -memory_initialization_radix = 16; -memory_initialization_vector = -07b00093, 06f08113, 06f10193, 06f18213, 06f20293, 00000313, 00400393, 09400413, 09800493, 40400513, 00000a13, 00132023, 0023a023, 00032583, 00342023, 0044a023, 00042683, 0003a603, 0004a703, ea758593, e3860613, 00c59463, 001a0a13, 00552023, 0003a583, 00052603, 14d58593, 00c59463, 001a0a13, 00032583, 00052603, 1bc58593, 04c59863, 001a0a13, 00fff7b7, 00ffe837, 001a0a13, 008008ef, fffa0a13, 00001937, 01280833, 001a0a13, 00f80463, fffa0a13, fffff937, fff92793, 7ffff8b7, 0128a833, 00081863, 001a0a13, 01078463, 001a0a13, 00700a93, ff4a9ee3; diff --git a/src/memory/RAM.v b/src/memory/RAM.v new file mode 100644 index 0000000..555b9d6 --- /dev/null +++ b/src/memory/RAM.v @@ -0,0 +1,26 @@ +`timescale 1ns / 1ps + +module RAM ( + input clk, + input we, + input [31:0] write_data, + input [10:0] address, + output [31:0] read_data +); + reg [31:0] ram [0:2047]; + + genvar idx; + for (idx = 0; idx < 512; idx = idx + 1) begin + initial $dumpvars(0, ram[idx]); + end + + initial begin + for (integer i = 0; i < 2048; i = i + 1) ram[i] <= 0; + end + + always @(posedge clk) begin + if (we == 1) ram[address] <= write_data; + end + + assign read_data = ram[address]; +endmodule \ No newline at end of file diff --git a/src/memory/ROM.v b/src/memory/ROM.v new file mode 100644 index 0000000..1d6efbe --- /dev/null +++ b/src/memory/ROM.v @@ -0,0 +1,14 @@ +`timescale 1ns / 1ps + +module ROM ( + input [10:0] address, + output [31:0] out +); + reg [31:0] rom [0:2047]; + + initial begin + $readmemh("tests/full.hex", rom); + end + + assign out = rom[address]; +endmodule diff --git a/src/tests/bonus.asm b/src/tests/bonus.asm new file mode 100644 index 0000000..517cb6e --- /dev/null +++ b/src/tests/bonus.asm @@ -0,0 +1,21 @@ +.section .text +.globl _start +_start: + addi x1, x0, 123 # x1 = 123 + andi x2, x1, 456 # x2 = 72 + ori x3, x2, 789 # x3 = 861 + and x4, x3, x1 # x4 = 89 + addi x5, x0, 234 # x5 = 234 + or x5, x4, x5 # x5 = 251 (0xfb) + sll x6, x5, x2 # x6 = 64256 (0xFB00) + xori x7, x6, 123 # x7 = 64379 (0xFB7B) + slli x8, x7, 4 # x8 = 1030064 (0xFB7B0) + srli x9, x8, 8 # x9 = 4023 (0xFB7) + srl x10, x8, x2 # x10 = 4023 (0xFB7) + auipc x11, 0xFFF # x11 = 0xFFF02C + addi x12, x0, -1 # x12 = -1 + sltu x12, x11, x12 # x12 = 1 + jalr x13, 63(x12) # x13 = 60 + addi x14, x0, 1 # won't exec +Label: + addi x15, x0, 1 \ No newline at end of file diff --git a/src/tests/bonus.hex b/src/tests/bonus.hex new file mode 100644 index 0000000..f5153fe --- /dev/null +++ b/src/tests/bonus.hex @@ -0,0 +1,17 @@ +07b00093 +1c80f113 +31516193 +0011f233 +0ea00293 +005262b3 +00229333 +07b34393 +00439413 +00845493 +00245533 +00fff597 +fff00613 +00c5b633 +03f606e7 +00100713 +00100793 \ No newline at end of file diff --git a/src/lab10_all.asm b/src/tests/full.asm similarity index 100% rename from src/lab10_all.asm rename to src/tests/full.asm diff --git a/src/tests/full.hex b/src/tests/full.hex new file mode 100644 index 0000000..e4a81cb --- /dev/null +++ b/src/tests/full.hex @@ -0,0 +1,54 @@ +07b00093 +06f08113 +06f10193 +06f18213 +06f20293 +00000313 +00400393 +09400413 +09800493 +40400513 +00000a13 +00132023 +0023a023 +00032583 +00342023 +0044a023 +00042683 +0003a603 +0004a703 +ea758593 +e3860613 +00c59463 +001a0a13 +00552023 +0003a583 +00052603 +14d58593 +00c59463 +001a0a13 +00032583 +00052603 +1bc58593 +04c59863 +001a0a13 +00fff7b7 +00ffe837 +001a0a13 +008008ef +fffa0a13 +00001937 +01280833 +001a0a13 +00f80463 +fffa0a13 +fffff937 +fff92793 +7ffff8b7 +0128a833 +00081863 +001a0a13 +01078463 +001a0a13 +00700a93 +ff4a9ee3 \ No newline at end of file diff --git a/src/lab10.asm b/src/tests/simple.asm similarity index 100% rename from src/lab10.asm rename to src/tests/simple.asm diff --git a/src/tests/simple.hex b/src/tests/simple.hex new file mode 100644 index 0000000..8f007b4 --- /dev/null +++ b/src/tests/simple.hex @@ -0,0 +1,36 @@ +07b00093 +06f08113 +06f10193 +06f18213 +06f20293 +00000313 +00400393 +09400413 +09800493 +40400513 +00000a13 +00132023 +0023a023 +00032583 +00342023 +0044a023 +00042683 +0003a603 +0004a703 +ea758593 +e3860613 +00c59463 +001a0a13 +00552023 +0003a583 +00052603 +14d58593 +00c59463 +001a0a13 +00032583 +00052603 +1bc58593 +00c59463 +001a0a13 +00300a93 +ff4a9ee3 \ No newline at end of file diff --git a/src/utils/Mux2x32.v b/src/utils/Mux2x32.v new file mode 100644 index 0000000..79c4c37 --- /dev/null +++ b/src/utils/Mux2x32.v @@ -0,0 +1,10 @@ +`timescale 1ns / 1ps + +module Mux2x32( + input [31:0] I0, + input [31:0] I1, + input s, + output [31:0] o +); + assign o = s ? I1 : I0; +endmodule \ No newline at end of file diff --git a/src/utils/Mux4x32.v b/src/utils/Mux4x32.v new file mode 100644 index 0000000..9a7ffa8 --- /dev/null +++ b/src/utils/Mux4x32.v @@ -0,0 +1,21 @@ +`timescale 1ns / 1ps + +module Mux4x32( + input [31:0] I0, + input [31:0] I1, + input [31:0] I2, + input [31:0] I3, + input [1:0] s, + output [31:0] o +); + reg [31:0] out; + always @(*) begin + case (s) + 2'b00: out <= I0; + 2'b01: out <= I1; + 2'b10: out <= I2; + 2'b11: out <= I3; + endcase + end + assign o = out; +endmodule \ No newline at end of file diff --git a/src/utils/MuxPC.v b/src/utils/MuxPC.v new file mode 100644 index 0000000..40e028d --- /dev/null +++ b/src/utils/MuxPC.v @@ -0,0 +1,36 @@ +`timescale 1ns / 1ps + +module MuxPC( + input [31:0] I0, + input [31:0] I1, + input [31:0] I2, + input [31:0] I3, + input [1:0] s, + input branch, + input b_type, // 0 bne, 1 beq + input [31:0] alu_res, + output [31:0] o +); + reg [31:0] out; + always @(*) begin + if (branch) begin + if (b_type) begin + if (alu_res == 32'b0) out <= I3; + else out <= I0; + end + else begin + if (alu_res == 32'b0) out <= I0; + else out <= I3; + end + end + else begin + case (s) + 2'b00: out <= I0; + 2'b01: out <= I1; + 2'b10: out <= I2; + 2'b11: out <= I3; + endcase + end + end + assign o = out; +endmodule \ No newline at end of file