Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to modify periphery to use other clock and cross clock #101

Open
colin4124 opened this issue Jan 4, 2019 · 4 comments
Open

How to modify periphery to use other clock and cross clock #101

colin4124 opened this issue Jan 4, 2019 · 4 comments

Comments

@colin4124
Copy link

Take GPIO for example, there are controlXType and mclock in GPIOAttachParams .

case class GPIOAttachParams(
gpio: GPIOParams,
controlBus: TLBusWrapper,
intNode: IntInwardNode,
controlXType: ClockCrossingType = NoCrossing,
intXType: ClockCrossingType = NoCrossing,
mclock: Option[ModuleValue[Clock]] = None,
mreset: Option[ModuleValue[Bool]] = None)
(implicit val p: Parameters)

The code below is to use it:

trait HasPeripheryGPIO { this: BaseSubsystem =>
val gpioNodes = p(PeripheryGPIOKey).map { ps => GPIO.attach(GPIOAttachParams(ps, pbus, ibus.fromAsync)).ioNode.makeSink }
}

If I want to use other clock giving to GPIO, should I use SynchronousCrossing ? So I would give controlXType as below:

trait HasPeripheryGPIO { this: BaseSubsystem =>
   val gpioXType = SynchronousCrossing // Here I use dafault options
   val gpioNodes = p(PeripheryGPIOKey).map { ps => GPIO.attach(GPIOAttachParams(ps, pbus, ibus.fromAsync, controlXType=gpioXType)).ioNode.makeSink } 
} 

But I don't know how to connect mclock from outside, such as GPIO's IO port.

@colin4124
Copy link
Author

@borancar Would you have any idea? PS: I think github issues is much useful than sifive forums, because I can link the code and jump to source file easy.

@borancar
Copy link

borancar commented Jan 4, 2019

Depends what the relationship between the clocks will be. If the clocks have different frequencies and phases then you typically need AsynchronousCrossing. As for the mclock and mreset, you just need to pass it to the GPIOAttachParams and the magic will happen in attach:

InModuleBody { gpio.module.clock := params.mclock.map(_.getWrappedValue).getOrElse(cbus.module.clock) }
InModuleBody { gpio.module.reset := params.mreset.map(_.getWrappedValue).getOrElse(cbus.module.reset) }

This is just what I think should be done, and Diplomacy will do its magic. Note that I haven't tried any of it yet.

@colin4124
Copy link
Author

@borancar I notice GPIOAttachParams . But I don't know how to connect outside E300ArtyDevKitSystem . I would try to explain more as below.

  1. I declare outside_mclock type the same as mclock parameter in GPIOAttachParams .
trait HasPeripheryGPIO { this: BaseSubsystem =>
  val outside_mclock: Option[ModuleValue[Clock]]
   val gpioXType = SynchronousCrossing // Here I use dafault options
   val gpioNodes = p(PeripheryGPIOKey).map { ps => GPIO.attach(GPIOAttachParams(ps, pbus, ibus.fromAsync, controlXType=gpioXType)).ioNode.makeSink } 
} 
  1. I define outside_mclock in the class which extends this trait.
class E300ArtyDevKitSystem(mclock: Clock)(implicit p: Parameters) extends RocketSubsystem
    with HasPeripheryMaskROMSlave
    with HasPeripheryDebug
    with HasPeripheryMockAON
    with HasPeripheryUART
    with HasPeripherySPIFlash
    with HasPeripherySPI
    with HasPeripheryGPIO
    with HasPeripheryPWM
    with HasPeripheryI2C {
  override lazy val module = new E300ArtyDevKitSystemModule(this)

  lazy val outside_mclock = Some(InModuleBody { clock })
}
  1. I give a outside clock to E300ArtyDevKitSystem when I use it in the outside.
class Platform(implicit val p: Parameters) extends RawModule {
   val clock_25   = IO(Input(Clock()))
   val clock_125 = IO(Input(Clock()))
   val rstn          = IO(Input(Bool()))
   
   withClockAndReset(clock_125, ~rstn) {
      val sys = Mdule(LazyModule(new E300ArtyDevKitSystem(clock_25)).module)
      ....
   }
}

But this failed: chisel3.internal.ChiselException: Connection between sink (chisel3.core.Clock@70cf8) and source (chisel3.core.Clock@3) failed @: Sink or source unavailable to current module.

Shoule I write module maybe like AsynchronousCrossing to connect outside Clock then use it inside?

@colin4124
Copy link
Author

I use different way to solve problem.

  1. delete the "Specify module clock" in attach method:

    InModuleBody { gpio.module.clock := params.mclock.map(_.getWrappedValue).getOrElse(cbus.module.clock) }
    InModuleBody { gpio.module.reset := params.mreset.map(_.getWrappedValue).getOrElse(cbus.module.reset) }

  2. Add explicitly Clock and Reset to GPIOPortIO

class GPIOPortIO(val c: GPIOParams) extends Bundle {
  val new_clock = Input(Clock())
  val new_reset = Input(Bool())
  val pins = Vec(c.width, new EnhancedPin())
  val iof_0 = if (c.includeIOF) Some(Vec(c.width, new IOFPin).flip) else None
  val iof_1 = if (c.includeIOF) Some(Vec(c.width, new IOFPin).flip) else None
}
  1. Use LazyRawModuleImp and withClockAndReset instead of LazyModuleImp and implicitly clock and reset:
lazy val module = new LazyRawModuleImp(this) {
   withClockAndReset(port.new_clock, port.new_reset) {
      .....
   }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants