Implementation of RISC-V Processor in System Verilog
.
- Unprivileged
- RV32I (jump, branch, load/store, arithmetic/logical operations, ecall, ebreak)
- RV32 Zicsr (CSR operations)
- RV32M (mul, div, rem)
- Privileged
- Trap-Return Instructions (mret)
ISA is published in RISC-V official page.
Unprivileged Instructions are based on "Volume 1, Unprivileged Spec v. 20191213."
Privileged Instructions are based on "Volume 2, Privileged Spec v. 20190608."
- 4-stage pipeline (
Fetch
,Decode
,Execute
,Write)
- Forwarding (
E → D
,W → D
) - Branch prediction (
Two-level adaptive predictor
) - Register (32 entries, 32 bit)
- Memory (1024 entries, 32 bit)
- Use just registers for ease of implementation
- CSR (Control and Status Register)
- Exception/Interrupt handling (only
User
andMachine
mode withoutSupervisor
mode)- Exception
- 2: Illegal instruction exception
- 3: Breakpoint exception
- 8: System call exception (from User mode)
- 11: System call exception (from Machine mode)
- Interrupt
- 7: Machine timer interrupt
- 11: Machine external interrupt
- Exception
Register | ABI Name | Description |
---|---|---|
r0 | zero | hardwired zero |
r1 | ra | return address |
r2 | sp | stack pointer |
r8 | s0 / fp | saved register / frame pointer |
r9 | s1 | saved register |
r10-11 | a0-1 | function arguments / return values |
r12-17 | a2-7 | function arguments |
-
fib-csr
- fib function with all exceptions, all interrupts, and CSR operations
r15 = fib(10)
clocks : 18613 pc : 43 instructions : total 14587, normal 3809, exception 709, others 10069 prediction : total 1344, succeed 1130, fail 214 register : r00: 0, r01: 43, r02: 2032, r03: 0, r04: 0, r05: 0, r06: 0, r07: 0, r08: 2048, r09: 0, r10: 89, r11: 0, r12: 0, r13: 0, r14: 0, r15: 89
-
fib-ebreak
- fib function with exceptions and interrupts
r15 = fib(10)
clocks : 9385 pc : 43 instructions : total 5267, normal 3809, exception 709, others 749 prediction : total 622, succeed 416, fail 206 register : r00: 0, r01: 43, r02: 2032, r03: 0, r04: 0, r05: 0, r06: 0, r07: 0, r08: 2048, r09: 0, r10: 89, r11: 0, r12: 0, r13: 0, r14: 0, r15: 89
-
fib
- fib function
r15 = fib(10)
- 4222 [clocks] = 3809 [instructions] + (206-1) * 2 [stalls] + (4-1) [stages]
206-1
is performed to ignore the prediction miss of the final instruction.
clocks : 4222 pc : 35 instructions : total 3809, normal 3809, exception 0, others 0 prediction : total 622, succeed 416, fail 206 register : r00: 0, r01: 35, r02: 2032, r03: 0, r04: 0, r05: 0, r06: 0, r07: 0, r08: 2048, r09: 0, r10: 89, r11: 0, r12: 0, r13: 0, r14: 0, r15: 89
-
memory
- memory operations
r15 = a[0](=1) + a[1](=2)
clocks : 16 pc : 12 instructions : total 13, normal 13, exception 0, others 0 prediction : total 2, succeed 1, fail 1 register : r00: 0, r01: 1, r02: 2016, r03: 0, r04: 0, r05: 0, r06: 0, r07: 0, r08: 2048, r09: 0, r10: 0, r11: 0, r12: 0, r13: 0, r14: 1, r15: 3
-
This repository
$ git clone https://github.com/hashi0203/riscv-processor.git
-
RISC-V Cross Compiler
If you just want to run the processor, you can skip this process.
If you want to run youroriginal test program
, you should follow this process.We use riscv-gnu-toolchain as a cross compiler.
Basically, you can follow the instructions on the GitHub page.$ git clone https://github.com/riscv/riscv-gnu-toolchain $ ./configure --prefix=/opt/riscv32 --with-arch=rv32ima --with-abi=ilp32d $ make linux
You can change
--prefix=/opt/riscv32
to the path you want to install this compiler.You also have to update
PATH
.export PATH=/opt/riscv32/bin:$PATH
If you just want to run the processor, you can skip 1 and 2.
If you want to run your original test program
, you should follow 1 to 3.
-
Make a test program for processor in test-programs.
- Make a test program in C (e.g., fib.c, memory.c).
- Compile the program by the following command (change "fib" to the file name (without extension) you have made).
$ cd /path/to/test-programs $ make ARG=fib
- Output files are explained later in Files in test-programs chapter.
-
Change the test program for the processor.
- Update instruction memory (
instr_mem
) in fetch.sv.- Make sure to change
63
in line 14 tothe number of lines - 1
.
- Make sure to change
- Update
MEM_SIZE
,final_pc
,privilege_jump_addr
,exception_enabled
, andinterrupt_enabled
in core.sv.- If you don't expect exception or interruption, you don't have to set
privilege_jump_addr
, and you have to setexception_enabled
, andinterrupt_enabled
to zero.
- If you don't expect exception or interruption, you don't have to set
- Set
max_clocks
,max_reg_show
,ext_intr
andtimer_intr
in test_core.sv.- If
max_clocks
is small, the program may not finish. - If you don't expect external or timer interruption, you don't have to set
ext_intr
andtimer_intr
.
- If
- Update instruction memory (
-
Run the processor.
- We use Vivado simulator commands (
xvlog
,xelab
, andxsim
). - You just have to run the following command.
- All the
.sv
files in src will be compiled.
- All the
$ cd /path/to/src $ make
- We use Vivado simulator commands (
-
Compile from Assembly
When you make test programs, you can also write or edit RISC-V assembly code.
For example, fib-ebreak.S and fib-csr.S are obtained by editing fib.S.
When editing assemblies, you have to make sure that the edited part should beabove
the following three lines..size main, .-main .ident "GCC: (GNU) 10.2.0" .section .note.GNU-stack,"",@progbits
After creating test programs in assembly, edit the Makefile by commenting out line 25 and 26.
# $(ARG).S: $(ARG).c # $(CC) $(CFLAGS) -S -o $(ARG).S $(ARG).c
Then, compile it by using
make
command.$ cd /path/to/test-programs $ make ARG=fib-ebreak
Files in test-programs
- start.S
- disable default initial routine
- no need to edit
- link.ld
- set start pc (program counter) to 0
- no need to edit
Explanation when using fib.c
- fib.c
- test program in C
- fib.S
- test program in assembly
- automatically generated by
make
command
- fib.bin
- binary file of test program
- automatically generated by
make
command
- fib.hex
- test program in hexadecimal
- automatically generated by
make
command
- fib.b
- test program in binary for Verilog
- used to test processor by editing fetch.sv
- automatically generated by
make
command
- fib.dump
- disassembled test program (almost same as fib.S)
- automatically generated by
make
command
.hex
and.dump
are used for debugging. - start.S
-
Simulation in Vivado
- Start Vivado
- Create Project
Create a New Vivado Project
→Next >
Project Name
→ Set anyProject Name
andProject location
→Next >
Project Type
→RTL Project
(Default) →Next >
Add Sources
→ Add all.sv
files in src (including test_core.sv) →Next >
Add Constraints (optional)
→Next >
Default Part
→Next >
New Project Summary
→Finish
- Run Simulation
Flow Navigator
>PROJECT MANAGER
>SIMULATION
>Run Simulation
>Run Behavioral Simulation
- Click
Yes
orSave
, if there are any pop-ups - Add
wire
orreg
you want to check- Choose modules (e.g.,
_core
) inScope
tab wire
andreg
in the module appear inObjects
tab- Choose
wire
orreg
inObjects
tab - Drag and drop it on
Name
in the wave orm area
- Choose modules (e.g.,
- Top bar >
Run All
▶ - Check the waveform
After updating source codes, you have to follow
Run Simulation
again.
- riscv-gnu-toolchain (Cross Compiler)
- to cross-compile the C programs to binary.
- RISC-Vを使用したアセンブリ言語入門 〜2. アセンブリ言語を見てみよう〜
- to see how to compile programs by using
riscv-gnu-toolchain
.
- to see how to compile programs by using
- RISC-Vクロスコンパイラで生成したバイナリを自作RISC-V上で実行する
- to see how to compile C programs to binary.
- to validate the compile result.
- RV32I, RV64I Instructions
- to see the detailed explanation of RISC-V ISA.
- RISC-Vについて(CPU実験その2)
- to see the detailed explanation of RISC-V ISA.
- RV32I インストラクション・セット
- to see the detailed explanation of RISC-V ISA.
- 分岐先アドレスを予測する
- to see how to implement branch prediction.
- cpuex2019-7th/core
- to see how to implement a processor.
- RISC-Vの特権命令まとめ
- to see how the CSR instructions work.
- RISC-VでLinuxを動かすためのレジスタ制御
- to see how the CSR instructions work.
- RISC-Vにおけるprivilege modeの遷移(xv6-riscvを例にして)
- to see how to handle exceptions and interrupts.
- RISC-Vとx86のsystem callの内部実装の違い(xv6を例に)
- to see the behavior of system call instructions.
- xv6-riscv (simple OS)
- to check exception/interrupt behavior.
- cpuex2019-yokyo/core
- to see how to implement privileged instructions.