This repository contains information and code that was formed during the RISC-V MYTH Workshop. A RISC-V pipelined core that supports RV32I base integer instructions was developed on Makerchip and written in TL-Verilog.
RISC-V is an open standard instruction set architecture (ISA), meaning it is provided under open source licenses and available to the public. It is comprised of a base integer ISA (RV32I/RV64I) with optional extension ISAs and belongs to the little endian memory addressing system.
The GNU compiler toolchain is a collection of programming tools used for developing applications and operating systems; it has tools that make and compile code into machine-readable programs. The flow from user to machine code is as follows:
- Preprocessor: process user code to be read by compiler such as macro expansion and file inclusion.
- Compiler: compile source code to assembly instructions
- Assembler: convert assembly to relocatable machine code
- Linker: converts assembler output to absolute machine code
Compile command:
$ riscv64-unkown-elf-gcc -O<1/fast> -mabi=lp<XLEN> -march=rv<XLEN>i -o <output_program> <input_user_file> [<input_user_file>...]
Assembly preview command:
$ riscv64-unkown-elf-objdump -d <output_program>
Run command:
$ spike pk <output_program>
Debug command:
$ spike -d pk <output_program>
The Application Binary Interface (ABI), also known as the System Call Interface, is used by the program to access the ISA registers. RISC-V architecture contains 32 registers of width 32/64 if using RV32I/RV64I, respectively:
Register | ABI Name | Usage |
---|---|---|
x0 | zero | Hard-wired zero |
x1 | ra | Return address |
x2 | sp | Stack pointer |
x3 | gp | Global pointer |
x4 | tp | Thread opinter |
x5-7 | t0-2 | Temporaries |
x8 | s0/fp | Saved register/frame pointer |
x9 | s1 | Saved register |
x10-11 | a0-1 | Function arguments/return values |
x12-17 | a2-7 | Function arguments |
x18-27 | s2-11 | Saved registers |
x28-31 | t3-6 | Temporaries |
There are 3 types of instructions:
- R-type: operate only on registers
Ex:add x8, x24, x8
- I-type: operate on registers and immediate values
Ex:ld x8, 16(x23)
- S-type: operate on source registers and store in immediate value
Ex:sd x8, 8(x23)
A simple program for summing numbers 1 to 9 was created; view source in Day2 folder. The compiled output in assembly looks like this:
Transaction-Level Verilog (TL-Verilog) is a hardware descriptive language (HDL) that extends Verilog in the context of pipelines; specifically, it maintains behavior of the circuit while being timing abstract, which means it takes care of retiming.
Makerchip is a free online platform made by Redwood EDA. It supports TL-Verilog, SystemVerilog, and Verilog languages to code, compile, simulate, and debug digital designs.
A simple calculator with single value memory and validity was created; view source here. The diagram and viz showing one cycle of operation:
The building blocks of a simple CPU are program counter (PC), instruction memory (IMem Rd), instruction decoder (Dec), register file read (RF Rd), arithmetic logic unit (ALU), register file write (RF Wr), and data memory (DMem Rd/Wr). The following diagram depicts the connections between these blocks:
A simple RISC-V core from fetch and decode to control logic with branching was created; view source here. The diagram and viz showing final instruction executed:
Pipelining is used in designs to cut down the amount of combinational logic between flip-flops. This allows for higher clock speeds and, for a processor, more instructions per second (IPS). In order for this to function properly, the flow of logic must be broken up into pipe stages; the implemented RISC-V core's stages are seen in the below diagram:
This introduces hazards that were not seen before pipelining:
- Control flow hazard
- Hazard: branch and jump instructions update PC in stage @3 when it is needed in stage @1
- Solution: invalidate the next 2 instructions
- Read after write hazard
- Hazard: register file read occurs before register file write on previous instruction (stage @4 versus @2)
- Solution: for dependent instructions (write to register followed by read from same register), select previous instruction's ALU output data/register file write input data (write stage @3 is in parallel with read stage @2)
- Load instruction redirect
- Hazard: load data from memory is valid 2 cycles after register write (stage @5 versus @3)
- Solution: invalidate the next 2 instructions and select load data for register file write data when it is valid
A RISC-V core that implements the ISA was pipelined; view source here.
The pipe stages are the green boxes and contain signals for that stage.
The final summation result of 45 was stored in DMem (address 1) then loaded from DMem into r15/a5.
SandPiper generated ~40,000 characters of SystemVerilog from ~10,000 characters of TL-Verilog (excluding whitespace, comments, and instrumentation).
The current state of this RISC-V core implements almost all of RV32I base instruction set. Future improvements include completing the remaining instructions in RV32I and adding instruction set extensions such as RV32M, RV32F, and RV32D.
A compiled list of references used during this workshop:
- RISC-V International: https://riscv.org
- TL-Verilog: https://www.redwoodeda.com/tl-verilog and http://tl-x.org
- Makerchip: https://www.makerchip.com
- Redwood EDA: https://www.redwoodeda.com
- VLSI System Design: https://www.vlsisystemdesign.com
- Kunal Ghosh, Co-founder, VSD Corp. Pvt. Ltd.
- Steve Hoover, Founder, Redwood EDA
- Joseph Aronson, Design Engineer, Texas Instruments Inc.
- Email: [email protected]