Splits multiplication in two cycles for 40MHz

This commit is contained in:
2025-11-20 18:10:23 +01:00
parent ed04c13a76
commit baea321958
3 changed files with 75 additions and 134 deletions

View File

@@ -80,7 +80,21 @@ class Alu extends Module {
}
// Multiplication
val multiplication_res = op_a * op_b // Mul non signée
// Pipeline multiplication to trim critical path
val multiplication_res = RegNext(op_a * op_b) // Mul non signée
switch(io.opcode) {
is(Mul, Mulhsu, Mulh, Mulhu) {
when(!in_computation) {
in_computation := true.B
}.elsewhen(in_computation) {
in_computation := false.B
io.should_stop_stall := true.B
}
}
}
val multiplication_low =
Mux(io.word_mode, multiplication_res(31, 0), multiplication_res(63, 0))
val multiplication_high =
@@ -123,54 +137,54 @@ class Alu extends Module {
out := multiplication_high;
}
is(Div) {
when(op_b === 0.U) {
div_by_zero()
}.elsewhen(op_a_sign ^ op_b_sign) {
out := Utils.two_complement(divider.io.quotient, io.word_mode)
}.otherwise {
out := divider.io.quotient
}
}
is(Divu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
div_by_zero()
}.otherwise { out := divider.io.quotient; }
}
is(Rem) {
when(op_b === 0.U) {
out := op_a
}.elsewhen(
op_a_sign && !op_b_sign && divider.io.remainder =/= 0.U
) {
out := op_b - divider.io.remainder
}.elsewhen(
!op_a_sign && op_b_sign && divider.io.remainder =/= 0.U
) {
out := Utils.two_complement(
Utils.two_complement(op_b) - divider.io.remainder,
io.word_mode
)
}.elsewhen(op_a_sign && op_b_sign) {
out := Utils.two_complement(divider.io.remainder, io.word_mode)
}.otherwise {
out := divider.io.remainder
}
}
is(Remu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
out := op_a
}.otherwise {
out := divider.io.remainder
}
}
is(Div) {
when(op_b === 0.U) {
div_by_zero()
}.elsewhen(op_a_sign ^ op_b_sign) {
out := Utils.two_complement(divider.io.quotient, io.word_mode)
}.otherwise {
out := divider.io.quotient
}
}
is(Divu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
div_by_zero()
}.otherwise { out := divider.io.quotient; }
}
is(Rem) {
when(op_b === 0.U) {
out := op_a
}.elsewhen(
op_a_sign && !op_b_sign && divider.io.remainder =/= 0.U
) {
out := op_b - divider.io.remainder
}.elsewhen(
!op_a_sign && op_b_sign && divider.io.remainder =/= 0.U
) {
out := Utils.two_complement(
Utils.two_complement(op_b) - divider.io.remainder,
io.word_mode
)
}.elsewhen(op_a_sign && op_b_sign) {
out := Utils.two_complement(divider.io.remainder, io.word_mode)
}.otherwise {
out := divider.io.remainder
}
}
is(Remu) {
divider.io.dividend := op_a
divider.io.divisor := op_b
when(op_b === 0.U) {
out := op_a
}.otherwise {
out := divider.io.remainder
}
}
is(And) {
out := op_a & op_b;
@@ -231,18 +245,17 @@ class Alu extends Module {
}
}
switch(io.opcode) {
is(Div, Divu, Rem, Remu) {
when(!in_computation) {
divider.io.start := true.B
in_computation := true.B
}.elsewhen(divider.io.ready) {
io.should_stop_stall := true.B
in_computation := false.B
}
}
}
switch(io.opcode) {
is(Div, Divu, Rem, Remu) {
when(!in_computation) {
divider.io.start := true.B
in_computation := true.B
}.elsewhen(divider.io.ready) {
io.should_stop_stall := true.B
in_computation := false.B
}
}
}
// Special overflow cases for Div and Rem
when(

View File

@@ -23,6 +23,7 @@ object OpM {
}
io.reg_file_we := true.B // Write to regfile
io.should_stall := true.B
switch(funct3) {
is(Funct3.MUL) {
io.alu_opcode := AluOpCode.Mul
@@ -38,19 +39,15 @@ object OpM {
}
is(Funct3.DIV) {
io.alu_opcode := AluOpCode.Div
io.should_stall := true.B
}
is(Funct3.DIVU) {
io.alu_opcode := AluOpCode.Divu
io.should_stall := true.B
}
is(Funct3.REM) {
io.alu_opcode := AluOpCode.Rem
io.should_stall := true.B
}
is(Funct3.REMU) {
io.alu_opcode := AluOpCode.Remu
io.should_stall := true.B
}
}
}

View File

@@ -1,69 +0,0 @@
+====================+====================+==============================+
| Launch Setup Clock | Launch Hold Clock | Pin |
+====================+====================+==============================+
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[58]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[52]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[32]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[61]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[54]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[17]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[42]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[11]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[12]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[56]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[8]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[36]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[19]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[60]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[48]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[51]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[24]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[41]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[53]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[50]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[57]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[37]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[1]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[62]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[29]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[46]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[38]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[10]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[14]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[63]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[28]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[9]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | clnt/clintRegValue_reg[49]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[58]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[61]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[60]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[57]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[56]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[52]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[53]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[49]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[48]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[45]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[44]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[41]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[40]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[37]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[36]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[33]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[32]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[29]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[28]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[25]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[24]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[21]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[20]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[17]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[16]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[13]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[12]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[9]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[8]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[5]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[4]/D |
| clk_out1_clk_wiz_0 | clk_out1_clk_wiz_0 | core/reg_pc_reg[1]/D |
+--------------------+--------------------+------------------------------+