Project 2.1: Qin110 - RV32I CPU (single-cycle)
Computer Architecture I @ ShanghaiTech University
Background
You fell asleep during CS110 lecture. When you wake up, you find yourself transported into the Three-Body Problem game. As the player, you are ordered by the Qin Shi Huang to build a computer to predict the three-body problem.
Fortunately, thanks to the advanced technology you brought back from 2026, you can use Logisim or SpinalHDL, rather than human logic gates, to complete your processor design.
You decide to name this great processor Qin110 in memory of the knowledge you learned in CS110.
Please complete your design carefully. Faulty hardware will result in the designer being โrepairedโ.
Introduction
In this project, you need to design a single-cycle processor that supports the RV32I subset. You are also encouraged to implement the full RV32I instruction set.
You may complete your design using either Logisim or SpinalHDL. You only need to choose one track to finish Project 2.1. This document only focuses on the CPU knowledge shared by both tracks.
GitHub Classroom
Choose exactly one of the following GitHub Classroom assignments:
- Logisim version: https://classroom.github.com/a/iwtGGtMS
- SpinalHDL version: https://classroom.github.com/a/CO-mci2V
RV32I Instruction
The CPU supports the following instructions
addsubandsltaddiandisltilblwjalrsbswbeqbltjalluiauipc
Here list all the RV32I instructions, with their function and encoding. Required instrucstions are marked with @ symbol.
| Instructions | Functions | Type | opcode |
f3 |
f7 |
Info | Required |
|---|---|---|---|---|---|---|---|
add rd,rs1,rs2 |
rd=rs1+rs2 |
R | 0110011 |
000 |
0000000 |
Add | @ |
sub rd,rs1,rs2 |
rd=rs1-rs2 |
R | 0110011 |
000 |
0100000 |
Sub | @ |
sll rd,rs1,rs2 |
rd=rs1<<rs2[4:0] |
R | 0110011 |
001 |
0000000 |
Shift Left Logical | |
srl rd,rs1,rs2 |
rd=rs1>>rs2[4:0] |
R | 0110011 |
101 |
0000000 |
Shift Right Logical | |
sra rd,rs1,rs2 |
rd=rs1>>>rs2[4:0] |
R | 0110011 |
101 |
0100000 |
Shift Right Arithmetic | |
xor rd,rs1,rs2 |
rd=rs1^rs2 |
R | 0110011 |
100 |
0000000 |
Xor | |
or rd,rs1,rs2 |
rd=rs1\|rs2 |
R | 0110011 |
110 |
0000000 |
Or | |
and rd,rs1,rs2 |
rd=rs1&rs2 |
R | 0110011 |
111 |
0000000 |
And | @ |
slt rd,rs1,rs2 |
rd=(rs1<rs2) |
R | 0110011 |
010 |
0000000 |
Set Less Than | @ |
sltu rd,rs1,rs2 |
rd=(rs1<rs2) |
R | 0110011 |
011 |
0000000 |
Set Less Than Unsigned | |
addi rd,rs1,imm |
rd=rs1+SE(imm) |
I1 | 0010011 |
000 |
------- |
Add Immediate | @ |
slli rd,rs1,imm |
rd=rs1<<imm |
I2 | 0010011 |
001 |
0000000 |
Shift Left Logical Immediate | |
srli rd,rs1,imm |
rd=rs1>>imm |
I2 | 0010011 |
101 |
0000000 |
Shift Right Logical Immediate | |
srai rd,rs1,imm |
rd=rs1>>>imm |
I2 | 0010011 |
101 |
0100000 |
Shift Right Arithmetic Immediate | |
xori rd,rs1,imm |
rd=rs1^SE(imm) |
I1 | 0010011 |
100 |
------- |
Xor Immediate | |
ori rd,rs1,imm |
rd=rs1\|SE(imm) |
I1 | 0010011 |
110 |
------- |
Or Immediate | |
andi rd,rs1,imm |
rd=rs1&SE(imm) |
I1 | 0010011 |
111 |
------- |
And Immediate | @ |
slti rd,rs1,imm |
rd=(rs1<SE(imm)) |
I1 | 0010011 |
010 |
------- |
Set Less Than Immediate | @ |
sltiu rd,rs1,imm |
rd=(rs1<SE(imm)) |
I1 | 0010011 |
011 |
------- |
Set Less Than Immediate Unsigned | |
lb rd,imm(rs1) |
rd=SE([rs1+SE(imm)][7:0]) |
I1 | 0000011 |
000 |
------- |
Load Byte | @ |
lh rd,imm(rs1) |
rd=SE([rs1+SE(imm)][15:0]) |
I1 | 0000011 |
001 |
------- |
Load Half | |
lw rd,imm(rs1) |
rd=[rs1+SE(imm)] |
I1 | 0000011 |
010 |
------- |
Load Word | @ |
lbu rd,imm(rs1) |
rd=ZE([rs1+SE(imm)][7:0]) |
I1 | 0000011 |
100 |
------- |
Load Byte Unsigned | |
lhu rd,imm(rs1) |
rd=ZE([rs1+SE(imm)][15:0]) |
I1 | 0000011 |
101 |
------- |
Load Half Unsigned | |
jalr rd,rs1,imm |
rd=pc+4, pc=rs1+SE(imm) |
I1 | 1100111 |
000 |
------- |
Jump and Link Register | @ |
sb rs2,imm(rs1) |
[rs1+SE(imm)][7:0]=rs2[7:0] |
S | 0100011 |
000 |
------- |
Store Byte | @ |
sh rs2,imm(rs1) |
[rs1+SE(imm)][15:0]=rs2[15:0] |
S | 0100011 |
001 |
------- |
Store Half | |
sw rs2,imm(rs1) |
[rs1+SE(imm)]=rs2 |
S | 0100011 |
010 |
------- |
Store Word | @ |
beq rs1,rs2,lab |
if(rs1==rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
000 |
------- |
Branch If Equal | @ |
bne rs1,rs2,lab |
if(rs1!=rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
001 |
------- |
Branch If Not Equal | |
blt rs1,rs2,lab |
if(rs1< rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
100 |
------- |
Branch If Less Than | @ |
bltu rs1,rs2,lab |
if(rs1< rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
110 |
------- |
Branch If Less Than Unsigned | |
bge rs1,rs2,lab |
if(rs1>=rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
101 |
------- |
Branch If Greater Than or Equal | |
bgeu rs1,rs2,lab |
if(rs1>=rs2) pc+=SE({imm,1'b0}) |
B | 1100011 |
111 |
------- |
Branch If Greater Than or Equal Unsigned | |
jal rd,lab |
rd=pc+4, pc+=SE({imm,1'b0}) |
J | 1101111 |
--- |
------- |
Jump and Link | @ |
lui rd,imm |
rd={imm,12'b0} |
U | 0110111 |
--- |
------- |
Load Upper Immediate | @ |
auipc rd,imm |
rd=pc+{imm,12'b0} |
U | 0010111 |
--- |
------- |
Add Upper Immediate to PC | @ |
RV32I Microarchitecture
The following figure is a good start point to understand a single-cycle RISC-V datapath (1 ALU, 2 ADD, 3 MUX). However, it only supports a smaller subset of RV32I than this project. Some modification must be made to complete the current required subset or the full RV32I instruction set.
- Branch Unit is required to proceed various branch instructions. We recommend to place it at EX stage instead of as a submodule in Control Unit at ID stage, in order to be compatible with pipeline in latter project.
- Load Store Unit is required before and after DMEM. For store, you need to generate byte mask. For load, you need to pick requested byte or half and extend it to 32-bits.
- ALU might need a new control signal
Less = ALUResult[0]along withZero = (ALUResult == 32'b0). - ALU should support pass
SrcAorSrcBtoALUResult(Instructionluisimply writebackimmonSrcB). - A MUX on
SrcAis required, input isrs1andpc(Instructionauipcrequested to writebackpc + imm). - A MUX on first input of
PCTargetis required, input is alsors1andpc(Instructionjalrrequested to jump tors1 + imm).
Here is a suggested naming scheme for control signals. You may not need every case to complete the required subset. The exact encoding of each control signal does not matter.
| Control Signal | Case | Usage |
|---|---|---|
RegWrite |
0, 1 |
REGFILE writeback enable |
ResultSrc |
alu, mem, pc4 |
REGFILE writeback source |
MemWrite |
0, 1 |
DMEM writeback enable |
MemOp |
word, half, byte, halfu, byteu |
DMEM operation type |
AluOp |
add, sub, sll, srl, sra, and, or, xor, slt, slti, srca, srcb |
ALU operation type |
AluSrcA |
rs1, pc |
ALU srca input select |
AluSrcB |
rs2, imm |
ALU srcb input select |
PcAddSrcA |
rs1, pc |
ADD PCTarget srca input select |
PcSrc |
pc4, pctarget |
PC source |
ImmSrc |
i1, i2, s, b, j, u |
Immediate extend mode |
RV32I Dataflow
Here are the major dataflows for six different instruction classes.
The following TA(s) are responsible for this project: Chaofan Li <lichf2025@shanghaitech.edu.cn>, Yuxuan Li <liyx22025@shanghaitech.edu.cn>