{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Module 5.1: Project Template\n",
"**Prev: [FIRRTL](4.4_firrtl_add_ops_per_module.ipynb)**
\n",
"**Next: [Combinational Logic]()**\n",
"\n",
"## Motivation\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Setup\n",
"The following cell downloads the dependencies needed for Chisel. You will see it in all future notebooks. **Run this cell now**."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"val path = System.getProperty(\"user.dir\") + \"/source/load-ivy.sc\"\n",
"interp.load.module(ammonite.ops.Path(java.nio.file.FileSystems.getDefault().getPath(path)))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As mentioned in the last module, these statements are needed to import Chisel. **Run this cell now** before running any future code blocks."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"import chisel3._\n",
"import chisel3.util._\n",
"import freechips.rocketchip.subsystem._\n",
"import freechips.rocketchip.config.{Field, Parameters}\n",
"import freechips.rocketchip.devices.debug.Debug\n",
"import freechips.rocketchip.devices.tilelink._\n",
"import freechips.rocketchip.diplomacy._\n",
"import freechips.rocketchip.regmapper.{HasRegMap, RegField}\n",
"import freechips.rocketchip.subsystem._\n",
"import freechips.rocketchip.tilelink._\n",
"import freechips.rocketchip.util.{DontTouch, UIntIsOneOf}"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"# Your First Rocketchip Peripheral\n",
"\n",
"This example is based on the [project-template](https://github.com/ucb-bar/project-template/) repo."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"case class PWMParams(address: BigInt, beatBytes: Int)\n",
"\n",
"class PWMBase(w: Int) extends Module {\n",
" val io = IO(new Bundle {\n",
" val pwmout = Output(Bool())\n",
" val period = Input(UInt(w.W))\n",
" val duty = Input(UInt(w.W))\n",
" val enable = Input(Bool())\n",
" })\n",
"\n",
" // The counter should count up until period is reached\n",
" val counter = Reg(UInt(w.W))\n",
"\n",
" when (counter >= (io.period - 1.U)) {\n",
" counter := 0.U\n",
" } .otherwise {\n",
" counter := counter + 1.U\n",
" }\n",
"\n",
" // If PWM is enabled, pwmout is high when counter < duty\n",
" // If PWM is not enabled, it will always be low\n",
" io.pwmout := io.enable && (counter < io.duty)\n",
"}\n",
"\n",
"trait PWMTLBundle extends Bundle {\n",
" val pwmout = Output(Bool())\n",
"}\n",
"\n",
"trait PWMTLModule extends HasRegMap {\n",
" val io: PWMTLBundle\n",
" implicit val p: Parameters\n",
" def params: PWMParams\n",
"\n",
" // How many clock cycles in a PWM cycle?\n",
" val period = Reg(UInt(32.W))\n",
" // For how many cycles should the clock be high?\n",
" val duty = Reg(UInt(32.W))\n",
" // Is the PWM even running at all?\n",
" val enable = RegInit(false.B)\n",
"\n",
" val base = Module(new PWMBase(32))\n",
" io.pwmout := base.io.pwmout\n",
" base.io.period := period\n",
" base.io.duty := duty\n",
" base.io.enable := enable\n",
"\n",
" regmap(\n",
" 0x00 -> Seq(\n",
" RegField(32, period)),\n",
" 0x04 -> Seq(\n",
" RegField(32, duty)),\n",
" 0x08 -> Seq(\n",
" RegField(1, enable)))\n",
"}\n",
"\n",
"class PWMTL(c: PWMParams)(implicit p: Parameters)\n",
" extends TLRegisterRouter(\n",
" c.address, \"pwm\", Seq(\"ucbbar,pwm\"),\n",
" beatBytes = c.beatBytes)(\n",
" new TLRegBundle(c, _) with PWMTLBundle)(\n",
" new TLRegModule(c, _, _) with PWMTLModule)\n",
"\n",
"trait HasPeripheryPWM { this: BaseSubsystem =>\n",
" implicit val p: Parameters\n",
"\n",
" private val address = 0x2000\n",
" private val portName = \"pwm\"\n",
"\n",
" val pwm = LazyModule(new PWMTL(\n",
" PWMParams(address, pbus.beatBytes))(p))\n",
"\n",
" pbus.toVariableWidthSlave(Some(portName)) { pwm.node }\n",
"}\n",
"\n",
"trait HasPeripheryPWMModuleImp extends LazyModuleImp {\n",
" implicit val p: Parameters\n",
" val outer: HasPeripheryPWM\n",
"\n",
" val pwmout = IO(Output(Bool()))\n",
"\n",
" pwmout := outer.pwm.module.io.pwmout\n",
"}\n",
"\n",
"class RocketWithPWM(implicit p: Parameters) extends RocketSubsystem\n",
" with HasAsyncExtInterrupts\n",
" with CanHaveMasterAXI4MemPort\n",
" with CanHaveMasterAXI4MMIOPort\n",
" with CanHaveSlaveAXI4Port\n",
" with HasPeripheryBootROM\n",
" with HasPeripheryPWM {\n",
" override lazy val module = new RocketWithPWMModule(this)\n",
"}\n",
"\n",
"class RocketWithPWMModule(l: RocketWithPWM) extends RocketSubsystemModuleImp(l)\n",
" with HasRTCModuleImp\n",
" with HasExtInterruptsModuleImp\n",
" with CanHaveMasterAXI4MemPortModuleImp\n",
" with CanHaveMasterAXI4MMIOPortModuleImp\n",
" with CanHaveSlaveAXI4PortModuleImp\n",
" with HasPeripheryBootROMModuleImp\n",
" with DontTouch\n",
" with HasPeripheryPWMModuleImp\n",
"\n",
"class TestHarness extends Module {\n",
" implicit val p: Parameters = new freechips.rocketchip.system.DefaultConfig\n",
" override def desiredName = \"TestHarness\"\n",
"\n",
" val io = IO(new Bundle {\n",
" val success = Output(Bool())\n",
" })\n",
"\n",
" val dut = Module(LazyModule(new RocketWithPWM).module)\n",
" dut.dontTouchPorts()\n",
" dut.tieOffInterrupts()\n",
" dut.connectSimAXIMem()\n",
" dut.connectSimAXIMMIO()\n",
" dut.l2_frontend_bus_axi4.foreach(a => {\n",
" a.tieoff()\n",
" a.ar.bits := DontCare\n",
" a.aw.bits := DontCare\n",
" a.w.bits := DontCare\n",
" })\n",
" Debug.connectDebug(dut.debug, clock, reset.toBool, io.success)\n",
"}\n",
"\n",
"// println(getFirrtl(new TestHarness))\n",
"chisel3.Driver.execute(Array[String](\"-X\", \"verilog\", \"-td\", \"./verisim/generated-src/\"), () => new TestHarness)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n",
"# You're done!\n",
"\n",
"[Return to the top.](#top)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Scala",
"language": "scala",
"name": "scala"
},
"language_info": {
"codemirror_mode": "text/x-scala",
"file_extension": ".scala",
"mimetype": "text/x-scala",
"name": "scala",
"nbconvert_exporter": "script",
"version": "2.12.8"
}
},
"nbformat": 4,
"nbformat_minor": 2
}