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. 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;
}