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