CarrySelectCompoundAdder constructor

CarrySelectCompoundAdder(
  1. Logic a,
  2. Logic b, {
  3. String name = 'cs_compound_adder',
  4. List<int> widthGen(
    1. int
    ) = splitSelectAdderAlgorithmSingleBlock,
})

Constructs a CarrySelectCompoundAdder.

Implementation

CarrySelectCompoundAdder(super.a, super.b,
    {super.name = 'cs_compound_adder',
    List<int> Function(int) widthGen =
        splitSelectAdderAlgorithmSingleBlock}) {
  // output bits lists
  final sumList0 = <Logic>[];
  final sumList1 = <Logic>[];
  // carryout of previous ripple-carry adder block
  // for sum and sum+1
  Logic? carry0;
  Logic? carry1;
  // Get size of each ripple-carry adder block
  final adderSplit = widthGen(a.width);
  // 1st output bit index of each block
  var blockStartIdx = 0;
  for (var i = 0; i < adderSplit.length; ++i) {
    // input width of current ripple-carry adder block
    final blockWidth = adderSplit[i];
    if (blockWidth <= 0) {
      throw RohdHclException('non-positive ripple-carry adder block size.');
    }
    if (blockWidth + blockStartIdx > a.width) {
      throw RohdHclException('oversized ripple-carry adders sequence.');
    }
    final blockA = Logic(name: 'block_${i}_a', width: blockWidth);
    final blockB = Logic(name: 'block_${i}_b', width: blockWidth);
    blockA <= a.getRange(blockStartIdx, blockStartIdx + blockWidth);
    blockB <= b.getRange(blockStartIdx, blockStartIdx + blockWidth);
    // Build ripple-carry adders for 0 and 1 carryin values
    final fullAdder0 = RippleCarryAdder(blockA, blockB,
        carryIn: Const(0), name: 'block0_$i');
    final fullAdder1 = RippleCarryAdder(blockA, blockB,
        carryIn: Const(1), name: 'block1_$i');
    for (var bitIdx = 0; bitIdx < blockWidth; ++bitIdx) {
      if (i == 0) {
        // connect directly to respective sum output bit
        sumList0.add(fullAdder0.sum[bitIdx]);
        sumList1.add(fullAdder1.sum[bitIdx]);
      } else {
        final bitOut0 = Logic(name: 'bit0_${blockStartIdx + bitIdx}');
        final bitOut1 = Logic(name: 'bit1_${blockStartIdx + bitIdx}');
        // select adder output from adder matching carryin value
        bitOut0 <=
            mux(carry0!, fullAdder1.sum[bitIdx], fullAdder0.sum[bitIdx]);
        bitOut1 <=
            mux(carry1!, fullAdder1.sum[bitIdx], fullAdder0.sum[bitIdx]);
        sumList0.add(bitOut0);
        sumList1.add(bitOut1);
      }
    }
    if (i == 0) {
      // select carryout as a last bit of the adder
      carry0 = fullAdder0.sum[blockWidth];
      carry1 = fullAdder1.sum[blockWidth];
    } else {
      // select carryout depending on carryin (carryout of the previous block)
      carry0 = mux(
          carry0!, fullAdder1.sum[blockWidth], fullAdder0.sum[blockWidth]);
      carry1 = mux(
          carry1!, fullAdder1.sum[blockWidth], fullAdder0.sum[blockWidth]);
    }
    blockStartIdx += blockWidth;
  }

  // append carryout bit
  sumList0.add(carry0!);
  sumList1.add(carry1!);

  sum <= sumList0.rswizzle();
  sum1 <= sumList1.rswizzle();
}