RISC-V RTOS-enabled multi-core SoC using Wishbone4 interconnect.
CPU is a single-issue in-order 4 stages pipeline with branch-JAL-RET-prediction (BHT: 4096 entries, RAS: 8 entries). The stages are IF (Fetch) ID (Decode) EX (Execute) WB (WriteBack). Memory access is not considered a stage in the design, but just another late result that takes multiple cycles like division.
Software toolchain includes libc with builtin RTOS named _OS (underLineOS) which implements preemptive multi-threading (SMP capable load balanced per-cpu runqueue), sw-timer, mutex, semaphore, fifo.
git clone https://github.com/fontamsoc/ftpu.git
git -C ftpu/ submodule update --init
wget https://github.com/YosysHQ/oss-cad-suite-build/releases/download/2025-12-04/oss-cad-suite-linux-x64-20251204.tgz
sudo tar -C /opt/ -xf oss-cad-suite-linux-x64-20251204.tgz
PATH="/opt/oss-cad-suite/bin:${PATH}"
sudo tee /etc/profile.d/fpga-toolchain.sh <<'EOF'
PATH="/opt/oss-cad-suite/bin:${PATH}"
EOF
A number of sample applications are available under ftpu/hw/rv32-sim/apps/ along with their prebuilt .hex file:
coremark donut helloworld isatests smp_pi thrdtst tinyraytracer
cd ftpu/hw/rv32-sim/
make clean sim run SRAM_INITFILE=apps/coremark/rv32/coremark.32.hex CLKFREQ=1000000
cd -
Output:
rm -rf obj_dir *.fst *.log
make[1]: Entering directory '/tmp/ftpu/hw/rv32-sim'
verilator -cc --exe --x-assign 1 --x-initial-edge \
--relative-includes -I.. -Wno-lint \
-DCLKFREQ=1000000 \
-DCPU_COUNT=1 \
-DXWORDBITSZ=32 \
-DSRAM_INITFILE='"apps/coremark/rv32/coremark.32.hex"' \
-DSRAM_KBSIZE="(256/*KB*/)" \
sim.sv sim.cpp &>>build.log
make[1]: Leaving directory '/tmp/ftpu/hw/rv32-sim'
Sun Jul 26 05:08:30 PM CDT 2026
apps/coremark/rv32/coremark.32.hex loaded
CoreMark @ 1000000 Hz
2K performance run parameters for coremark.
Total ticks : 14872319
Total time (secs): 14.872319
Iterations/Sec : 4.034341
Iterations : 60
Compiler version : GCC16.1.0
Compiler flags : -O3 -DMULTITHREAD=16 -DUSE__OS=1 -DPERFORMANCE_RUN=1
Parallel cores : 1
Memory location : HEAP
Correct operation validated. See readme.txt for run and reporting rules.
CoreMark 1.0 : 4.034341 / GCC16.1.0 -O3 -DMULTITHREAD=16 -DUSE__OS=1 -DPERFORMANCE_RUN=1 / HEAP / 1:cores
CoreMark/MHz : 4.034341
CoreMark done
- /tmp/ftpu/hw/rvxx/sys.pu.sv:231: Verilog $finish
cd ftpu/hw/rv32-sim/
make clean sim run SRAM_INITFILE=apps/smp_pi/smp_pi.32.hex CPU_COUNT=4
cd -
Output:
rm -rf obj_dir *.fst *.log
make[1]: Entering directory '/tmp/ftpu/hw/rv32-sim'
verilator -cc --exe --x-assign 1 --x-initial-edge \
--relative-includes -I.. -Wno-lint \
-DCLKFREQ=100000000 \
-DCPU_COUNT=4 \
-DXWORDBITSZ=32 \
-DSRAM_INITFILE='"apps/smp_pi/smp_pi.32.hex"' \
-DSRAM_KBSIZE="(256/*KB*/)" \
sim.sv sim.cpp &>>build.log
make[1]: Leaving directory '/tmp/ftpu/hw/rv32-sim'
Sun Jul 26 05:09:00 PM CDT 2026
apps/smp_pi/smp_pi.32.hex loaded
Calculate first 240 digits of Pi independently by 16 threads.
Pi value calculated by thread #0: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #1: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #2: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #3: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #4: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #5: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #6: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #7: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #8: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #9: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #10: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #11: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #12: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #13: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #14: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
Pi value calculated by thread #15: 314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316
All 16 threads executed by 4 cores in 18 ms
- /tmp/ftpu/hw/rvxx/sys.pu.sv:231: Verilog $finish
cd ftpu/hw/rv32-sim/
make clean sim run SRAM_INITFILE=apps/tinyraytracer/tinyraytracer.32.hex CPU_COUNT=4
cd -
Output:
cd ftpu/hw/rv32-sim/
make clean sim run SRAM_INITFILE=apps/donut/donut.32.hex
cd -
Output:
Generate signal traces that can be viewed using GTKWave using sim_trace instead of sim make target,
and setting TRACE_BEGIN= (and optionally TRACE_LEN=):
cd ftpu/hw/rv32-sim/
make clean sim_trace run SRAM_INITFILE=apps/helloworld/helloworld.32.hex TRACE_BEGIN=100 TRACE_LEN=2000
gtkwave sim.fst
cd -
FPGA support is available under ftpu/hw/:
rv32-artya7100 rv32-nexysa7100 rv32-orangecrab0285
The easiest FPGA support to work with is the rv32-orangecrab0285 because its sram can be updated without rebuilding the bitstream:
cd ftpu/hw/rv32-orangecrab0285/yosys/
make updsram SRAM_INITFILE=../../rv32-sim/apps/coremark/rv32/coremark.32.hex
# While holding the button on the OrangeCrab, plug it in;
# it enters the bootloader and enables programming a new bitstream.
make prog
cd -
Set SRAM_INITFILE of make updsram to a different .hex to use a different application.
To rebuild the rv32-orangecrab0285 bitstream, use make clean all.
The bitstreams for the xilinx FPGAs, such as rv32-artya7100, need to be built from their Vivado project file (ie: ftpu/hw/rv32-artya7100/vivado2020/artya7100.xpr).
Build sw toolchain (or download prebuilt
)
Only needed in order to build software.
sudo ln -snf /bin/bash /bin/sh
mkdir ftpu-build && cd ftpu-build
make -f ../ftpu/makefile clean all
The toolchain gets generated under /opt/ftpu-toolchain/.
sudo tar -xf ftpu-toolchain-linux-x64.tar.xz -C /opt/
PATH="/opt/ftpu-toolchain/bin:${PATH}"
sudo tee /etc/profile.d/ftpu-toolchain.sh <<'EOF'
PATH="/opt/ftpu-toolchain/bin:${PATH}"
EOF