Shixuan Li



RISC-V Based CPU Design with Logisim [Part 3]

Decoding and ALU Selection

3. Instruction Analysis

Instructions Sheet

We assume that you have basic understanding about RISC-V, if you are not so familiar with RISC-V, please click HERE(not published) to see my related article.

Each type of RISC-V instructions has an special encoding format to convert the assembly scripts into machine codes. Here, given the machine codes, we need to determine which instruction it is by comparing with the formatting regulations.

3.1 Breaking the Instructions

To determine the type and value information of each type, we need to cut off certain parts of the instruction to do comparison. Thus, we want to first get all the possible information so that it will be much convenient in our further application.

We use splitters to get sections of information from the instruction

Types and Instruction Formats

According to the formats shown above, we need to break the instruction based on bit positions from bit 31 to bit 0 and get sections. However, we do not have to do it for every type, since there are some common parts for the decoding. For example, for Rtype we need to decode the instruction into func7, rs2, rs1, func3, rd, and opcode.

Note that since the position of opcode, rs2, rs1, rd are the same for all types (if needed), we do not need to replicate doing these parts.

And we can realize that for other parts, we just need to deal with the immediate parts.

The full version of first-stage decoding is presented as following

Break the Instructions

3.2 Determining the Types

As part of the RISC-V knowledge, we know that we should use opcode to determine the type of instruction. Also according to the Instructions Sheet at the very top of this page, we can do our analyzing by performing:

Determine the Types

Note that since the specialty of the Itype, we break the Itype into three categories which are Itype-Load, Itype-Other, and Itype-Jalr.

3.3 Determining the Instruction

Congrats! You are at the most tedious part in this CPU. According to the Instruction Sheet, we need to consider over opcode(Type), func3, and func7 in order to determine the exact instruction.

3.3.1 Rtype
Rtype Instruction Decoding
3.3.2 Itype-Load
Itype-Load Instruction Decoding
3.3.3 Itype-Other
Itype-Other Instruction Decoding
3.3.4 Itype-Jalr
Itype-Jalr Instruction Decoding
3.3.5 Stype
Stype Instruction Decoding
3.3.6 SBtype
SBtype Instruction Decoding
3.3.7 Utype
Utype Instruction Decoding
3.3.8 UJtype
UJtype Instruction Decoding

3.4 ALU Selection

Now we've successfully decoded the instructions. What's next?

3.4.1 Intuition

Note that we need to implement the corresponding ALU unit according to our result. How can we make this happen? Note that ALU is set of arithmetic units, with the given input. Thus, we need to make an index in our control panel to give our ALU a signal noticing which arithmetic unit we are using.

The solution to this is that we use an Multiplexer in our ALU unit (more details in Part 5), and we will create an controller AluSel to help choose the correct arithmetic unit. There are totally 13 arithmetic units we will implement for this CPU. Thus, we need to use a 4 bit Multiplexer.

To do this, we convert our decoding results into bit-representation. To be more specific, for example, we assign add unit to 0000 and and to 0001 .....

3.4.2 Implementation Indicator

How can we make this happen? The intuition here is that since each instruction will only be decoded as one implementation, we assign value to each kind of implementation. There are totally 30 kinds of instructions. We first assign 30 different indexes (denoted as ctrxx) to indicate if the instruction is corresponding to the implementation it represents.

Indicator Counting

Then, we using each ctrxx as an controller for a Multiplexer, getting corresponding cntxx as 0 if the instruction does not correspond to the instruction it represents, and xxx(the index number of arithmetic unit we need to implement considering the instruction, note that we should set the instructions that will use the same kind of arithmetic unit).

Here I follow the following indexing of ALU system

ALU Index

And here is how I made the "counting" (get the indexing for each instruction)

Counting Index Accumulation

Now we are at the final step. We will accumulate the values of the indexes and store the result in ALUSel. The intuition here is that since each instruction has unique type of implementation type, there will be only one result of the counters to be non-zero, which indicates which arithmetic unit we are using. This way, we are able to figure out an signal to out ALU, telling it which arithmetic unit to implement.

The accumulation look like this; Accumulation

In Part 4 we will talk about the RegFile unit of the CPU, which implement the registers, writing and reading data from the registers.