Use logisim to build a single-cycle CPU and add instructions
to build
General design
Borrowing from Boss Gao’s diagram, we only need to make PC, NPC, IM, RF, EXT, ALU, DM, and Controller modules separately, then connect according to the diagram, and finally process the control signals, and a CPU is almost finished. . The currently supported instruction sets are {addu, subu, ori, lw, sw, beq, jal, jr, nop, lui, sb, lb, sh, lh}
The following sub-modules are analyzed one by one
PC
It is essentially a 32-bit register. Here, an asynchronous reset is used, so the reset signal is directly connected to the clear port.
NPC
Since my CPU supports beq, jal, jr, NPCOp has 2 bits, as shown in the table below
NPCOp | Function |
---|---|
00 | Calculate sequential address (PC+4) |
01 | Calculate beq address |
10 | Calculate jal address |
11 | Calculate jr address |
Among them, PC4 is used to output PC+4 to RF to complete the jal command
IM
This is even simpler, just use a ROM to get it done, pay attention to lead out the 2~6 digits of the PC as the address of the IM.
RF
This is time-consuming. I heard that you can write code to build this thing by opening the .circ file with vscode. After opening it, you will find 3k lines of code, so you can turn off vscode and continue to connect manually. It should look like this when it's finished.
It looks like this from the outside. RD1 outputs the value of the register corresponding to A1, and RD2 outputs the value of the register corresponding to A2. When the write enable signal WE3 is valid, WD3 will be written into the register corresponding to A3 at the rising edge of the clock.
EXT
Output after expanding imm16. Since my lui is loaded into the high bit using EXT (it seems that it should be implemented with ALU?), so my EXT has 3 functions: unsigned extension, sign extension, and left shift 16 bits.
ALU
Different operations can be performed according to ALUOp. Here, an adder is used for addition and subtraction (AB=A+~B+1), but it seems that this is not easy to expand (?)
DM
It was originally a very simple RAM, but since lb, sb, lh, and sh have been made, it is necessary to add combinational logic before and after DM to ensure that the data of other bits will not be changed. Two control signals are used here, SSel controls the bit width of the store, and LSel controls the bit width of the Load. (In fact, one control signal can be used, but I was stupid and used two when I was doing it)
Use a decoder to select the segment to be replaced. For example, when sb, the 0 and 1 bits of A are 01, then the 8 and 15 bits of the 32-bit data corresponding to the address in DM will be replaced with the lower 8 bits of WD. , and then stored in DM, thus ensuring that only one byte is read and other bits are not changed, that is, sb is realized.
Controller
The simplest method is used. When building, you can point opcode and funct to the command to be added with a small hand, and then connect the command. If the opcode is 000000, then combine it with the signal obtained by funct to get the instruction, such as addu and subu in the figure.
After getting the instruction, according to the truth table of the column, connect the ones that are 1 in the truth table
For example, for NPCOp[1:0], only beq is 01, only jal is 10, and only jr is 11, that is, NPCOp[0] only takes 1 when beq and jr, and NPCOp[1] only takes jal and jr Take 1 for jr, so just connect them, as shown in the figure below.
For each control signal is connected in this way, the construction of the CPU can be completed.
add command
Precautions
- When changing the number of input data of the AND gate or the OR gate, it is recommended to change from an odd number to an odd number, otherwise such a situation may occur: For example, I have a 5input OR gate, as follows
Now to add the sixth input, if it is directly changed to 6input, then as shown in the figure
Found that the middle is empty
And if you follow the principle of changing odd numbers to odd numbers, there will be no mistakes. For example, change the number of input to 7, as shown in the figure below, and the middle ones are connected.
eg: add addiu
First analyze the data path
Judging whether it is necessary to add a new path to realize the instruction, it can be seen that my CPU has all the required functions, so directly modify the control signal
OK control signal
For NPCOp, this is not a jump instruction, so NPCOp takes 00
For RFWr, write back to R[rt], so RFWr is 1
For EXTOp, sign extension is required, so take 01
For ALUOp, addition, so take 00
For DMWr, do not write to DM, so take 0
For WRSel, since R[rt] is written, take 01
For WDSel, since the written data comes from the calculation result of ALU, it takes 00
For BSel, since the second number involved in ALU calculation comes from EXT, it takes 1
For SSel and LSel, since no halfword or byte is involved, both take 00
Add command signal
First point the opcode into the instruction
Then connect to addiu
At this time, since the opcode is the addiu command, only addiu should be on.
modify control signal
After getting the addiu signal, you only need to connect the corresponding position where the addiu control signal is 1. For example, addiu only has RFWr, EXTOp[0], WRSel[0], and BSel as 1, so you only need to add one to their OR gate The root wire is connected with the addiu signal. After the connection is completed, check whether the control signal at this time is the same as that analyzed before.
It can be seen that it is exactly the same as the previous analysis, so far the addition of addiu is complete.