d472ddd118deee21779e8b0011f6821d6bc2f8f5
[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 }
60
61 val aon_io = aon.module.io
62 val pads = io.pads
63
64 // -----------------------------------------------
65 // Generation of aonrst
66 // -----------------------------------------------
67
68 // ERST
69 val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true))
70 aon_io.resetCauses.erst := erst
71 aon_io.resetCauses.wdogrst := aon_io.wdog_rst
72
73 // PORRST
74 val porrst = Bool(false) // TODO
75 aon_io.resetCauses.porrst := porrst
76
77 //--------------------------------------------------
78 // Drive "Mostly Off" Reset Signals (these
79 // are synchronized inside MOFF as needed)
80 //--------------------------------------------------
81
82 io.rsts.hfclkrst := aon_io.moff.hfclkrst
83 io.rsts.corerst := aon_io.moff.corerst
84
85 //--------------------------------------------------
86 // Generate the LFCLK input to AON
87 // This is the same clock that is driven to this
88 // block as 'clock'.
89 //--------------------------------------------------
90
91 // LFCLK Override
92 // Note that the actual mux lives inside AON itself.
93 // Therefore, the lfclk which comes out of AON is the
94 // true clock that AON and AONWrapper are running off of.
95 val lfextclk = GPIOInputPinCtrl(pads.lfextclk, pue=Bool(true))
96 aon_io.lfextclk := lfextclk.asClock
97
98 // Drive AON's clock and Reset
99 val lfclk = aon_io.lfclk
100
101 val aonrst_catch = Module (new ResetCatchAndSync(3))
102 aonrst_catch.reset := erst | aon_io.wdog_rst
103 aonrst_catch.clock := lfclk
104 aon.module.reset := aonrst_catch.io.sync_reset
105
106 aon.module.clock := lfclk
107
108 //--------------------------------------------------
109 // TL2 Register Access Interface
110 //--------------------------------------------------
111
112 // Safely cross TL2 into AON Domain
113 // Ensure that both are reset and clocked
114 // at the same time.
115 // Note that aon.moff.corerst is synchronous
116 // to aon.module.clock, so this is safe.
117 val crossing_slave_reset = ResetCatchAndSync(lfclk,
118 aon.module.io.moff.corerst | aon.module.reset)
119
120 crossing.module.clock := lfclk
121 crossing.module.reset := crossing_slave_reset
122
123 crossing_monitor.foreach { lm =>
124 lm.module.clock := lfclk
125 lm.module.reset := crossing_slave_reset
126 }
127
128 // Note that aon.moff.corerst is synchronous
129 // to aon.module.clock, so this is safe.
130 isolation.module.io.iso_out := aon.module.io.moff.corerst
131 isolation.module.io.iso_in := Bool(true)
132
133 //--------------------------------------------------
134 // PMU <--> pads Interface
135 //--------------------------------------------------
136
137 val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true))
138
139 val dwakeup_deglitch = Module (new DeglitchShiftRegister(3))
140 dwakeup_deglitch.clock := lfclk
141 dwakeup_deglitch.io.d := ~dwakeup_n_async
142 aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q
143
144 GPIOOutputPinCtrl(pads.pmu.vddpaden, aon.module.io.pmu.vddpaden)
145
146 //--------------------------------------------------
147 // Connect signals to MOFF
148 //--------------------------------------------------
149
150 io.rtc := aon_io.lfclk
151 }
152
153 }
154
155 // -----------------------------------------------
156 // Isolation Cells
157 // -----------------------------------------------
158
159 class IsoZero extends Module {
160 val io = new Bundle {
161 val in = Bool(INPUT)
162 val iso = Bool(INPUT)
163 val out = Bool(OUTPUT)
164 }
165 io.out := io.in & ~io.iso
166 }
167
168 object IsoZero {
169 def apply (iso: Bool, in: UInt): UInt = {
170
171 val w = in.getWidth
172 val isos: List[IsoZero] = List.tabulate(in.getWidth)(
173 x => Module(new IsoZero).suggestName(s"iso_$x")
174 )
175 for ((z, i) <- isos.zipWithIndex) {
176 z.io.in := in(i)
177 z.io.iso := iso
178 }
179 isos.map(_.io.out).asUInt
180 }
181 }