83 lines
3.0 KiB
Scala
83 lines
3.0 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)
|
||
|
{
|
||
|
val bc = new PWMBundleConfig(ncmp)
|
||
|
}
|
||
|
|
||
|
case class PWMBundleConfig(
|
||
|
ncmp: Int)
|
||
|
{
|
||
|
def union(that: PWMBundleConfig): PWMBundleConfig =
|
||
|
PWMBundleConfig(scala.math.max(ncmp, that.ncmp))
|
||
|
}
|
||
|
|
||
|
trait HasPWMParameters {
|
||
|
val params: (PWMConfig, Parameters)
|
||
|
val c = params._1
|
||
|
implicit val p = params._2
|
||
|
}
|
||
|
|
||
|
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 val p: Parameters)
|
||
|
extends TLRegisterRouter(c.address, interrupts = c.ncmp, size = c.size, beatBytes = p(PeripheryBusConfig).beatBytes)(
|
||
|
new TLRegBundle((c, p), _) with PWMBundle)(
|
||
|
new TLRegModule((c, p), _, _) with PWMModule)
|