Stage 7: Register to register operations, all tests passing

This commit is contained in:
2025-11-06 19:02:42 +01:00
parent 37435c6677
commit c2c16d9672
4 changed files with 122 additions and 9 deletions

View File

@@ -3,7 +3,7 @@
_start: _start:
lui x2, 0xdead0 lui x2, 0xdead0
lui x3, 0x0 lui x3, 0x0
lui x4, 0x1 addi x4, x0, 0x1
addi x5, x0, (-1) addi x5, x0, (-1)
# Add 0 # Add 0

View File

@@ -1,4 +1,4 @@
# expected: 00000000, 00000001, 00000001, 00000000 # expected: 00000000, 00000001, 00000000, 00000000
.text .text
_start: _start:
addi x1, x0, (-1) addi x1, x0, (-1)

View File

@@ -10,8 +10,12 @@ class CUInterface extends Bundle {
val alu_opcode = Output(AluOpCode()) val alu_opcode = Output(AluOpCode())
val optype = Output(OpType()) val optype = Output(OpType())
// Muxers
// The naming convention is as follows : mux_xxx_yyy.
// If the signal is hot, xxx is selected otherwise yyy is selected
val mux_alu_imm = Output(Bool()) val mux_alu_imm = Output(Bool())
val mux_rega_pc = Output(Bool()) val mux_rega_pc = Output(Bool())
val mux_regb_imm = Output(Bool())
} }
object OpType extends ChiselEnum { object OpType extends ChiselEnum {
@@ -26,7 +30,7 @@ object OpCode extends ChiselEnum {
// Type I + Type IR // Type I + Type IR
// Instruction format // Instruction format
// xxx rd, rs1 imm // xxx rd, rs1, imm
// Perfomrs some operation with rs1 and immediate // Perfomrs some operation with rs1 and immediate
// and writes back to a register // and writes back to a register
@@ -34,6 +38,14 @@ object OpCode extends ChiselEnum {
// slti, sltiu // slti, sltiu
val OpImm = 0b0010011.U val OpImm = 0b0010011.U
// Instruction format
// xxx rd, rs1, rs2
// Perfomrs some operation with rs1 and rd2
// and writes back to a register
// add, and, or, xor, sll, srl, sra, slt, stlu
val OpR = 0b0110011.U;
} }
@@ -45,6 +57,7 @@ class ControlUnit() extends Module {
io.optype := OpType.U io.optype := OpType.U
io.mux_alu_imm := true.B; io.mux_alu_imm := true.B;
io.mux_rega_pc := true.B; io.mux_rega_pc := true.B;
io.mux_regb_imm := true.B;
// Decode instruction // Decode instruction
val opcode = io.instruction(6, 0); val opcode = io.instruction(6, 0);
@@ -55,14 +68,15 @@ class ControlUnit() extends Module {
// U instructions // U instructions
is(OpCode.LUI) { is(OpCode.LUI) {
io.reg_file_we := true.B io.reg_file_we := true.B // Write to regfile
io.mux_alu_imm := false.B io.mux_alu_imm := false.B // Send immy directly to refile
io.optype := OpType.U io.optype := OpType.U
} }
is(OpCode.AUIPC) { is(OpCode.AUIPC) {
io.alu_opcode := AluOpCode.Add io.alu_opcode := AluOpCode.Add
io.reg_file_we := true.B io.reg_file_we := true.B // Write to regfile
io.mux_rega_pc := false.B io.mux_rega_pc := false.B // Send PC to ALU A
io.mux_alu_imm := false.B; // Send immu to ALU B
io.optype := OpType.U io.optype := OpType.U
} }
@@ -71,8 +85,16 @@ class ControlUnit() extends Module {
io.reg_file_we := true.B io.reg_file_we := true.B
opImm(funct3, funct7, io); opImm(funct3, funct7, io);
} }
// OpR instructions
is(OpCode.OpR) {
io.reg_file_we := true.B
opR(funct3, funct7, io);
}
} }
// Implements functions for all instruction of the opImm kind // Implements functions for all instruction of the opImm kind
def opImm(funct3: UInt, funct7: UInt, io: CUInterface) = def opImm(funct3: UInt, funct7: UInt, io: CUInterface) =
{ {
@@ -98,6 +120,10 @@ class ControlUnit() extends Module {
val SRLI = 0b0000000.U val SRLI = 0b0000000.U
val SRAI = 0b0100000.U val SRAI = 0b0100000.U
} }
io.mux_regb_imm := false.B; // OpImm are operations with imm, so send imm to ALU
io.mux_alu_imm := true.B;
io.mux_rega_pc := true.B;
switch(funct3) switch(funct3)
{ {
// Type I // Type I
@@ -162,6 +188,93 @@ class ControlUnit() extends Module {
} }
} }
} }
// Implements functions for all instruction of the opR kind
def opR(funct3: UInt, funct7: UInt, io: CUInterface) =
{
// Meaning of Funct3 in the context of an OpR instruction
object Funct3 extends ChiselEnum
{
// Type I
val ADD = 0b000.U
val AND = 0b111.U
val OR = 0b110.U
val XOR = 0b100.U
val SLL = 0b001.U
val SLT = 0b010.U
val SLTU = 0b011.U
// Arithmetic op (discriminate by Funct7)
val SRL_SRA = 0b101.U
}
// Meaning of Funct7 in the context of SHIFTR IR instructions
object IRFunct7 extends ChiselEnum
{
val SRL = 0b0000000.U
val SRA = 0b0100000.U
}
io.mux_regb_imm := true.B; // OpImm are operations with imm, so send imm to ALU
io.mux_rega_pc := true.B;
io.mux_alu_imm := true.B;
switch(funct3)
{
// Type I
is(Funct3.ADD)
{
io.alu_opcode := AluOpCode.Add
}
is(Funct3.AND)
{
io.alu_opcode := AluOpCode.And
}
is(Funct3.OR)
{
io.alu_opcode := AluOpCode.Or
}
is(Funct3.XOR)
{
io.alu_opcode := AluOpCode.Xor
}
is(Funct3.SLL)
{
io.alu_opcode := AluOpCode.ShiftLeft
}
is(Funct3.SLT)
{
io.alu_opcode := AluOpCode.LessThanSigned
}
is(Funct3.SLTU)
{
io.alu_opcode := AluOpCode.LessThanUnsigned
}
// Type IR
is(Funct3.SRL_SRA)
{
switch(funct7)
{
is(IRFunct7.SRL)
{
io.alu_opcode := AluOpCode.ShiftRight
}
is(IRFunct7.SRA)
{
io.alu_opcode := AluOpCode.ShiftArithmeticRight
}
}
}
}
}
} }

View File

@@ -64,7 +64,7 @@ class Rv32i(sim: Boolean = true) extends Module {
reg_file.io.rs1_data, reg_file.io.rs1_data,
execute_pc execute_pc
); );
alu.io.b := imm; alu.io.b := Mux(control_unit.io.mux_regb_imm, reg_file.io.rs2_data, imm);
reg_file.io.rd_data := Mux(control_unit.io.mux_alu_imm, alu.io.out, imm); reg_file.io.rd_data := Mux(control_unit.io.mux_alu_imm, alu.io.out, imm);