Proposal: Radix-4 serial divider to halve worst-case division latency

Placeholder Sihun
2026-03-27T17:09:47Z

Hello!

I'm an undergraduate student who has been exploring the CVA6 divider while working on an FPGA project. I noticed that `core/serdiv.sv` uses a radix-2 (1-bit/cycle) serial divider and thought it could be interesting to try a radix-4 approach. I went ahead and implemented it, and wanted to share the results in case it's useful.

## What I changed

I modified `core/serdiv.sv` to process 2 quotient bits per cycle instead of 1, which halves the worst-case division latency (64→32 cycles for RV64, 32→16 for RV32). The module interface and FSM structure are fully preserved — it's a drop-in replacement.

Key details:
- Two quotient bits computed per cycle using an additional comparator (`b_half_r4 = op_b_q >> 1`)
- When `div_shift` is even, a single radix-2 half-step on the first cycle to re-align
- All special-case handling (div-by-zero, signed overflow, etc.) unchanged
- Area overhead: +2 comparators and one shifted-B path

## Benchmark results

I ran the full `benchmark.sh` suite on `cv64a6_imafdc_sv39` (Verilator 5.008):

| Benchmark | Master (cycles) | Radix-4 (cycles) | Delta |
|---|---|---|---|
| dhrystone | 229,645 | 229,112 | −533 (−0.23%) |
| mm | 315,478 | 315,355 | −123 (−0.04%) |
| mt-matmul | 40,118 | 40,091 | −27 (−0.07%) |
| mt-vvadd | 55,504 | 55,439 | −65 (−0.12%) |
| multiply | 33,215 | 33,215 | 0% |
| median | 12,198 | 12,198 | 0% |
| qsort | 221,842 | 221,842 | 0% |
| rsort | 174,914 | 174,914 | 0% |
| spmv | 57,523 | 57,523 | 0% |
| towers | 12,650 | 12,650 | 0% |
| vvadd | 7,914 | 7,914 | 0% |

The improvement is small on these benchmarks since they aren't division-heavy, but the per-operation worst-case latency is halved.

## Regression results

Full regression (590 tests): **589 PASS, 1 FAIL**. The only failure is `csr_test` (`tohost = 1337`), which also fails on unmodified master — seems pre-existing. All 8 `rv64um` div/rem tests pass (both p-mode and v-mode).

## Questions

1. Should this be parameterized (radix-2 vs. radix-4 selectable) or is a straight replacement okay?
2. Is the `csr_test` failure a known issue?
3. Any division-heavy benchmarks you'd recommend for better measurement?

I have a draft PR ready and happy to reformat with verible / rebase / adjust based on feedback. Thanks for taking a look!