Skip to content

Commit

Permalink
[MultiCycleDivider] Patch of prior bug fix to properly support unsign…
Browse files Browse the repository at this point in the history
…ed division (#141)

* Fixing bug in Divider and updating tests and documentation accordingly.
  • Loading branch information
kimmeljo authored Nov 21, 2024
1 parent d8d72f8 commit bf4106e
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 9 deletions.
10 changes: 7 additions & 3 deletions doc/components/divider.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# Divider

ROHD HCL provides an integer divider module to get the dividend of numerator and denominator operands. The divider implementation is not pipelined and has a maximum latency of the bit width of the operands.
ROHD HCL provides an integer divider module to get the quotient and the remainder of dividend and divisor operands. The divider implementation is not pipelined and has a minimum latency of 3 cycles. The maximum latency is dependent on the width of the operands (upper bound of `O(WIDTH**2)`). Note that latency increases exponentially as the absolute difference between the dividend and the divisor increases (worst case: largest possible dividend and divisor of 1).

## Interface

The inputs to the divider module are:

* `clock` => clock for synchronous logic
* `reset` => reset for synchronous logic (active high)
* `reset` => reset for synchronous logic (active high, synchronous to `clock`)
* `dividend` => the numerator operand
* `divisor` => the denominator operand
* `isSigned` => should the operands of the division be treated as signed integers
Expand All @@ -30,7 +30,7 @@ To initiate a new request, it is expected that the requestor drive `validIn` to

When the division is complete, the module will assert the `validOut` signal along with the numerical values of `quotient` and `remainder` representing the division result and the signal `divZero` to indicate whether or not a division by zero occurred. The module will hold these signal values until `readyOut` is driven high by the integrating environment. The integrating environment must assume that `quotient` and `remainder` are meaningless if `divZero` is asserted.

### Mathematical Properties
## Mathematical Properties

For the division, implicit rounding towards 0 is always performed. I.e., a negative quotient will always be rounded up if the dividend is not evenly divisible by the divisor. Note that this behavior is not uniform across all programming languages (for example, Python rounds towards negative infinity).

Expand Down Expand Up @@ -65,3 +65,7 @@ if (divIntf.validOut.value.toBool()) {
}
```

## Future Considerations

In the future, an optimization might be added in which the `remainder` output is optional and controlled by a build time constructor parameter. If the remainder does not need to be computed, the implementation's upper bound latency can be significantly improved (`O(WIDTH**2)` => `O(WIDTH)`).
7 changes: 2 additions & 5 deletions lib/src/arithmetic/divider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -258,10 +258,7 @@ class MultiCycleDivider extends Module {
orElse: [
tmpDifference < (aBuf - tmpShift),
// move to accumulate if tmpDifference <= 0
If(
~tmpShift.or() |
tmpDifference[dataWidth - 1] |
~tmpDifference.or(),
If(~tmpShift.or() | tmpDifference[-1] | ~tmpDifference.or(),
then: [nextState < _MultiCycleDividerState.accumulate],
orElse: [nextState < _MultiCycleDividerState.process])
])
Expand Down Expand Up @@ -375,7 +372,7 @@ class MultiCycleDivider extends Module {
currentState.eq(_MultiCycleDividerState
.process), // didn't exceed a_buf, so count as success
[
If(~tmpDifference[dataWidth - 1], then: [
If(~tmpDifference[-1], then: [
lastSuccess <
(Const(1, width: dataWidth + 1) <<
currIndex), // capture 2^i
Expand Down
9 changes: 8 additions & 1 deletion test/arithmetic/divider_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,14 @@ class MultiCycleDividerBasicSequence extends Sequence {
mDivisor: 0,
mValidIn: true,
mIsSigned: true,
mReadyOut: true)); // divide by 0
mReadyOut: true)) // divide by 0
// long latency division
..add(MultiCycleDividerInputSeqItem(
mDividend: 0xffffffec,
mDivisor: 0x6,
mValidIn: true,
mIsSigned: false,
mReadyOut: true));
}
}

Expand Down

0 comments on commit bf4106e

Please sign in to comment.