Direct to Table of Contents:
First of all, there is an overview of the CPU, FII-RISCV. RISCV is an open standard instruction set architecture (ISA) based on reduced instruction set computer (RISC) principles . FII-RISCV is researched and developed following the RISCV standard. Here are some basic features about FII-RISCV:
- RV32I (32 registers that supports integer operations)
- Does not support multiplication instructions (the newest version do support)
- Does not support Atomic operations
- Does not support compressed instruction
- Supports software interrupt
- Supports timer interrupt
- Supports UART output (Peripherals)
- Supports 4 groups of GPIO interfaces (32 pins per group)
- 4K bytes DTCM
- 16K bytes ITCM
Here is a screenshot of the address allocation, which is helpful when writing the C project, as shown in Figure 1.
Address range Detail Description Read/Write Size
Figure 1 Address allocation
The GPIO configuration is shown below. The relevant code block is located in the top level entity, fii_cpu_sys.v.
wire [ 31: 0 ] gpio_ia; wire [ 31: 0 ] gpio_oa; wire [ 31: 0 ] gpio_ta; wire [ 31: 0 ] gpio_a; //IO buffer for LED fii_iobuf #( .IO_WIDTH( 32 ) ) fii_iobuf_insta ( .i_dio_t ( gpio_ta ), .i_dio ( gpio_oa ), .o_dio ( gpio_ia ), .io_dio_p ( gpio_a ) ); assign LED = gpio_a[ IO_WIDTHa - 1: 0 ]; wire [ 31: 0 ] gpio_ib; wire [ 31: 0 ] gpio_ob; wire [ 31: 0 ] gpio_tb; wire [ 31: 0 ] gpio_b; //IO buffer for segment display location selection fii_iobuf #( .IO_WIDTH( 32 ) ) fii_iobuf_instb ( .i_dio_t ( gpio_tb ), .i_dio ( gpio_ob ), .o_dio ( gpio_ib ), .io_dio_p ( gpio_b ) ); assign SEAT = gpio_b[ IO_WIDTHb - 1: 0 ]; wire [ 31: 0 ] gpio_ic; wire [ 31: 0 ] gpio_oc; wire [ 31: 0 ] gpio_tc; wire [ 31: 0 ] gpio_c; //IO buffer for segment selection fii_iobuf #( .IO_WIDTH( 32 ) ) fii_iobuf_instc ( .i_dio_t ( gpio_tc ), .i_dio ( gpio_oc ), .o_dio ( gpio_ic ), .io_dio_p ( gpio_c ) ); assign SEG = gpio_c[ IO_WIDTHc - 1: 0 ]; wire [ 31: 0 ] gpio_id; wire [ 31: 0 ] gpio_od; wire [ 31: 0 ] gpio_td; wire [ 31: 0 ] gpio_d; //IO buffer fro push buttons fii_iobuf #( .IO_WIDTH( 32 ) ) fii_iobuf_instd ( .i_dio_t ( gpio_td ), .i_dio ( gpio_od ), .o_dio ( gpio_id ), .io_dio_p ( gpio_d ) ); assign PB = gpio_d[2:0];
It’s important to note that only when using “assign” with I/O buffer, “assign” can connect an inout type, otherwise, “assign” always connects an output.
As shown in Figure 2, the translation procedure for C program is as follows:
- Write C source code (e.g. foo.c in Unix and MS-DOS)
- Compiler converts C program to assembly program (e.g. foo.s in Unix, foo.asm in MS-DOS )
- Assembler converts assembly program to the machine language module (object, e.g. foo.o in Unix, foo.obj in MS-DOS)
- Linker assembles machine language module, including libraries to the executable file (e.g. a.out in Unix, a.exe in MS-DOS)
- At run time, loader would load the program into memory and jump to the address where it started.
Figure 2 Translate the C source code to runnable program 
The following figures 3-5 illustrate different translation situations. It can be seen that the compiler and assembler translate the C source files to the object files, where the linker links every object files together when translating multiple files. If only the assembly files or object files are given, then the compiler or assembler translation could be neglected.
Figure 3 Single C source file translation
Figure 4 Two C source files translation
Figure 5 Multiple types of files (*.c, *.s, *.o) translation
 F. Based, “C Programming (1) on RISCV FII-PRX100 (ARTIX-7, XC7A100T) XILINX FPGA Board with our FII-Risc-V CPU (RV32G2.0)”, Fraser Innovation Inc | We focus on FPGA Development Board, 2021. [Online]. Available: https://fraserinnovations.com/fpga-board-based/risc-v-cpu-risc-v-c-programming/. [Accessed: 10- Mar- 2021].
 Riscv.org, 2021. [Online]. Available: https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf. [Accessed: 22- Feb- 2021].