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