1 // See LICENSE for license details.
2 package sifive.blocks.devices.mockaon
5 import freechips.rocketchip.config.Parameters
6 import freechips.rocketchip.diplomacy._
7 import freechips.rocketchip.tilelink._
8 import freechips.rocketchip.util._
9 import sifive.blocks.devices.pinctrl.{EnhancedPin}
10 import sifive.blocks.util.{DeglitchShiftRegister}
12 /* The wrapper handles the Clock and Reset Generation for The AON block itself,
13 and instantiates real pad controls (aka pull-ups)*/
15 class MockAONWrapperPMUIO extends Bundle {
16 val dwakeup_n = new EnhancedPin()
17 val vddpaden = new EnhancedPin()
20 class MockAONWrapperPins extends Bundle {
21 val erst_n = new EnhancedPin()
22 val lfextclk = new EnhancedPin()
23 val pmu = new MockAONWrapperPMUIO()
26 class MockAONWrapperBundle extends Bundle {
27 val pins = new MockAONWrapperPins()
28 val rsts = new MockAONMOffRstIO()
31 class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends LazyModule {
33 val aon = LazyModule(new TLMockAON(w, c))
35 // We only need to isolate the signals
36 // coming from MOFF to AON,
37 // since AON is never off while MOFF is on.
38 // The MOFF is on the "in" side of the Isolation.
39 // AON is on the "out" side of the Isolation.
41 def isoOut(iso: Bool, x: UInt): UInt = IsoZero(iso, x)
42 def isoIn(iso: Bool, x: UInt): UInt = x
43 val isolation = LazyModule(new TLIsolation(fOut = isoOut, fIn = isoIn))
44 val crossing = LazyModule(new TLAsyncCrossingSink(depth = 1))
46 val node: TLAsyncInwardNode = isolation.node
47 crossing.node := isolation.node
48 aon.node := crossing.node
50 // crossing lives outside in Periphery
51 val intnode: IntOutwardNode = aon.intnode
53 lazy val module = new LazyModuleImp(this) {
54 val io = IO(new MockAONWrapperBundle {
55 val rtc = Clock(OUTPUT)
56 val ndreset = Bool(INPUT)
59 val aon_io = aon.module.io
62 // -----------------------------------------------
63 // Generation of aonrst
64 // -----------------------------------------------
67 val erst = ~pins.erst_n.inputPin(pue = Bool(true))
68 aon_io.resetCauses.erst := erst
69 aon_io.resetCauses.wdogrst := aon_io.wdog_rst
72 val porrst = Bool(false) // TODO
73 aon_io.resetCauses.porrst := porrst
75 //--------------------------------------------------
76 // Drive "Mostly Off" Reset Signals (these
77 // are synchronized inside MOFF as needed)
78 //--------------------------------------------------
80 io.rsts.hfclkrst := aon_io.moff.hfclkrst
81 io.rsts.corerst := aon_io.moff.corerst
83 //--------------------------------------------------
84 // Generate the LFCLK input to AON
85 // This is the same clock that is driven to this
87 //--------------------------------------------------
90 // Note that the actual mux lives inside AON itself.
91 // Therefore, the lfclk which comes out of AON is the
92 // true clock that AON and AONWrapper are running off of.
93 val lfextclk = pins.lfextclk.inputPin(pue=Bool(true))
94 aon_io.lfextclk := lfextclk.asClock
96 // Drive AON's clock and Reset
97 val lfclk = aon_io.lfclk
99 val aonrst_catch = Module (new ResetCatchAndSync(3))
100 aonrst_catch.reset := erst | aon_io.wdog_rst | io.ndreset
101 aonrst_catch.clock := lfclk
102 aon.module.reset := aonrst_catch.io.sync_reset
104 aon.module.clock := lfclk
106 //--------------------------------------------------
107 // TL2 Register Access Interface
108 //--------------------------------------------------
110 // Safely cross TL2 into AON Domain
111 // Ensure that both are reset and clocked
113 // Note that aon.moff.corerst is synchronous
114 // to aon.module.clock, so this is safe.
115 val crossing_slave_reset = ResetCatchAndSync(lfclk,
116 aon.module.io.moff.corerst | aon.module.reset)
118 crossing.module.clock := lfclk
119 crossing.module.reset := crossing_slave_reset
121 // Note that aon.moff.corerst is synchronous
122 // to aon.module.clock, so this is safe.
123 isolation.module.io.iso_out := aon.module.io.moff.corerst
124 isolation.module.io.iso_in := Bool(true)
126 //--------------------------------------------------
127 // PMU <--> pins Interface
128 //--------------------------------------------------
130 val dwakeup_n_async = pins.pmu.dwakeup_n.inputPin(pue=Bool(true))
132 val dwakeup_deglitch = Module (new DeglitchShiftRegister(3))
133 dwakeup_deglitch.clock := lfclk
134 dwakeup_deglitch.io.d := ~dwakeup_n_async
135 aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q
137 pins.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
139 //--------------------------------------------------
140 // Connect signals to MOFF
141 //--------------------------------------------------
143 io.rtc := aon_io.lfclk
148 // -----------------------------------------------
150 // -----------------------------------------------
152 class IsoZero extends Module {
153 val io = new Bundle {
155 val iso = Bool(INPUT)
156 val out = Bool(OUTPUT)
158 io.out := io.in & ~io.iso
162 def apply (iso: Bool, in: UInt): UInt = {
165 val isos: List[IsoZero] = List.tabulate(in.getWidth)(
166 x => Module(new IsoZero).suggestName(s"iso_$x")
168 for ((z, i) <- isos.zipWithIndex) {
172 isos.map(_.io.out).asUInt