bfc73b252510a679f7a031bfc8902577a371e62e
[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 aon = LazyModule(new TLMockAON(w, c))
34
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.
40
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))
45
46 val node: TLAsyncInwardNode = isolation.node
47 crossing.node := isolation.node
48 aon.node := crossing.node
49
50 // crossing lives outside in Periphery
51 val intnode: IntOutwardNode = aon.intnode
52
53 lazy val module = new LazyModuleImp(this) {
54 val io = IO(new MockAONWrapperBundle {
55 val rtc = Clock(OUTPUT)
56 val ndreset = Bool(INPUT)
57 })
58
59 val aon_io = aon.module.io
60 val pins = io.pins
61
62 // -----------------------------------------------
63 // Generation of aonrst
64 // -----------------------------------------------
65
66 // ERST
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
70
71 // PORRST
72 val porrst = Bool(false) // TODO
73 aon_io.resetCauses.porrst := porrst
74
75 //--------------------------------------------------
76 // Drive "Mostly Off" Reset Signals (these
77 // are synchronized inside MOFF as needed)
78 //--------------------------------------------------
79
80 io.rsts.hfclkrst := aon_io.moff.hfclkrst
81 io.rsts.corerst := aon_io.moff.corerst
82
83 //--------------------------------------------------
84 // Generate the LFCLK input to AON
85 // This is the same clock that is driven to this
86 // block as 'clock'.
87 //--------------------------------------------------
88
89 // LFCLK Override
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
95
96 // Drive AON's clock and Reset
97 val lfclk = aon_io.lfclk
98
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
103
104 aon.module.clock := lfclk
105
106 //--------------------------------------------------
107 // TL2 Register Access Interface
108 //--------------------------------------------------
109
110 // Safely cross TL2 into AON Domain
111 // Ensure that both are reset and clocked
112 // at the same time.
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)
117
118 crossing.module.clock := lfclk
119 crossing.module.reset := crossing_slave_reset
120
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)
125
126 //--------------------------------------------------
127 // PMU <--> pins Interface
128 //--------------------------------------------------
129
130 val dwakeup_n_async = pins.pmu.dwakeup_n.inputPin(pue=Bool(true))
131
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
136
137 pins.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
138
139 //--------------------------------------------------
140 // Connect signals to MOFF
141 //--------------------------------------------------
142
143 io.rtc := aon_io.lfclk
144 }
145
146 }
147
148 // -----------------------------------------------
149 // Isolation Cells
150 // -----------------------------------------------
151
152 class IsoZero extends Module {
153 val io = new Bundle {
154 val in = Bool(INPUT)
155 val iso = Bool(INPUT)
156 val out = Bool(OUTPUT)
157 }
158 io.out := io.in & ~io.iso
159 }
160
161 object IsoZero {
162 def apply (iso: Bool, in: UInt): UInt = {
163
164 val w = in.getWidth
165 val isos: List[IsoZero] = List.tabulate(in.getWidth)(
166 x => Module(new IsoZero).suggestName(s"iso_$x")
167 )
168 for ((z, i) <- isos.zipWithIndex) {
169 z.io.in := in(i)
170 z.io.iso := iso
171 }
172 isos.map(_.io.out).asUInt
173 }
174 }