CarrySelectCompoundAdder constructor
Constructs a CarrySelectCompoundAdder.
carryIn
is a carry Logic into the CarrySelectCompoundAdderadderGen
provides an adder Function which must supply optionalcarryIn
andsubtractIn
Logic controls.subtractIn
This option is used by the CarrySelectOnesComplementCompoundAdder and should not be used directly as it requires ones-complement behavior fromadderGen
.widthGen
is the splitting function for creating the different adder blocks.
Implementation
CarrySelectCompoundAdder(
super.a,
super.b, {
Logic? subtractIn,
super.carryIn,
Adder Function(Logic a, Logic b,
{Logic? carryIn, Logic? subtractIn, String name})
adderGen = _defaultBlockAdder,
List<int> Function(int) widthGen = splitSelectAdderAlgorithmSingleBlock,
String? definitionName,
super.name = 'cs_compound_adder',
}) : super(
definitionName: definitionName ??
'CarrySelectCompoundAdder_${adderGen(a, b).definitionName}') {
subtractIn = (subtractIn != null)
? addInput('subtractIn', subtractIn, width: subtractIn.width)
: null;
// output bits lists
final sumList0 = <Logic>[];
final sumList1 = <Logic>[];
// carryout of previous adder block
// for sum and sum+1
Logic? carry0;
Logic? carry1;
// Get size of each 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 adder block
final blockWidth = adderSplit[i];
if (blockWidth <= 0) {
throw RohdHclException('non-positive adder block size.');
}
if (blockWidth + blockStartIdx > a.width) {
throw RohdHclException('oversized 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 sub adders for 0 and 1 carryin values
final fullAdder0 = adderGen(blockA, blockB,
subtractIn: subtractIn, carryIn: Const(0), name: 'block0_$i');
final fullAdder1 = adderGen(blockA, blockB,
subtractIn: subtractIn, 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();
sumP1 <= sumList1.rswizzle();
}