Counting on my RISC-V FPGA CPU
Introduction
Last time, I talked about getting a minimal RISC-V CPU up and running on my Basys FPGA development board. In this article, we’ll connect up the seven segment displays as memory mapped I/O and write a simple RISC-V Assembly Language program to count on the display.
Connecting the Seven Segment Display
To support the four seven segment displays, I took the code from the book “FPGA Programming for Beginners” by Frank Bruno, and connected it to the RISC-V CPU from the book “Digital Design and Computer Architecture: RISC-V Edition” by Sarah L. Harris and David Harris. This turned out to be quite easy. Just needed to add a case statement in soc.sv where if the address is 0x100 then it goes to the seven segment display routine. I chose the rather low address 0x100 since that fits in an immediate argument saving additional code.
always @(negedge clk_25)
begin
if(MemWrite) begin
case(DataAdr)
16'h100: encoded = WriteData;
endcase
led[7:0] = WriteData[7:0];
led[15:8] = DataAdr[7:0];
end
end
To test this, I needed to write a RISC-V Assembly Language program, only using the instructions that my mini RISC-V CPU supports.
Writing RISC-V Assembly Language
I wrote the simple program:
# Simple program to count on the 7-segment display addi x2, x0, 0 #initialize counter to 0 addi x3, x0, 0x100 # memory address of seven seg display main: addi x2, x2, 1 # add 1 to counter sw x2, (x3) # save to the display addi x4, x0, 0x7ff # delay loop counter addi x6, x0, 9 # ready to shift left 9 bits sll x4, x4, x6 # shift left 9 bits addi x5, x0, 1 # will subtract from x4 loop: sub x4, x4, x5 # decrement counter beq x4, x0, next # loop done, proceed beq x4, x4, loop # repeat loop next: beq x2, x2, main # jump back to loop forever
The first version of this didn’t have the delay loop, so was simpler. With this nice Assembly Language source code, I needed a way to assemble it. I googled and found RARS (Risc-V Assembler and Runtime Simulator). RARS compiled the program fine and I could copy the compiled programs to the instruction memory in the SoC source code.


When I first ran the program, it was way too fast and the seven segment display just showed all eights (all segments lit up). So I added a delay loop, but due to the limited instruction set, I could only loop 0x7ff times, this slowed it down so the high order LED counted. I needed a way to create bigger numbers, so I implemented the SLL (shift logical left) instruction, which was easy to add to the ALU. I could have loaded a larger number from memory or could have written an outer loop to have two nested loops, but chose this instead. With this all done it works fairly well.
Utilization
Below is the utilization report for the hardware resources being used. Notice that with this simple CPU implementation that we are using a small percentage of the available resources. Hence, we have a lot of headroom to keep developing this simple CPU/computer.
+----------------------------+------+-------+------------+-----------+-------+
| Site Type | Used | Fixed | Prohibited | Available | Util% |
+----------------------------+------+-------+------------+-----------+-------+
| Slice LUTs* | 347 | 0 | 0 | 20800 | 1.67 |
| LUT as Logic | 299 | 0 | 0 | 20800 | 1.44 |
| LUT as Memory | 48 | 0 | 0 | 9600 | 0.50 |
| LUT as Distributed RAM | 48 | 0 | | | |
| LUT as Shift Register | 0 | 0 | | | |
| Slice Registers | 93 | 0 | 0 | 41600 | 0.22 |
| Register as Flip Flop | 93 | 0 | 0 | 41600 | 0.22 |
| Register as Latch | 0 | 0 | 0 | 41600 | 0.00 |
| F7 Muxes | 2 | 0 | 0 | 16300 | 0.01 |
| F8 Muxes | 1 | 0 | 0 | 8150 | 0.01 |
+----------------------------+------+-------+------------+-----------+-------+
Summary
Developing a CPU is a lot of work, but a lot of fun. It’s amazing that with a low cost FPGA development board you can design a CPU and start building a computer around it. This was a small increment in my RISC-V CPU, but nice to see that the tools are quite easy to work with to accomplish my goal.
[…] Last time, we assembled a small RISC-V program to run on my FPGA RISC-V core running on a Digilent Basys3 development board. To do this we used RARS, which is a quite good Assembler, Debugger, Simulator for RISC-V; in this article I thought I’d point out some other tools available from the official RISC-V github page, including the full GNU C toolchain. […]
Simulating RISC-V on a Raspberry Pi | Stephen Smith's Blog
April 1, 2023 at 8:06 pm