1
0

Make it possible to adjust the type of pad controls used,

and seperate out some of the "GPIO Peripheral" from "Pin Control"
This commit is contained in:
Megan Wachs
2017-07-18 10:58:04 -07:00
parent fb9dd31374
commit 4d74e8f67f
11 changed files with 198 additions and 236 deletions

View File

@ -2,6 +2,7 @@
package sifive.blocks.devices.gpio
import Chisel._
import sifive.blocks.devices.pinctrl.{PinCtrl, Pin, BasePin, EnhancedPin, EnhancedPinCtrl}
import freechips.rocketchip.config.Parameters
import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink._
@ -9,28 +10,18 @@ import freechips.rocketchip.util.{AsyncResetRegVec, GenericParameterizedBundle}
case class GPIOParams(address: BigInt, width: Int, includeIOF: Boolean = false)
// YAGNI: Make the PUE, DS, and
// these also optionally HW controllable.
// This is the base class of things you "always"
// want to control from a HW block.
class GPIOCtrl extends Bundle {
val oval = Bool()
val oe = Bool()
val ie = Bool()
}
// This is the actual IOF interface.
// This is the actual IOF interface.pa
// Add a valid bit to indicate whether
// there is something actually connected
// to this.
class GPIOPinIOFCtrl extends GPIOCtrl {
class IOFCtrl extends PinCtrl {
val valid = Bool()
}
// By default,
object GPIOPinIOFCtrl {
def apply(): GPIOPinIOFCtrl = {
val iof = Wire(new GPIOPinIOFCtrl())
object IOFCtrl {
def apply(): IOFCtrl = {
val iof = Wire(new IOFCtrl())
iof.valid := Bool(false)
iof.oval := Bool(false)
iof.oe := Bool(false)
@ -39,53 +30,34 @@ object GPIOPinIOFCtrl {
}
}
// This is the control for a physical
// Pad.
class GPIOPinCtrl extends GPIOCtrl {
val pue = Bool() // Pull-up Enable
val ds = Bool() // Drive Strength
}
object GPIOPinCtrl {
def apply(): GPIOPinCtrl = {
val pin = Wire(new GPIOPinCtrl())
pin.oval := Bool(false)
pin.oe := Bool(false)
pin.pue := Bool(false)
pin.ds := Bool(false)
pin.ie := Bool(false)
pin
}
}
// Package up the inputs and outputs
// for the IOF
class GPIOPinIOF extends Bundle {
val i = new Bundle {
val ival = Bool(INPUT)
class IOFPin extends Pin {
val o = new IOFCtrl().asOutput
def inputPin(pue: Bool = Bool(false) /*ignored*/): Bool = {
this.o.oval := Bool(false)
this.o.oe := Bool(false)
this.o.ie := Bool(true)
this.i.ival
}
def outputPin(signal: Bool,
pue: Bool = Bool(false), /*ignored*/
ds: Bool = Bool(false), /*ignored*/
ie: Bool = Bool(false)
): Unit = {
this.o.oval := signal
this.o.oe := Bool(true)
this.o.ie := ie
}
val o = new GPIOPinIOFCtrl().asOutput
}
// Connect both the i and o side of the pin,
// and drive the valid signal for the IOF.
object GPIOPinToIOF {
def apply (pin: GPIOPin, iof: GPIOPinIOF): Unit = {
def apply(pin: BasePin, iof: IOFPin): Unit = {
iof <> pin
iof.o.valid := Bool(true)
}
}
// Package up the inputs and outputs
// for the Pin
class GPIOPin extends Bundle {
val i = new Bundle {
val ival = Bool(INPUT)
}
val o = new GPIOPinCtrl().asOutput
}
// This is sort of weird because
@ -94,9 +66,9 @@ class GPIOPin extends Bundle {
// outside of RocketChipTop.
class GPIOPortIO(c: GPIOParams) extends GenericParameterizedBundle(c) {
val pins = Vec(c.width, new GPIOPin)
val iof_0 = if (c.includeIOF) Some(Vec(c.width, new GPIOPinIOF).flip) else None
val iof_1 = if (c.includeIOF) Some(Vec(c.width, new GPIOPinIOF).flip) else None
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
}
// It would be better if the IOF were here and
@ -183,15 +155,14 @@ trait HasGPIOModuleContents extends Module with HasRegMap {
// Actual Pinmux
// -------------------------------------------------
val swPinCtrl = Wire(Vec(c.width, new GPIOPinCtrl()))
val swPinCtrl = Wire(Vec(c.width, new EnhancedPinCtrl()))
// This strips off the valid.
val iof0Ctrl = Wire(Vec(c.width, new GPIOCtrl()))
val iof1Ctrl = Wire(Vec(c.width, new GPIOCtrl()))
val iofCtrl = Wire(Vec(c.width, new GPIOCtrl()))
val iofPlusSwPinCtrl = Wire(Vec(c.width, new GPIOPinCtrl()))
val iof0Ctrl = Wire(Vec(c.width, new EnhancedPinCtrl()))
val iof1Ctrl = Wire(Vec(c.width, new EnhancedPinCtrl()))
val iofCtrl = Wire(Vec(c.width, new EnhancedPinCtrl()))
val iofPlusSwPinCtrl = Wire(Vec(c.width, new EnhancedPinCtrl()))
for (pin <- 0 until c.width) {
@ -202,7 +173,7 @@ trait HasGPIOModuleContents extends Module with HasRegMap {
swPinCtrl(pin).ds := dsReg(pin)
swPinCtrl(pin).ie := ieReg.io.q(pin)
val pre_xor = Wire(new GPIOPinCtrl())
val pre_xor = Wire(new EnhancedPinCtrl())
if (c.includeIOF) {
// Allow SW Override for invalid inputs.
@ -246,57 +217,6 @@ trait HasGPIOModuleContents extends Module with HasRegMap {
}
}
object GPIOOutputPinCtrl {
def apply( pin: GPIOPin, signal: Bool,
pue: Bool = Bool(false),
ds: Bool = Bool(false),
ie: Bool = Bool(false)
): Unit = {
pin.o.oval := signal
pin.o.oe := Bool(true)
pin.o.pue := pue
pin.o.ds := ds
pin.o.ie := ie
}
def apply(pins: Vec[GPIOPin], signals: Bits,
pue: Bool, ds: Bool, ie: Bool
): Unit = {
for ((signal, pin) <- (signals.toBools zip pins)) {
apply(pin, signal, pue, ds, ie)
}
}
def apply(pins: Vec[GPIOPin], signals: Bits): Unit = apply(pins, signals,
Bool(false), Bool(false), Bool(false))
}
object GPIOInputPinCtrl {
def apply (pin: GPIOPin, pue: Bool = Bool(false)): Bool = {
pin.o.oval := Bool(false)
pin.o.oe := Bool(false)
pin.o.pue := pue
pin.o.ds := Bool(false)
pin.o.ie := Bool(true)
pin.i.ival
}
def apply (pins: Vec[GPIOPin], pue: Bool): Vec[Bool] = {
val signals = Wire(Vec.fill(pins.size)(Bool(false)))
for ((signal, pin) <- (signals zip pins)) {
signal := GPIOInputPinCtrl(pin, pue)
}
signals
}
def apply (pins: Vec[GPIOPin]): Vec[Bool] = apply(pins, Bool(false))
}
// Magic TL2 Incantation to create a TL2 Slave
class TLGPIO(w: Int, c: GPIOParams)(implicit p: Parameters)
extends TLRegisterRouter(c.address, "gpio", Seq("sifive,gpio0"), interrupts = c.width, beatBytes = w)(