1
0
Megan Wachs 03be9aba67 Use HomogenousBag to handle lists of peripherals
Previously we had to do weird things to make non-homogenous
lists of items (e.g. PWM Peripherals where ncmp were different from one to
the other) into a vector. But now Chisel supports a Record type,
and we use the HomogenousBag utility to do this more naturally.
This also deletes all the cruft which was introduced to get
around the limitation which doesn't exist anymore.
2017-02-16 17:52:24 -08:00

73 lines
2.8 KiB
Scala

// See LICENSE for license details.
package sifive.blocks.devices.pwm
import Chisel._
import Chisel.ImplicitConversions._
import config._
import regmapper._
import rocketchip.PeripheryBusConfig
import uncore.tilelink2._
import util._
import sifive.blocks.util.GenericTimer
// Core PWM Functionality & Register Interface
class PWM(val ncmp: Int = 4, val cmpWidth: Int = 16)(implicit p: Parameters) extends GenericTimer {
protected def countWidth = ((1 << scaleWidth) - 1) + cmpWidth
protected lazy val countAlways = RegEnable(io.regs.cfg.write.bits(12), Bool(false), io.regs.cfg.write.valid && unlocked)
protected lazy val feed = count.carryOut(scale + UInt(cmpWidth))
protected lazy val countEn = Wire(Bool())
override protected lazy val oneShot = RegEnable(io.regs.cfg.write.bits(13) && !countReset, Bool(false), (io.regs.cfg.write.valid && unlocked) || countReset)
override protected lazy val center = RegEnable(io.regs.cfg.write.bits(16 + ncmp - 1, 16), io.regs.cfg.write.valid && unlocked)
override protected lazy val gang = RegEnable(io.regs.cfg.write.bits(24 + ncmp - 1, 24), io.regs.cfg.write.valid && unlocked)
override protected lazy val deglitch = RegEnable(io.regs.cfg.write.bits(10), io.regs.cfg.write.valid && unlocked)(0)
override protected lazy val sticky = RegEnable(io.regs.cfg.write.bits(8), io.regs.cfg.write.valid && unlocked)(0)
override protected lazy val ip = {
val doSticky = Reg(next = (deglitch && !countReset) || sticky)
val sel = ((0 until ncmp).map(i => s(cmpWidth-1) && center(i))).asUInt
val reg = Reg(UInt(width = ncmp))
reg := (sel & elapsed.asUInt) | (~sel & (elapsed.asUInt | (Fill(ncmp, doSticky) & reg)))
when (io.regs.cfg.write.valid && unlocked) { reg := io.regs.cfg.write.bits(28 + ncmp - 1, 28) }
reg
}
lazy val io = new GenericTimerIO {
val gpio = Vec(ncmp, Bool()).asOutput
}
io.gpio := io.gpio.fromBits(ip & ~(gang & Cat(ip(0), ip >> 1)))
countEn := countAlways || oneShot
}
case class PWMConfig(
address: BigInt,
size: Int = 0x1000,
regBytes: Int = 4,
ncmp: Int = 4,
cmpWidth: Int = 16)
trait HasPWMParameters {
implicit val p: Parameters
val params: PWMConfig
val c = params
}
trait PWMBundle extends Bundle with HasPWMParameters {
val gpio = Vec(c.ncmp, Bool()).asOutput
}
trait PWMModule extends Module with HasRegMap with HasPWMParameters {
val io: PWMBundle
val pwm = Module(new PWM(c.ncmp, c.cmpWidth))
interrupts := pwm.io.ip
io.gpio := pwm.io.gpio
regmap((GenericTimer.timerRegMap(pwm, 0, c.regBytes)):_*)
}
class TLPWM(c: PWMConfig)(implicit p: Parameters)
extends TLRegisterRouter(c.address, interrupts = c.ncmp, size = c.size, beatBytes = p(PeripheryBusConfig).beatBytes)(
new TLRegBundle(c, _) with PWMBundle)(
new TLRegModule(c, _, _) with PWMModule)