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