The following cell downloads the dependencies needed for Chisel. You will see it in all future notebooks. Run this cell now.
val path = System.getProperty("user.dir") + "/source/load-ivy.sc"
interp.load.module(ammonite.ops.Path(java.nio.file.FileSystems.getDefault().getPath(path)))
As mentioned in the last module, these statements are needed to import Chisel. Run this cell now before running any future code blocks.
import chisel3._
import chisel3.util._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.config.{Field, Parameters}
import freechips.rocketchip.devices.debug.Debug
import freechips.rocketchip.devices.tilelink._
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.regmapper.{HasRegMap, RegField}
import freechips.rocketchip.subsystem._
import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.{DontTouch, UIntIsOneOf}
case class PWMParams(address: BigInt, beatBytes: Int)
class PWMBase(w: Int) extends Module {
val io = IO(new Bundle {
val pwmout = Output(Bool())
val period = Input(UInt(w.W))
val duty = Input(UInt(w.W))
val enable = Input(Bool())
})
// The counter should count up until period is reached
val counter = Reg(UInt(w.W))
when (counter >= (io.period - 1.U)) {
counter := 0.U
} .otherwise {
counter := counter + 1.U
}
// If PWM is enabled, pwmout is high when counter < duty
// If PWM is not enabled, it will always be low
io.pwmout := io.enable && (counter < io.duty)
}
trait PWMTLBundle extends Bundle {
val pwmout = Output(Bool())
}
trait PWMTLModule extends HasRegMap {
val io: PWMTLBundle
implicit val p: Parameters
def params: PWMParams
// How many clock cycles in a PWM cycle?
val period = Reg(UInt(32.W))
// For how many cycles should the clock be high?
val duty = Reg(UInt(32.W))
// Is the PWM even running at all?
val enable = RegInit(false.B)
val base = Module(new PWMBase(32))
io.pwmout := base.io.pwmout
base.io.period := period
base.io.duty := duty
base.io.enable := enable
regmap(
0x00 -> Seq(
RegField(32, period)),
0x04 -> Seq(
RegField(32, duty)),
0x08 -> Seq(
RegField(1, enable)))
}
class PWMTL(c: PWMParams)(implicit p: Parameters)
extends TLRegisterRouter(
c.address, "pwm", Seq("ucbbar,pwm"),
beatBytes = c.beatBytes)(
new TLRegBundle(c, _) with PWMTLBundle)(
new TLRegModule(c, _, _) with PWMTLModule)
trait HasPeripheryPWM { this: BaseSubsystem =>
implicit val p: Parameters
private val address = 0x2000
private val portName = "pwm"
val pwm = LazyModule(new PWMTL(
PWMParams(address, pbus.beatBytes))(p))
pbus.toVariableWidthSlave(Some(portName)) { pwm.node }
}
trait HasPeripheryPWMModuleImp extends LazyModuleImp {
implicit val p: Parameters
val outer: HasPeripheryPWM
val pwmout = IO(Output(Bool()))
pwmout := outer.pwm.module.io.pwmout
}
class RocketWithPWM(implicit p: Parameters) extends RocketSubsystem
with HasAsyncExtInterrupts
with CanHaveMasterAXI4MemPort
with CanHaveMasterAXI4MMIOPort
with CanHaveSlaveAXI4Port
with HasPeripheryBootROM
with HasPeripheryPWM {
override lazy val module = new RocketWithPWMModule(this)
}
class RocketWithPWMModule(l: RocketWithPWM) extends RocketSubsystemModuleImp(l)
with HasRTCModuleImp
with HasExtInterruptsModuleImp
with CanHaveMasterAXI4MemPortModuleImp
with CanHaveMasterAXI4MMIOPortModuleImp
with CanHaveSlaveAXI4PortModuleImp
with HasPeripheryBootROMModuleImp
with DontTouch
with HasPeripheryPWMModuleImp
class TestHarness extends Module {
implicit val p: Parameters = new freechips.rocketchip.system.DefaultConfig
override def desiredName = "TestHarness"
val io = IO(new Bundle {
val success = Output(Bool())
})
val dut = Module(LazyModule(new RocketWithPWM).module)
dut.dontTouchPorts()
dut.tieOffInterrupts()
dut.connectSimAXIMem()
dut.connectSimAXIMMIO()
dut.l2_frontend_bus_axi4.foreach(a => {
a.tieoff()
a.ar.bits := DontCare
a.aw.bits := DontCare
a.w.bits := DontCare
})
Debug.connectDebug(dut.debug, clock, reset.toBool, io.success)
}
// println(getFirrtl(new TestHarness))
chisel3.Driver.execute(Array[String]("-X", "verilog", "-td", "./verisim/generated-src/"), () => new TestHarness)