FE310G: an open source RISC-V microcontroller – Introduction

What about using a high-performance open hardware microcontroller? In this series I talk about SiFive’s FE310G, the first commercial implementation of a RISC-V core. For those who don’t know, RISC-V (riscv.org) was designed as a high-performance open-source ISA (Instruction Set Architecture) focused on general purpose applications. It was designed and maintained by the University of California and includes 32, 64 and 128-bit instruction sets, along with several extensions such as compressed instructions (similar to ARM’s THUMB and MIPS’ MIPS16e), integer multiply and divide, vector operations, floating point (single, double or quad precision), atomic operations, SIMD (Single Instruction Multiple Data), embedded systems (a simplified version of the 32-bit core), etc. According to its designers, it can perform as fast as 1.61 DMIPs/MHz or 2.73 Coremark/MHz.

One of RISC-V’s interesting features is regarding its compressed instruction set, which can co-exist with standard instructions without any state or mode changing (as it is usually needed when changing from ARM to THUMB states and similarly on MIPS architecture). On the most recent ARM Cortex cores a new ISA (THUMB-2) improved THUMB performance by adding several 32-bit instructions, even though, Cortex cores which include ARM and THUMB2 instructions (such as Cortex-A) still require a state change when using ARM or THUMB2 instructions.

One important missing feature (until now) is the lack of integer digital signal processing instructions, a feature usually found on most 32-bit embedded architectures such as ARMv7-M, ARMv8-M, Renesas RX, MIPS, etc. On the other hand, RISC-V’s FPU extensions are IEEE754-2008-compliant meaning they include floating-point multiply-and-accumulate and multiply-and-subtract instructions. Unfortunately, these are floating-point-only instructions and can’t perform DSP operations on integers.

Along with the E31 core (which is FE310G’s core), SiFive has also the E51, a 64-bit general-purpose core, and U5, a high-performance multicore full-Linux design with up to eight U54 64-bit cores plus an auxiliary U51 64-bit core.

Also note that RISC-V ISA has a fully open-source development tool ecosystem such as full GCC support, a free Eclipse-based IDE (Freedom Studio), GDB, etc. Both hardware and software are open-source and free!

RISC-V Architecture

RISC-V ISA includes three main specifications regarding natural data size: 32-bit (RV32I e RV32E), 64-bit (RV64I) and 128-bit (RV128I). The I-suffix is used for the integer instruction set, whereas the E suffix is used for the simplified core (targeting embedded systems). The ISA also includes other suffixes for its several extensions: A (atomic operations), C (compressed instructions), M (integer multiply and division), F (single-precision FPU), D (double-precision FPU), Q (quad-precision FPU), V (vector operations), etc.

There are 32 general-purpose registers (x0 to x31, 32-bit each on RV32I) and a 32-bit program-counter (PC). RV32E has only 16 general-purpose registers and the PC.

Register NameAlternate Name Description
x0zeroAlways zero
x1raReturn address
x2spStack pointer
x3gpGlobal pointer
x4tpThread pointer
x5t0Temporary / Alternate return address
x8s0/fpSaved register / Frame pointer
x9s1Saved register
x10a0Function argument / return value
x11a1Function argument / return value
x12a2Function argument
x13a3Function argument
x14a4Function argument
x15a5Function argument
x16a6Function argument
x17a7Function argument
x18s2Saved register
x19s3Saved register
x20s4Saved register
x21s5Saved register
x22s6Saved register
x23s7Saved register
x24s8Saved register
x25s9Saved register
x26s10Saved register
x27s11Saved register
pc-Program counter

Table 1 – CPU Registers

One interesting RISC-V feature is the lack of a status register for ALU-related flag storage, instead, RISC-V ISA implements branch instructions capable of directly comparing register content.

RISC-V also includes some special registers (CSR – Control and Status Register) located in a special memory area (up to 2,048 registers) and which are accessed through special control instructions:

  • CSRRW – for CSR reading and writing (CSR content is read to a destination register and source-register content is then copied to the CSR);
  • CSRRS – for CSR reading and setting (CSR content is read to the destination register and then its content is set according to the source register bit-mask);
  • CSRRC – for CSR reading and clearing (CSR content is read to the destination register and then its content is cleared according to the source register bit-mask);
  • CSRRWI – the CSR content is read to the destination register and then the immediate constant is written into the CSR;
  • CSRRSI – the CSR content is read to the destination register and then set according to the immediate constant;
  • CSRRCI – the CSR content is read to the destination register and then cleared according to the immediate constant;

There are three mandatory registers which must be present on every RISC-V implementation (except on RV32E). These read-only registers can be used for performance statistics and other tasks:

  • RDCYCLE and RDCYCLEH – store the 64-bit elapsed clock cycles since an arbitrary initial time;
  • RDTIME and RDTIMEH – store the 64-bit elapsed standard timer clock cycles since an arbitrary initial time;
  • RDINSTRET and RDINSTRETH – store the 64-bit number of retired instructions since an arbitrary initial time.

There are also several privileged-mode related CSR (RISC-V can have up to three modes: user, supervisor and machine) which must be present when the privileged instruction ISA is present (currently in draft version 1.10 and subject to changes). The user mode is a non-privileged mode designed for application level, while supervisor mode has some privileged access and machine mode has full machine access. The following tables show user, supervisor and machine-related CSRs:

Table 2 – User CSRs
Table 3 – Supervisor CSRs
Table 4 – Machine CSRs

Regarding instructions, there is a total of 47 on RV32I, but it is possible to have a reduced version with a minimum of 38 instructions (by removing FENCE, ECALL, EBREAK and CSRxx instructions). Table 5 shows the six basic instruction formats and table 6 shows RV32I instruction-set.

Table 5 – RV32I basic instruction formats
Table 6 – RV32I instruction set

All data instructions operate on 32-bit operands, but load and store instructions can deal with other operand sizes: LB and LBU can load a byte from memory (LBU will also sign-extend it), LH and LHU can load a half-word from memory (LWU will also sign-extend it). SB, SH and SW are used to store a byte, half-word or word into memory respectively.

Note there are two synchronization-related instructions (FENCE and FENCE.I). They can be used on multiprocessor systems to ensure instruction/data is accessed in the right order. FENCE.I is specially useful to ensure instruction cache is updated after any kind of write to program memory.

Along the RV32I set, the microcontroller presented in this article series also includes integer multiply and divide extension (M-suffix)  and atomic operations (A-suffix). The following tables present these extension-related instructions.

Table 7 – Integer multiply and divide instructions
Table 8 – Atomic instructions

Regarding the compressed instructions extension (C-suffix), it is important to emphasize the RISC-V ISA is designed so that the CPU will real-time translate (decompress) 16-bit instructions into their 32-bit equivalent, without any performance impact. Also, due to the extensible format, 16, 32, 48, 64 or more bits are possible for instruction length. The lowest significant bits are used for decoding instruction size as shown in table 9.

Table 9 – RISC-V Instruction length encoding

The compressed instruction set is shown in tables 10, 11 and 12.

Table 10 – RISC-V compressed instructions (quadrant 0)
Table 11 – RISC-V compressed instructions (quadrant 1)
Table 12 – RISC-V compressed instructions (quadrant 2)

Finally, there is also a small privileged-mode instruction set (for supervisor and machine modes) listed in table 13. Note there is a “wait for interrupt” (WFI) instruction designed to suspend execution flow until an interrupt event resumes execution.

Table 13 – Privileged instructions

The next part of this article will cover the RISC-V interrupt and exception system and some details of FE310G, the first commercial silicon implementation of an RISC-V. See you!


Note: tables shown here were taken from SiFive’s documents referred above.

Leave a Reply