2016-11-28 01:16:37 +01:00
|
|
|
// See LICENSE.Berkeley for license details.
|
|
|
|
// See LICENSE.SiFive for license details.
|
|
|
|
|
2017-07-07 19:48:16 +02:00
|
|
|
package freechips.rocketchip.util
|
2016-09-14 05:29:42 +02:00
|
|
|
|
|
|
|
import Chisel._
|
2016-09-28 06:27:07 +02:00
|
|
|
import scala.math.max
|
2016-09-14 05:29:42 +02:00
|
|
|
|
|
|
|
// Produces 0-width value when counting to 1
|
|
|
|
class ZCounter(val n: Int) {
|
|
|
|
val value = Reg(init=UInt(0, log2Ceil(n)))
|
|
|
|
def inc(): Bool = {
|
|
|
|
if (n == 1) Bool(true)
|
|
|
|
else {
|
|
|
|
val wrap = value === UInt(n-1)
|
|
|
|
value := Mux(Bool(!isPow2(n)) && wrap, UInt(0), value + UInt(1))
|
|
|
|
wrap
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object ZCounter {
|
|
|
|
def apply(n: Int) = new ZCounter(n)
|
|
|
|
def apply(cond: Bool, n: Int): (UInt, Bool) = {
|
|
|
|
val c = new ZCounter(n)
|
|
|
|
var wrap: Bool = null
|
|
|
|
when (cond) { wrap = c.inc() }
|
|
|
|
(c.value, cond && wrap)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
object TwoWayCounter {
|
|
|
|
def apply(up: Bool, down: Bool, max: Int): UInt = {
|
|
|
|
val cnt = Reg(init = UInt(0, log2Up(max+1)))
|
|
|
|
when (up && !down) { cnt := cnt + UInt(1) }
|
|
|
|
when (down && !up) { cnt := cnt - UInt(1) }
|
|
|
|
cnt
|
|
|
|
}
|
|
|
|
}
|
2016-09-28 06:27:07 +02:00
|
|
|
|
|
|
|
// a counter that clock gates most of its MSBs using the LSB carry-out
|
|
|
|
case class WideCounter(width: Int, inc: UInt = UInt(1), reset: Boolean = true)
|
|
|
|
{
|
|
|
|
private val isWide = width > 2*inc.getWidth
|
|
|
|
private val smallWidth = if (isWide) inc.getWidth max log2Up(width) else width
|
|
|
|
private val small = if (reset) Reg(init=UInt(0, smallWidth)) else Reg(UInt(width = smallWidth))
|
|
|
|
private val nextSmall = small +& inc
|
|
|
|
small := nextSmall
|
|
|
|
|
|
|
|
private val large = if (isWide) {
|
|
|
|
val r = if (reset) Reg(init=UInt(0, width - smallWidth)) else Reg(UInt(width = width - smallWidth))
|
2017-03-09 09:28:19 +01:00
|
|
|
when (nextSmall(smallWidth)) { r := r + UInt(1) }
|
2016-09-28 06:27:07 +02:00
|
|
|
r
|
|
|
|
} else null
|
|
|
|
|
|
|
|
val value = if (isWide) Cat(large, small) else small
|
|
|
|
lazy val carryOut = {
|
|
|
|
val lo = (small ^ nextSmall) >> 1
|
|
|
|
if (!isWide) lo else {
|
|
|
|
val hi = Mux(nextSmall(smallWidth), large ^ (large +& UInt(1)), UInt(0)) >> 1
|
|
|
|
Cat(hi, lo)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
def := (x: UInt) = {
|
|
|
|
small := x
|
|
|
|
if (isWide) large := x >> smallWidth
|
|
|
|
}
|
|
|
|
}
|