Skip to content

Commit

Permalink
Allow counters to be reset manually (#1527)
Browse files Browse the repository at this point in the history
Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
  • Loading branch information
nullobject and mergify[bot] authored Aug 13, 2020
1 parent a66d2d1 commit d9903de
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 3 deletions.
18 changes: 15 additions & 3 deletions src/main/scala/chisel3/util/Counter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class Counter private (r: Range, oldN: Option[Int] = None) {
def this(n: Int) { this(0 until math.max(1, n), Some(n)) }

/** The current value of the counter. */
val value = if (r.length > 1) RegInit(r.head.U(width.W)) else r.head.U
val value = if (r.length > 1) RegInit(r.head.U(width.W)) else WireInit(r.head.U)

/** The range of the counter values. */
def range: Range = r
Expand Down Expand Up @@ -91,6 +91,11 @@ class Counter private (r: Range, oldN: Option[Int] = None) {
true.B
}
}

/** Resets the counter to its initial value */
def reset(): Unit = {
value := r.head.U
}
}

object Counter
Expand Down Expand Up @@ -118,14 +123,21 @@ object Counter
*
* @param r the range of counter values
* @param enable controls whether the counter increments this cycle
* @param reset resets the counter to its initial value during this cycle
* @return tuple of the counter value and whether the counter will wrap (the value is at
* maximum and the condition is true).
*/
@chiselName
def apply(r: Range, enable: Bool = true.B): (UInt, Bool) = {
def apply(r: Range, enable: Bool = true.B, reset: Bool = false.B): (UInt, Bool) = {
val c = new Counter(r)
val wrap = WireInit(false.B)
when (enable) { wrap := c.inc() }

when(reset) {
c.reset()
}.elsewhen(enable) {
wrap := c.inc()
}

(c.value, wrap)
}
}
17 changes: 17 additions & 0 deletions src/test/scala/chiselTests/Counter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ class EnableTester(seed: Int) extends BasicTester {
}
}

class ResetTester(n: Int) extends BasicTester {
val triggerReset = WireInit(false.B)
val wasReset = RegNext(triggerReset)
val (value, _) = Counter(0 until 8, reset = triggerReset)

triggerReset := value === (n-1).U

when(wasReset) {
assert(value === 0.U)
stop()
}
}

class WrapTester(max: Int) extends BasicTester {
val (cnt, wrap) = Counter(true.B, max)
when(wrap) {
Expand Down Expand Up @@ -61,6 +74,10 @@ class CounterSpec extends ChiselPropSpec {
forAll(safeUInts) { (seed: Int) => whenever(seed >= 0) { assertTesterPasses{ new EnableTester(seed) } } }
}

property("Counter can be reset") {
forAll(smallPosInts) { (seed: Int) => assertTesterPasses{ new ResetTester(seed) } }
}

property("Counter should wrap") {
forAll(smallPosInts) { (max: Int) => assertTesterPasses{ new WrapTester(max) } }
}
Expand Down

0 comments on commit d9903de

Please sign in to comment.