3d35d81cf49fcbf5a8a64bc5a07e28a9204f2611
[sifive-blocks.git] / src / main / scala / devices / pwm / PWM.scala
1 // See LICENSE for license details.
2 package sifive.blocks.devices.pwm
3
4 import Chisel._
5 import Chisel.ImplicitConversions._
6 import freechips.rocketchip.config.Parameters
7 import freechips.rocketchip.regmapper._
8 import freechips.rocketchip.tilelink._
9 import freechips.rocketchip.util._
10 import sifive.blocks.util.GenericTimer
11
12 // Core PWM Functionality & Register Interface
13
14 class PWM(val ncmp: Int = 4, val cmpWidth: Int = 16) extends GenericTimer {
15 protected def countWidth = ((1 << scaleWidth) - 1) + cmpWidth
16 protected lazy val countAlways = RegEnable(io.regs.cfg.write.bits(12), Bool(false), io.regs.cfg.write.valid && unlocked)
17 protected lazy val feed = count.carryOut(scale + UInt(cmpWidth))
18 protected lazy val countEn = Wire(Bool())
19 override protected lazy val oneShot = RegEnable(io.regs.cfg.write.bits(13) && !countReset, Bool(false), (io.regs.cfg.write.valid && unlocked) || countReset)
20 override protected lazy val center = RegEnable(io.regs.cfg.write.bits(16 + ncmp - 1, 16), io.regs.cfg.write.valid && unlocked)
21 override protected lazy val gang = RegEnable(io.regs.cfg.write.bits(24 + ncmp - 1, 24), io.regs.cfg.write.valid && unlocked)
22 override protected lazy val deglitch = RegEnable(io.regs.cfg.write.bits(10), io.regs.cfg.write.valid && unlocked)(0)
23 override protected lazy val sticky = RegEnable(io.regs.cfg.write.bits(8), io.regs.cfg.write.valid && unlocked)(0)
24 override protected lazy val ip = {
25 val doSticky = Reg(next = (deglitch && !countReset) || sticky)
26 val sel = ((0 until ncmp).map(i => s(cmpWidth-1) && center(i))).asUInt
27 val reg = Reg(UInt(width = ncmp))
28 reg := (sel & elapsed.asUInt) | (~sel & (elapsed.asUInt | (Fill(ncmp, doSticky) & reg)))
29 when (io.regs.cfg.write.valid && unlocked) { reg := io.regs.cfg.write.bits(28 + ncmp - 1, 28) }
30 reg
31 }
32 lazy val io = new GenericTimerIO {
33 val gpio = Vec(ncmp, Bool()).asOutput
34 }
35 io.gpio := io.gpio.fromBits(ip & ~(gang & Cat(ip(0), ip >> 1)))
36 countEn := countAlways || oneShot
37 }
38
39 case class PWMParams(
40 address: BigInt,
41 size: Int = 0x1000,
42 regBytes: Int = 4,
43 ncmp: Int = 4,
44 cmpWidth: Int = 16)
45
46 trait HasPWMBundleContents extends Bundle {
47 def params: PWMParams
48 val gpio = Vec(params.ncmp, Bool()).asOutput
49 }
50
51 trait HasPWMModuleContents extends Module with HasRegMap {
52 val io: HasPWMBundleContents
53 val params: PWMParams
54
55 val pwm = Module(new PWM(params.ncmp, params.cmpWidth))
56
57 interrupts := pwm.io.ip
58 io.gpio := pwm.io.gpio
59
60 regmap((GenericTimer.timerRegMap(pwm, 0, params.regBytes)):_*)
61 }
62
63 class TLPWM(w: Int, c: PWMParams)(implicit p: Parameters)
64 extends TLRegisterRouter(c.address, "pwm", Seq("sifive,pwm0"), interrupts = c.ncmp, size = c.size, beatBytes = w)(
65 new TLRegBundle(c, _) with HasPWMBundleContents)(
66 new TLRegModule(c, _, _) with HasPWMModuleContents)