// See LICENSE for license details. package sifive.blocks.devices.mockaon import Chisel._ import config._ import diplomacy._ import uncore.tilelink2._ import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl} import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync} import util._ /* The wrapper handles the Clock and Reset Generation for The AON block itself, and instantiates real pad controls (aka pull-ups)*/ class MockAONWrapperPMUIO extends Bundle { val dwakeup_n = new GPIOPin() val vddpaden = new GPIOPin() } class MockAONWrapperPadsIO extends Bundle { val erst_n = new GPIOPin() val lfextclk = new GPIOPin() val pmu = new MockAONWrapperPMUIO() } class MockAONWrapperBundle extends Bundle { val pads = new MockAONWrapperPadsIO() val rsts = new MockAONMOffRstIO() } class MockAONWrapper(c: MockAONConfig)(implicit val p: Parameters) extends LazyModule { val node = TLAsyncInputNode() val intnode = IntOutputNode() val aon = LazyModule (new MockAON(c)(p)) // We only need to isolate the signals // coming from MOFF to AON, // since AON is never off while MOFF is on. // The MOFF is on the "in" side of the Isolation. // AON is on the "out" side of the Isolation. def isoOut(iso: Bool, x: UInt): UInt = IsoZero(iso, x) def isoIn(iso: Bool, x: UInt): UInt = x val isolation = LazyModule(new TLIsolation(fOut = isoOut, fIn = isoIn)) val crossing = LazyModule(new TLAsyncCrossingSink(depth = 1)) isolation.node := node crossing.node := isolation.node val crossing_monitor = (aon.node := crossing.node) // crossing lives outside in Periphery intnode := aon.intnode lazy val module = new LazyModuleImp(this) { val io = new MockAONWrapperBundle { val in = node.bundleIn val ip = intnode.bundleOut val rtc = Clock(OUTPUT) } val aon_io = aon.module.io val pads = io.pads // ----------------------------------------------- // Generation of aonrst // ----------------------------------------------- // ERST val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true)) aon_io.resetCauses.erst := erst aon_io.resetCauses.wdogrst := aon_io.wdog_rst // PORRST val porrst = Bool(false) // TODO aon_io.resetCauses.porrst := porrst //-------------------------------------------------- // Drive "Mostly Off" Reset Signals (these // are synchronized inside MOFF as needed) //-------------------------------------------------- io.rsts.hfclkrst := aon_io.moff.hfclkrst io.rsts.corerst := aon_io.moff.corerst //-------------------------------------------------- // Generate the LFCLK input to AON // This is the same clock that is driven to this // block as 'clock'. //-------------------------------------------------- // LFCLK Override // Note that the actual mux lives inside AON itself. // Therefore, the lfclk which comes out of AON is the // true clock that AON and AONWrapper are running off of. val lfextclk = GPIOInputPinCtrl(pads.lfextclk, pue=Bool(true)) aon_io.lfextclk := lfextclk.asClock // Drive AON's clock and Reset val lfclk = aon_io.lfclk val aonrst_catch = Module (new ResetCatchAndSync(3)) aonrst_catch.reset := erst | aon_io.wdog_rst aonrst_catch.clock := lfclk aon.module.reset := aonrst_catch.io.sync_reset aon.module.clock := lfclk //-------------------------------------------------- // TL2 Register Access Interface //-------------------------------------------------- // Safely cross TL2 into AON Domain // Ensure that both are reset and clocked // at the same time. // Note that aon.moff.corerst is synchronous // to aon.module.clock, so this is safe. val crossing_slave_reset = ResetCatchAndSync(lfclk, aon.module.io.moff.corerst | aon.module.reset) crossing.module.clock := lfclk crossing.module.reset := crossing_slave_reset crossing_monitor.foreach { lm => lm.module.clock := lfclk lm.module.reset := crossing_slave_reset } // Note that aon.moff.corerst is synchronous // to aon.module.clock, so this is safe. isolation.module.io.iso_out := aon.module.io.moff.corerst isolation.module.io.iso_in := Bool(true) //-------------------------------------------------- // PMU <--> pads Interface //-------------------------------------------------- val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true)) val dwakeup_deglitch = Module (new DeglitchShiftRegister(3)) dwakeup_deglitch.clock := lfclk dwakeup_deglitch.io.d := ~dwakeup_n_async aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q GPIOOutputPinCtrl(pads.pmu.vddpaden, aon.module.io.pmu.vddpaden) //-------------------------------------------------- // Connect signals to MOFF //-------------------------------------------------- io.rtc := aon_io.lfclk } } // ----------------------------------------------- // Isolation Cells // ----------------------------------------------- class IsoZero extends Module { val io = new Bundle { val in = Bool(INPUT) val iso = Bool(INPUT) val out = Bool(OUTPUT) } io.out := io.in & ~io.iso } object IsoZero { def apply (iso: Bool, in: UInt): UInt = { val w = in.getWidth val isos: List[IsoZero] = List.tabulate(in.getWidth)( x => Module(new IsoZero).suggestName(s"iso_$x") ) for ((z, i) <- isos.zipWithIndex) { z.io.in := in(i) z.io.iso := iso } isos.map(_.io.out).asUInt } }