c649e7e376eec6cf7e48737a50291bf123ddb69a
[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 config._
7 import regmapper._
8 import rocketchip.PeripheryBusConfig
9 import uncore.tilelink2._
10 import util._
11
12 import sifive.blocks.util.GenericTimer
13
14 // Core PWM Functionality & Register Interface
15
16 class PWM(val ncmp: Int = 4, val cmpWidth: Int = 16)(implicit p: Parameters) extends GenericTimer {
17 protected def countWidth = ((1 << scaleWidth) - 1) + cmpWidth
18 protected lazy val countAlways = RegEnable(io.regs.cfg.write.bits(12), Bool(false), io.regs.cfg.write.valid && unlocked)
19 protected lazy val feed = count.carryOut(scale + UInt(cmpWidth))
20 protected lazy val countEn = Wire(Bool())
21 override protected lazy val oneShot = RegEnable(io.regs.cfg.write.bits(13) && !countReset, Bool(false), (io.regs.cfg.write.valid && unlocked) || countReset)
22 override protected lazy val center = RegEnable(io.regs.cfg.write.bits(16 + ncmp - 1, 16), io.regs.cfg.write.valid && unlocked)
23 override protected lazy val gang = RegEnable(io.regs.cfg.write.bits(24 + ncmp - 1, 24), io.regs.cfg.write.valid && unlocked)
24 override protected lazy val deglitch = RegEnable(io.regs.cfg.write.bits(10), io.regs.cfg.write.valid && unlocked)(0)
25 override protected lazy val sticky = RegEnable(io.regs.cfg.write.bits(8), io.regs.cfg.write.valid && unlocked)(0)
26 override protected lazy val ip = {
27 val doSticky = Reg(next = (deglitch && !countReset) || sticky)
28 val sel = ((0 until ncmp).map(i => s(cmpWidth-1) && center(i))).asUInt
29 val reg = Reg(UInt(width = ncmp))
30 reg := (sel & elapsed.asUInt) | (~sel & (elapsed.asUInt | (Fill(ncmp, doSticky) & reg)))
31 when (io.regs.cfg.write.valid && unlocked) { reg := io.regs.cfg.write.bits(28 + ncmp - 1, 28) }
32 reg
33 }
34 lazy val io = new GenericTimerIO {
35 val gpio = Vec(ncmp, Bool()).asOutput
36 }
37 io.gpio := io.gpio.fromBits(ip & ~(gang & Cat(ip(0), ip >> 1)))
38 countEn := countAlways || oneShot
39 }
40
41 case class PWMConfig(
42 address: BigInt,
43 size: Int = 0x1000,
44 regBytes: Int = 4,
45 ncmp: Int = 4,
46 cmpWidth: Int = 16)
47 {
48 val bc = new PWMBundleConfig(ncmp)
49 }
50
51 case class PWMBundleConfig(
52 ncmp: Int)
53 {
54 def union(that: PWMBundleConfig): PWMBundleConfig =
55 PWMBundleConfig(scala.math.max(ncmp, that.ncmp))
56 }
57
58 trait HasPWMParameters {
59 implicit val p: Parameters
60 val params: PWMConfig
61 val c = params
62 }
63
64 trait PWMBundle extends Bundle with HasPWMParameters {
65 val gpio = Vec(c.ncmp, Bool()).asOutput
66 }
67
68 trait PWMModule extends Module with HasRegMap with HasPWMParameters {
69 val io: PWMBundle
70
71 val pwm = Module(new PWM(c.ncmp, c.cmpWidth))
72
73 interrupts := pwm.io.ip
74 io.gpio := pwm.io.gpio
75
76 regmap((GenericTimer.timerRegMap(pwm, 0, c.regBytes)):_*)
77 }
78
79 class TLPWM(c: PWMConfig)(implicit p: Parameters)
80 extends TLRegisterRouter(c.address, interrupts = c.ncmp, size = c.size, beatBytes = p(PeripheryBusConfig).beatBytes)(
81 new TLRegBundle(c, _) with PWMBundle)(
82 new TLRegModule(c, _, _) with PWMModule)