SignMagnitudeAdder constructor

SignMagnitudeAdder(
  1. Logic aSign,
  2. Logic a,
  3. Logic bSign,
  4. Logic b, {
  5. Adder adderGen(
    1. Logic a,
    2. Logic b, {
    3. Logic? carryIn,
    }) = NativeAdder.new,
  6. bool largestMagnitudeFirst = false,
  7. bool generateEndAroundCarry = false,
  8. String name = 'sign_magnitude_adder',
  9. bool reserveName = false,
  10. bool reserveDefinitionName = false,
  11. String? definitionName,
})

SignMagnitudeAdder constructor with an adder functor adderGen.

Inputs are (sign, magnitude) pairs: (aSign, a) and (bSign, b). If the caller can guarantee that the larger magnitude value is provided first in a, then they can set largestMagnitudeFirst to true to avoid adding a comparator. Without the comparator, the sign may be wrong, but magnitude will be correct.

  • If generateEndAroundCarry is true, then the end-around carry is not performed and is provided as output endAroundCarry. If generateEndAroundCarry is false, extra hardware takes care of adding the end-around carry to sum.
  • generateEndAroundCarry avoids extra hardware to add the '1' in an end-around carry during subtraction. For subtractions that remain positive the endAroundCarry will hold that final +1 that needs to be added. For subtractions that go negative, the endAroundCarry will be '0'.

Implementation

// TODO(desmonddak): this adder may need a carry-in for rounding
SignMagnitudeAdder(super.aSign, super.a, super.bSign, super.b,
    {Adder Function(Logic a, Logic b, {Logic? carryIn}) adderGen =
        NativeAdder.new,
    this.largestMagnitudeFirst = false,
    bool generateEndAroundCarry = false,
    super.name = 'sign_magnitude_adder',
    super.reserveName,
    super.reserveDefinitionName,
    String? definitionName})
    : super(
          definitionName:
              definitionName ?? 'SignMagnitudeAdder_W${a.width}') {
  if (generateEndAroundCarry) {
    addOutput('endAroundCarry');
  }

  if (!largestMagnitudeFirst) {
    final bLarger = a.lt(b) | (a.eq(b) & bSign.gt(aSign));
    _sign <= mux(bLarger, bSign, aSign);
  } else {
    _sign <= aSign;
  }

  final sub = aSign ^ bSign;

  final adder = OnesComplementAdder(
      mux(_sign & sub, ~a, a), mux(_sign & sub, ~b, b),
      generateEndAroundCarry: largestMagnitudeFirst & generateEndAroundCarry,
      subtractIn: sub,
      adderGen: adderGen);
  sum <= adder.sum;
  if (generateEndAroundCarry) {
    endAroundCarry! <=
        (largestMagnitudeFirst ? adder.endAroundCarry! : Const(0));
  }
}