I don't know why egg is in the name, but eggcpu will be a small riscV soft-core in verilog implementing RV32I version 2.2. Will definetly suck but will probably serve as a very good workbench to try out some stuff.
First iteration of the design, a single cycle core that supports only a tiny subset of the riscV32I
instruction set:
- add
- sub
- lw
- sw
- bne
- beq
- and
- or
Second iteration of the design, does not support interrupts and supervisor level instructions.
The design implementes the classic 5-stage RISC pipeline with the following stages:
Instruction Read
=> Instruction Decode
=> Execute
=> Mem R/W
=> Write Back
Hazards are solved using forwarding and stalling. Forwarding is done from EX/MEM
and MEM/WB
to the EX
stage as shown in the image above.
First, we need to build the toolchain (compiler,linker) used for building programs and tests for the Cores.
The following instructions are taken from Clifford Worlf's picorv32 repository. Installation is done in /opt/riscv32i
:
# Ubuntu packages needed:
sudo apt-get install autoconf automake autotools-dev curl libmpc-dev \
libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo \
gperf libtool patchutils bc zlib1g-dev git libexpat1-dev
sudo mkdir /opt/riscv32i
sudo chown $USER /opt/riscv32i
git clone https://github.com/riscv/riscv-gnu-toolchain riscv-gnu-toolchain-rv32i
cd riscv-gnu-toolchain-rv32i
git submodule update --init --recursive
mkdir build; cd build
../configure --with-arch=rv32i --prefix=/opt/riscv32i
make -j$(nproc)
Install Verilator, Icarus Verilog, and GTKwave to view signals produced by the simulators.
For now I'm using Verilator
to convert Verilog to C++ and then running that. So as to not worry about manually decoding the instruction to test the cores I wrote a small C++ program to read the .text
section from the elf
file generated by riscv32-elf-as
and then reading in the generated memory file using $readmemh
in verilog.
For the pipelined version, I switched to using the Icarus Verilog simulator. to build the riscV-official
test files run the /testing/riscV-official/build_tests.sh
shell script that will compile,link and use elf2hex
to convert elf files to hex files that are read by Icarus Verilog
.
To run the all the Tests do make runall
. For single testing edit the SINGLE_TEST
variable in testbench.v
then run make sim
or to produce a .vcd
trace use make trace
which automaticaly open gtk-wave
.
- Implement unalligned loads and stores
- Implement a better branch prediction scheme
- Try to implement
ISA Extension M
- Reduce cycle stall for mispredicted branches ( 4 currently )
- Implement caches ( Instruction and Data Cache )
All measures were done using Xilinx's Vivado 2020.1
tool.
The table below features compilations of the LUT
and BRAM
utilizations along with the maximum frequency that eggpu
can run one the Artix-7 XC7A35T
. I also recorded what improvements have been made along the way to get faster clock speeds and hopefully lower resource use.
Attempt | Slice LUTs | Slice Registers | BRAM Tiles | Clock period (frequency) |
---|---|---|---|---|
1(bad!) | 1523 | 1341 | 4 | 16ns (62.5Mhz) |
- TODO