099dba77e3c762aa06a7a9fe9d6fc40427706ebc
[sifive-blocks.git] / src / main / scala / devices / mockaon / MockAONWrapper.scala
1 // See LICENSE for license details.
2 package sifive.blocks.devices.mockaon
3
4 import Chisel._
5 import config._
6 import diplomacy._
7 import uncore.tilelink2._
8 import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
9 import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync}
10 import util._
11 /* The wrapper handles the Clock and Reset Generation for The AON block itself,
12 and instantiates real pad controls (aka pull-ups)*/
13
14 class MockAONWrapperPMUIO extends Bundle {
15 val dwakeup_n = new GPIOPin()
16 val vddpaden = new GPIOPin()
17 }
18
19 class MockAONWrapperPadsIO extends Bundle {
20 val erst_n = new GPIOPin()
21 val lfextclk = new GPIOPin()
22 val pmu = new MockAONWrapperPMUIO()
23 }
24
25 class MockAONWrapperBundle extends Bundle {
26 val pads = new MockAONWrapperPadsIO()
27 val rsts = new MockAONMOffRstIO()
28 }
29
30 class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends LazyModule {
31
32 val node = TLAsyncInputNode()
33 val intnode = IntOutputNode()
34 val aon = LazyModule(new TLMockAON(w, c))
35
36 // We only need to isolate the signals
37 // coming from MOFF to AON,
38 // since AON is never off while MOFF is on.
39 // The MOFF is on the "in" side of the Isolation.
40 // AON is on the "out" side of the Isolation.
41
42 def isoOut(iso: Bool, x: UInt): UInt = IsoZero(iso, x)
43 def isoIn(iso: Bool, x: UInt): UInt = x
44 val isolation = LazyModule(new TLIsolation(fOut = isoOut, fIn = isoIn))
45 val crossing = LazyModule(new TLAsyncCrossingSink(depth = 1))
46
47 isolation.node := node
48 crossing.node := isolation.node
49 val crossing_monitor = (aon.node := crossing.node)
50
51 // crossing lives outside in Periphery
52 intnode := aon.intnode
53
54 lazy val module = new LazyModuleImp(this) {
55 val io = new MockAONWrapperBundle {
56 val in = node.bundleIn
57 val ip = intnode.bundleOut
58 val rtc = Clock(OUTPUT)
59 val ndreset = Bool(INPUT)
60 }
61
62 val aon_io = aon.module.io
63 val pads = io.pads
64
65 // -----------------------------------------------
66 // Generation of aonrst
67 // -----------------------------------------------
68
69 // ERST
70 val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true))
71 aon_io.resetCauses.erst := erst
72 aon_io.resetCauses.wdogrst := aon_io.wdog_rst
73
74 // PORRST
75 val porrst = Bool(false) // TODO
76 aon_io.resetCauses.porrst := porrst
77
78 //--------------------------------------------------
79 // Drive "Mostly Off" Reset Signals (these
80 // are synchronized inside MOFF as needed)
81 //--------------------------------------------------
82
83 io.rsts.hfclkrst := aon_io.moff.hfclkrst
84 io.rsts.corerst := aon_io.moff.corerst
85
86 //--------------------------------------------------
87 // Generate the LFCLK input to AON
88 // This is the same clock that is driven to this
89 // block as 'clock'.
90 //--------------------------------------------------
91
92 // LFCLK Override
93 // Note that the actual mux lives inside AON itself.
94 // Therefore, the lfclk which comes out of AON is the
95 // true clock that AON and AONWrapper are running off of.
96 val lfextclk = GPIOInputPinCtrl(pads.lfextclk, pue=Bool(true))
97 aon_io.lfextclk := lfextclk.asClock
98
99 // Drive AON's clock and Reset
100 val lfclk = aon_io.lfclk
101
102 val aonrst_catch = Module (new ResetCatchAndSync(3))
103 aonrst_catch.reset := erst | aon_io.wdog_rst | io.ndreset
104 aonrst_catch.clock := lfclk
105 aon.module.reset := aonrst_catch.io.sync_reset
106
107 aon.module.clock := lfclk
108
109 //--------------------------------------------------
110 // TL2 Register Access Interface
111 //--------------------------------------------------
112
113 // Safely cross TL2 into AON Domain
114 // Ensure that both are reset and clocked
115 // at the same time.
116 // Note that aon.moff.corerst is synchronous
117 // to aon.module.clock, so this is safe.
118 val crossing_slave_reset = ResetCatchAndSync(lfclk,
119 aon.module.io.moff.corerst | aon.module.reset)
120
121 crossing.module.clock := lfclk
122 crossing.module.reset := crossing_slave_reset
123
124 crossing_monitor.foreach { lm =>
125 lm.module.clock := lfclk
126 lm.module.reset := crossing_slave_reset
127 }
128
129 // Note that aon.moff.corerst is synchronous
130 // to aon.module.clock, so this is safe.
131 isolation.module.io.iso_out := aon.module.io.moff.corerst
132 isolation.module.io.iso_in := Bool(true)
133
134 //--------------------------------------------------
135 // PMU <--> pads Interface
136 //--------------------------------------------------
137
138 val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true))
139
140 val dwakeup_deglitch = Module (new DeglitchShiftRegister(3))
141 dwakeup_deglitch.clock := lfclk
142 dwakeup_deglitch.io.d := ~dwakeup_n_async
143 aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q
144
145 GPIOOutputPinCtrl(pads.pmu.vddpaden, aon.module.io.pmu.vddpaden)
146
147 //--------------------------------------------------
148 // Connect signals to MOFF
149 //--------------------------------------------------
150
151 io.rtc := aon_io.lfclk
152 }
153
154 }
155
156 // -----------------------------------------------
157 // Isolation Cells
158 // -----------------------------------------------
159
160 class IsoZero extends Module {
161 val io = new Bundle {
162 val in = Bool(INPUT)
163 val iso = Bool(INPUT)
164 val out = Bool(OUTPUT)
165 }
166 io.out := io.in & ~io.iso
167 }
168
169 object IsoZero {
170 def apply (iso: Bool, in: UInt): UInt = {
171
172 val w = in.getWidth
173 val isos: List[IsoZero] = List.tabulate(in.getWidth)(
174 x => Module(new IsoZero).suggestName(s"iso_$x")
175 )
176 for ((z, i) <- isos.zipWithIndex) {
177 z.io.in := in(i)
178 z.io.iso := iso
179 }
180 isos.map(_.io.out).asUInt
181 }
182 }