All Downloads are FREE. Search and download functionalities are using the official Maven repository.

spinal.lib.io.Gpio.scala Maven / Gradle / Ivy

The newest version!
package spinal.lib.io

import spinal.core._
import spinal.lib._
import spinal.lib.bus.amba3.apb.{Apb3, Apb3Config, Apb3SlaveFactory}
import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbParameter, BmbSlaveFactory}
import spinal.lib.bus.misc.BusSlaveFactory

object Gpio {
  case class Parameter(width : Int,                   //Number of pin
                       var input : Seq[Int] = null,   //List of pin id which can be inputs (null mean all)
                       var output : Seq[Int]  = null, //List of pin id which can be outputs (null mean all)
                       interrupt : Seq[Int]  = Nil,   //List of pin id which can be used as interrupt source
                       readBufferLength : Int = 2)    //Number of syncronisation stages

  abstract class Ctrl[T <: spinal.core.Data with IMasterSlave](p: Gpio.Parameter,
                                                                busType: HardType[T],
                                                                factory: T => BusSlaveFactory
                                                               ) extends Component {

    if(p.input == null) p.input = (0 until p.width)
    if(p.output == null) p.output = (0 until p.width)

    val io = new Bundle {
      val gpio = master(TriStateArray(p.width bits))
      val bus = slave(busType())
      val interrupt = out(Bits(p.width bits))
    }

    val mapper = factory(io.bus)
    val syncronized = Delay(io.gpio.read, p.readBufferLength)
    val last = RegNext(syncronized)


    for(i <- 0 until p.width){
      if(p.input.contains(i)) mapper.read(syncronized(i), 0x00, i)
      if(p.output.contains(i)) mapper.driveAndRead(io.gpio.write(i), 0x04, i) else io.gpio.write(i) := False
      if(p.output.contains(i) && p.input.contains(i)) mapper.driveAndRead(io.gpio.writeEnable(i), 0x08, i) init(False) else io.gpio.writeEnable(i) := Bool(p.output.contains(i))
    }

    val interrupt = new Area {
      val enable = new Area{
        val high, low, rise, fall = Bits(p.width bits)
      }

      val valid = ((enable.high & syncronized)
                | (enable.low & ~syncronized)
                | (enable.rise & (syncronized & ~last))
                | (enable.fall & (~syncronized & last)))

      for(i <- 0 until p.width){
        if(p.interrupt.contains(i)){
          io.interrupt(i) := valid(i)
          mapper.driveAndRead(enable.rise(i), 0x20,i) init(False)
          mapper.driveAndRead(enable.fall(i), 0x24,i) init(False)
          mapper.driveAndRead(enable.high(i), 0x28,i) init(False)
          mapper.driveAndRead(enable.low(i),  0x2C,i) init(False)
        } else {
          io.interrupt(i) := False
          enable.rise(i) := False
          enable.fall(i) := False
          enable.high(i) := False
          enable.low(i) := False
        }
      }
    }
  }

  def addressWidth = 8
}


case class Apb3Gpio2(  parameter: Gpio.Parameter,
                       busConfig: Apb3Config = Apb3Config(12, 32)
                     ) extends Gpio.Ctrl[Apb3] (
  parameter,
  Apb3(busConfig),
  Apb3SlaveFactory(_)
)
object BmbGpio2{
  def getBmbCapabilities(accessSource : BmbAccessCapabilities) = BmbSlaveFactory.getBmbCapabilities(
    accessSource,
    addressWidth = Gpio.addressWidth,
    dataWidth = 32
  )
}
case class BmbGpio2(   parameter: Gpio.Parameter,
                       busConfig: BmbParameter
                    ) extends Gpio.Ctrl[Bmb] (
  parameter,
  Bmb(busConfig),
  BmbSlaveFactory(_)
)




© 2015 - 2024 Weber Informatics LLC | Privacy Policy