Counter constructor
Creates a counter that increments according to the provided interfaces
.
The width
can be either explicitly provided or inferred from other
values such as a maxValue
, minValue
, or resetValue
that contain
width information (e.g. a LogicValue), or by making it large enough to
fit maxValue
, or by inspecting widths of interfaces
. There must be
enough information provided to determine the width
.
If no maxValue
is provided, one will be inferred by the maximum that can
fit inside of the width
.
The restart
input can be used to restart the counter to a new value, but
also continue to increment in that same cycle. This is distinct from
reset
which will reset the counter, holding the count at resetValue
.
If saturates
is true
, then it will saturate at the maxValue
and
minValue
. If false
, will wrap around (overflow/underflow) at the
maxValue
and minValue
. The equalsMax, equalsMin, overflowed,
and underflowed outputs can be used to determine if the sum is at the
maximum, minimum, (would have) overflowed, or (would have) underflowed,
respectively.
Implementation
Counter(
super.interfaces, {
required Logic clk,
required Logic reset,
Logic? restart,
dynamic resetValue = 0,
super.maxValue,
super.minValue = 0,
super.width,
super.saturates,
super.name = 'counter',
}) : super(initialValue: resetValue) {
clk = addInput('clk', clk);
reset = addInput('reset', reset);
if (restart != null) {
restart = addInput('restart', restart);
}
addOutput('count', width: width);
final sum = Sum(
interfaces,
initialValue:
restart != null ? mux(restart, initialValueLogic, count) : count,
maxValue: maxValueLogic,
minValue: minValueLogic,
width: width,
saturates: saturates,
);
count <=
flop(
clk,
sum.sum,
reset: reset,
resetValue: initialValueLogic,
);
// need to flop these since value is flopped
overflowed <= flop(clk, sum.overflowed, reset: reset);
underflowed <= flop(clk, sum.underflowed, reset: reset);
equalsMax <= count.eq(maxValueLogic);
equalsMin <= count.eq(minValueLogic);
}