CarrySelectCompoundAdder constructor
Constructs a CarrySelectCompoundAdder.
carryInis a carry Logic into the CarrySelectCompoundAdderadderGenprovides an adder Function which must supply optionalcarryInandsubtractInLogic controls.subtractInThis option is used by the CarrySelectOnesComplementCompoundAdder and should not be used directly as it requires ones-complement behavior fromadderGen.widthGenis the splitting Function for creating the different adder blocks. Decreasing the split width will increase speed but also increase area.
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,
super.name = 'cs_compound_adder',
super.reserveName,
super.reserveDefinitionName,
String? definitionName,
}) : super(
definitionName: definitionName ??
'CarrySelectCompoundAdder_${adderGen(a, b).definitionName}') {
subtractIn = (subtractIn != null)
? addInput('subtractIn', subtractIn, width: subtractIn.width)
: null;
// output bits lists
final sumList0F = <Logic>[];
final sumList1F = <Logic>[];
// carryout of previous adder block
// for sum and sum+1
Logic carry0 = Const(0);
Logic carry1 = Const(0);
// 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];
final sum0Ary = Logic(width: blockWidth);
final sum1Ary = Logic(width: blockWidth);
if (blockWidth <= 0) {
throw RohdHclException('non-positive adder block size.');
}
final blockEnd = blockStartIdx + blockWidth;
if (blockEnd > a.width) {
throw RohdHclException('oversized adders sequence.');
}
// Build sub adders for carryIn=0 and carryIn=1
final fullAdder0 = adderGen(a.getRange(blockStartIdx, blockEnd),
b.getRange(blockStartIdx, blockEnd),
subtractIn: subtractIn, carryIn: Const(0), name: 'block0_$i');
final fullAdder1 = adderGen(a.getRange(blockStartIdx, blockEnd),
b.getRange(blockStartIdx, blockEnd),
subtractIn: subtractIn, carryIn: Const(1), name: 'block1_$i');
sum0Ary <=
((i == 0)
? fullAdder0.sum
: mux(carry0, fullAdder1.sum, fullAdder0.sum))
.slice(0, blockWidth - 1)
.named('block_${i}_sum0Ary');
sum1Ary <=
((i == 0)
? fullAdder1.sum
: mux(carry1, fullAdder1.sum, fullAdder0.sum))
.slice(0, blockWidth - 1)
.named('block_${i}_sum1Ary');
sumList0F.add(sum0Ary);
sumList1F.add(sum1Ary);
if (i == 0) {
// select carryout as a last bit of the adder
carry0 = fullAdder0.sum[blockWidth].named('block_${i}_adder0Msb');
carry1 = fullAdder1.sum[blockWidth].named('block_${i}_adder1Msb');
} else {
// select carryout depending on carryin (carryout of the previous block)
carry0 =
mux(carry0, fullAdder1.sum[blockWidth], fullAdder0.sum[blockWidth])
.named('block_${i}_carry0');
carry1 =
mux(carry1, fullAdder1.sum[blockWidth], fullAdder0.sum[blockWidth])
.named('block_${i}_carry1');
}
blockStartIdx += blockWidth;
}
sum <= [sumList0F.swizzle(), carry0].swizzle().named('sum_inner').reversed;
sumP1 <=
[sumList1F.swizzle(), carry1].swizzle().named('sumP1_inner').reversed;
}