In this blog series I want to document my experience of writing my own RV32I core in verilog.
Altough there are already a lot of risc-v cores out there I wanted to write my own as I got curious to learn
verilog and the risc-v instruction set.
The goal for this series is to get a very simple RV32I core which is synthesizable with the open source FPGA toolchain
Yosys and can also be loaded into an iCE40 FPGA.
Before proceeding with this tutorial, check that these tools are installed on your system:
riscv32-*-elf-gcc
qemu-system-riscv32
Before we can even think of writing the first verilog code we need to prepare some things first. Most importantly: We need to find a way to verify our core’s correct function.
risc-v formal is a Formal Verification Framework for risc-v cores by Clifford Wolf. As I am a very beginner in Verilog and don’t know much about
formal verification I decided to choose the official risc-v isa test suite.
Unfortunately we need to do some changes in the test-environment, as the default one has a lot of pre-assumptions we do not have on our core in the first place.
Here are the steps:
Prepare your working environment:
Checkout the risc-v isa test repo:
Now create a file called riscv_test.h and add the following:
Those macros modify the test behavior as such that if the isa test fails, it will stuck in an endless loop, otherwise the tests finish successfully. So
the only instructions for this to work is JAL and ADDI (nop).
Now prepare a buildscript like this:
The last missing part before building is an appropriate linker script. Prepare one like this (link_qemu.ld):
Now you can build the isa tests like this:
OK, first part of the first part is over. Now let’s get down to the real business. As I initially stated we need to find
a way to verify our own risc-v core. To achieve this we will simply run all the isa tests in qemu-system-riscv32 which has
an official port of the SiFive HiFive1 microcontroller. Our assumption is, that the official implementation will deliver us
the correct CPU core states when running our modified isa tests.
So how do we get all the CPU core states from qemu?
Answer: We will issue qemu and gdb with some scripting magic to get all CPU core states we want.
First prepare a gdb script (step_mult.gdb) like this:
This can be called like this in combination with qemu:
Just let it run and kill it with fire after a few seconds:
The _trace.txt file should now contain all CPU register states of the test run.
I’ve prepared a script which does all the above things automatically for all selected tests:
OK, fine first part is finished. In the next part we will start developing the actual risc-v core and setup a test-environment which compares the register
states of our own core with the ones from qemu. The workflow is comparable to a typical test-driven-development flow ;)