Add jal instruction

This commit is contained in:
2025-11-07 11:51:33 +01:00
parent c2c16d9672
commit cbf7ec9ad3
6 changed files with 90 additions and 41 deletions

View File

@@ -10,16 +10,21 @@ class CUInterface extends Bundle {
val alu_opcode = Output(AluOpCode())
val optype = Output(OpType())
// True if the decoded instruction is a jump
val is_jump = Output(Bool())
// 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_rega_pc = Output(Bool())
val mux_regb_imm = Output(Bool())
val mux_incrpc4_imm = Output(Bool())
val mux_regpc_executepc = Output(Bool())
}
object OpType extends ChiselEnum {
val U, I, IR = Value
val U, I, IR, J = Value
}
object OpCode extends ChiselEnum {
@@ -46,6 +51,8 @@ object OpCode extends ChiselEnum {
// add, and, or, xor, sll, srl, sra, slt, stlu
val OpR = 0b0110011.U;
// Type J
val JAL = 0b1101111.U
}
@@ -55,9 +62,12 @@ class ControlUnit() extends Module {
io.reg_file_we := false.B
io.alu_opcode := AluOpCode.Add
io.optype := OpType.U
io.is_jump := false.B;
io.mux_alu_imm := true.B;
io.mux_rega_pc := true.B;
io.mux_regb_imm := true.B;
io.mux_incrpc4_imm := true.B;
io.mux_regpc_executepc := true.B;
// Decode instruction
val opcode = io.instruction(6, 0);
@@ -76,21 +86,33 @@ class ControlUnit() extends Module {
io.alu_opcode := AluOpCode.Add
io.reg_file_we := true.B // Write to regfile
io.mux_rega_pc := false.B // Send PC to ALU A
io.mux_alu_imm := false.B; // Send immu to ALU B
io.mux_regb_imm := false.B; // Send immu to ALU B
io.optype := OpType.U
}
// OpImm instructions
is(OpCode.OpImm) {
io.reg_file_we := true.B
io.reg_file_we := true.B // Write to regfile
opImm(funct3, funct7, io);
}
// OpR instructions
is(OpCode.OpR) {
io.reg_file_we := true.B
io.reg_file_we := true.B // Write to regfile
opR(funct3, funct7, io);
}
// J instructions
is(OpCode.JAL) {
io.alu_opcode := AluOpCode.Add
io.reg_file_we := true.B // Write to regfile
io.mux_rega_pc := false.B // Send PC to ALU A
io.mux_regb_imm := false.B; // Send imm to ALU B
io.is_jump := true.B
io.mux_incrpc4_imm := false.B; // Send the immediate in PC
io.mux_regpc_executepc := false.B; // Add the immediate to the previous PC
io.optype := OpType.J
}
}

View File

@@ -20,6 +20,14 @@ class ImmediateDecoder extends Module {
val imm_u = Cat(io.instruction(31, 12), 0.U(12.W));
val imm_i = Cat(Fill(20, io.instruction(31)), io.instruction(31, 20));
val imm_ir = io.instruction(24, 20);
val imm_j = Cat(
Fill(11, io.instruction(31)),
io.instruction(31),
io.instruction(19, 12),
io.instruction(20),
io.instruction(30, 21),
0.U
);
switch(io.op_type) {
is(OpType.U) {
@@ -31,5 +39,8 @@ class ImmediateDecoder extends Module {
is(OpType.IR) {
io.immediate := imm_ir
}
is(OpType.J) {
io.immediate := imm_j
}
}
}

View File

@@ -12,32 +12,38 @@ class Rv32i(sim: Boolean = true) extends Module {
val reg_pc = RegInit(0.U(32.W));
val reg_file = Module(new RegFile(sim));
val instruction = io.ibus.rdata;
reg_file.io.rd_data := 0.U;
io.x31 := reg_file.io.x31
if (sim) {
io.valid_x31.get := reg_file.io.valid_x31.get && Delay.Delay(
!reset.asBool,
1,
false.B
)
io.valid_x31.get := reg_file.io.valid_x31.get
}
val alu = Module(new Alu());
val immediate_decoder = Module(new ImmediateDecoder());
val control_unit = Module(new ControlUnit());
// PC delayed to execute stage for auipc op
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);
// True if the instruction in the execute stage is a jump
val is_jump = Delay.Delay(control_unit.io.is_jump, 1, false.B);
val instruction = Mux(is_jump, 0b00000000000000000000000000010011.U, io.ibus.rdata);
immediate_decoder.io.instruction := instruction
immediate_decoder.io.op_type := control_unit.io.optype
alu.io.opcode := control_unit.io.alu_opcode;
reg_file.io.we := control_unit.io.reg_file_we
// Increment PC each clock
reg_pc := reg_pc + 4.U;
// PC delayed to execute stage for auipc op
val execute_pc = Delay.Delay(reg_pc, 1, 0.U);
reg_pc := Mux(
control_unit.io.mux_regpc_executepc,
reg_pc,
execute_pc
) + Mux(
control_unit.io.mux_incrpc4_imm,
4.U,
immediate_decoder.io.immediate
);
// Fetch instruction
io.ibus.en := true.B;

View File

@@ -24,7 +24,7 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
// clock et reset sont les signaux implicites
clkg.io.clk_in1 := clock
clkg.io.reset := reset
val rst = (reset.asBool || !clkg.io.locked).asAsyncReset
val rst = reset.asBool || !clkg.io.locked
// Ces deux IPs doivent tourner à 125 MHz
val vmem = Module(new IDMem(sim, 17))
@@ -34,7 +34,7 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
vgad.io.clk := clkg.io.clk_out2 // Clock pixel
// Expose core for testing usage
val core = withClockAndReset(clkg.io.clk_out1, rst) {
withClockAndReset(clkg.io.clk_out1, rst) {
val interconnect = Module(new BusInterconnect)
val core = Module(new Rv32i(sim))
val dmem = Module(new IDMem(sim, 16, file))
@@ -70,7 +70,5 @@ class ZzTop(file: String = "", sim: Boolean = true) extends Module {
io.r := vgad.io.r
io.g := vgad.io.g
io.b := vgad.io.b
core
}
}