@@ -294,60 +294,90 @@ trait CanHavePeripheryGCD { this: BaseSubsystem =>
294294 val (gcd_busy, gcd_clock) = p(GCDKey ) match {
295295 case Some (params) => {
296296
297+ // If externallyClocked is true, create an input port for the GCD clock.
298+ // This clock is distinct from the pbus clock or other internal clocks.
299+ // It's defined within InModuleBody as it's a hardware port.
297300 val gcd_clock = Option .when(params.externallyClocked) {
298301 InModuleBody { IO (Input (Clock ())).suggestName(" gcd_clock_in" ) }
299302 }
303+ // Define the clock source node for the GCD module.
300304 val gcdClockNode = if (params.externallyClocked) {
305+ // If externally clocked, create a new ClockSourceNode.
306+ // This node acts as the root of the GCD's independent clock domain.
301307 val gcdSourceClockNode = ClockSourceNode (Seq (ClockSourceParameters ()))
302308 InModuleBody {
309+ // Connect the ClockSourceNode's output clock to the external gcd_clock input.
303310 gcdSourceClockNode.out(0 )._1.clock := gcd_clock.get
311+ // The reset signal for the GCD's clock domain must be synchronous to the gcd_clock.
312+ // ResetCatchAndSync synchronizes the asynchronous pbus reset to the gcd_clock domain.
304313 gcdSourceClockNode.out(0 )._1.reset := ResetCatchAndSync (gcd_clock.get, pbus.module.reset.asBool)
305314 }
306315 gcdSourceClockNode
307316 } else {
317+ // If not externally clocked, the GCD runs on the same clock as the pbus.
308318 pbus.fixedClockNode
309319 }
320+ // Define the type of clock crossing required between the pbus and the GCD module.
310321 val gcdCrossing = if (params.externallyClocked) {
322+ // If the GCD has its own clock, an AsynchronousCrossing is necessary
323+ // to safely transfer data between the pbus clock domain and the GCD clock domain.
311324 AsynchronousCrossing ()
312325 } else {
326+ // If the GCD uses the pbus clock, a SynchronousCrossing can be used.
313327 SynchronousCrossing ()
314328 }
315329
330+ // Instantiate the GCD module (either TL, AXI4, or HLS variant)
316331 val gcd = if (params.useAXI4) {
317332 val gcd = LazyModule (new GCDAXI4 (params, pbus.beatBytes)(p))
333+ // Connect the GCD's clock input to our determined gcdClockNode.
318334 gcd.clockNode := gcdClockNode
335+ // Couple the GCD to the pbus, inserting the necessary clock crossing logic.
319336 pbus.coupleTo(portName) {
337+ // AXI4InwardClockCrossingHelper handles crossing details for AXI4.
320338 AXI4InwardClockCrossingHelper (" gcd_crossing" , gcd, gcd.node)(gcdCrossing) :=
321339 AXI4Buffer () :=
322340 TLToAXI4 () :=
323- // toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needsx
341+ // toVariableWidthSlave doesn't use holdFirstDeny, which TLToAXI4() needs
324342 TLFragmenter (pbus.beatBytes, pbus.blockBytes, holdFirstDeny = true ) := _
325343 }
326344 gcd
327345 } else if (params.useHLS) {
328346 val gcd = LazyModule (new HLSGCDAccel (params, pbus.beatBytes)(p))
347+ // Connect the GCD's clock input to our determined gcdClockNode.
329348 gcd.clockNode := gcdClockNode
349+ // Couple the GCD to the pbus, inserting the necessary clock crossing logic.
330350 pbus.coupleTo(portName) {
351+ // TLInwardClockCrossingHelper handles crossing details for TileLink.
331352 TLInwardClockCrossingHelper (" gcd_crossing" , gcd, gcd.node)(gcdCrossing) :=
332353 TLFragmenter (pbus.beatBytes, pbus.blockBytes) := _
333354 }
334355 gcd
335356 } else {
336357 val gcd = LazyModule (new GCDTL (params, pbus.beatBytes)(p))
358+ // Connect the GCD's clock input to our determined gcdClockNode.
337359 gcd.clockNode := gcdClockNode
360+ // Couple the GCD to the pbus, inserting the necessary clock crossing logic.
338361 pbus.coupleTo(portName) {
362+ // TLInwardClockCrossingHelper handles crossing details for TileLink.
339363 TLInwardClockCrossingHelper (" gcd_crossing" , gcd, gcd.node)(gcdCrossing) :=
340364 TLFragmenter (pbus.beatBytes, pbus.blockBytes) := _
341365 }
342366 gcd
343367 }
368+ // Expose the GCD's busy signal.
344369 val gcd_busy = InModuleBody {
345370 val busy = IO (Output (Bool ())).suggestName(" gcd_busy" )
346371 busy := gcd.module.io.gcd_busy
347372 busy
348373 }
374+ // Return the busy signal (always needed if GCD exists) and the optional external clock input.
375+ // The Option[Clock] allows the IOBinder (WithGCDBusyPunchthrough) to conditionally
376+ // create the top-level clock input only when `externallyClocked` is true.
377+ // The busy signal is Some(busy) because the entire GCD peripheral itself is optional based on GCDKey.
349378 (Some (gcd_busy), gcd_clock)
350379 }
380+ // If GCDKey is None, the GCD peripheral is not instantiated. Return None for both signals.
351381 case None => (None , None )
352382 }
353383}
0 commit comments