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

View File

@ -12,30 +12,23 @@ import Chisel._
import freechips.rocketchip.config._ import freechips.rocketchip.config._
import freechips.rocketchip.jtag.{JTAGIO} import freechips.rocketchip.jtag.{JTAGIO}
import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
class JTAGPinsIO(hasTRSTn: Boolean = true) extends Bundle { class JTAGPins[T <: Pin](pingen: () => T, hasTRSTn: Boolean = true) extends Bundle {
val TCK = new GPIOPin() val TCK = pingen()
val TMS = new GPIOPin() val TMS = pingen()
val TDI = new GPIOPin() val TDI = pingen()
val TDO = new GPIOPin() val TDO = pingen()
val TRSTn = if (hasTRSTn) Option(new GPIOPin()) else None val TRSTn = if (hasTRSTn) Option(pingen()) else None
} def fromJTAGPort(jtag: JTAGIO): Unit = {
jtag.TCK := TCK.inputPin (pue = Bool(true)).asClock
jtag.TMS := TMS.inputPin (pue = Bool(true))
jtag.TDI := TDI.inputPin(pue = Bool(true))
jtag.TRSTn.foreach{t => t := TRSTn.get.inputPin(pue = Bool(true))}
class JTAGGPIOPort(hasTRSTn: Boolean = true)(implicit p: Parameters) extends Module { TDO.outputPin(jtag.TDO.data)
TDO.o.oe := jtag.TDO.driven
val io = new Bundle {
// TODO: make this not hard-coded true.
val jtag = new JTAGIO(hasTRSTn)
val pins = new JTAGPinsIO(hasTRSTn)
} }
io.jtag.TCK := GPIOInputPinCtrl(io.pins.TCK, pue = Bool(true)).asClock
io.jtag.TMS := GPIOInputPinCtrl(io.pins.TMS, pue = Bool(true))
io.jtag.TDI := GPIOInputPinCtrl(io.pins.TDI, pue = Bool(true))
io.jtag.TRSTn.foreach{t => t := GPIOInputPinCtrl(io.pins.TRSTn.get, pue = Bool(true))}
GPIOOutputPinCtrl(io.pins.TDO, io.jtag.TDO.data)
io.pins.TDO.o.oe := io.jtag.TDO.driven
} }

View File

@ -46,7 +46,6 @@ import freechips.rocketchip.config._
import freechips.rocketchip.regmapper._ import freechips.rocketchip.regmapper._
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util.{AsyncResetRegVec, Majority} import freechips.rocketchip.util.{AsyncResetRegVec, Majority}
import sifive.blocks.devices.gpio.{GPIOPinCtrl}
case class I2CParams(address: BigInt) case class I2CParams(address: BigInt)

View File

@ -21,12 +21,6 @@ trait HasPeripheryI2C extends HasSystemNetworks {
trait HasPeripheryI2CBundle { trait HasPeripheryI2CBundle {
val i2cs: Vec[I2CPort] val i2cs: Vec[I2CPort]
def I2CtoGPIOPins(syncStages: Int = 0): Seq[I2CPinsIO] = i2cs.map { i =>
val pins = Module(new I2CGPIOPort(syncStages))
pins.io.i2c <> i
pins.io.pins
}
} }
trait HasPeripheryI2CModuleImp extends LazyMultiIOModuleImp with HasPeripheryI2CBundle { trait HasPeripheryI2CModuleImp extends LazyMultiIOModuleImp with HasPeripheryI2CBundle {

View File

@ -2,26 +2,22 @@
package sifive.blocks.devices.i2c package sifive.blocks.devices.i2c
import Chisel._ import Chisel._
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl} import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
import sifive.blocks.util.ShiftRegisterInit import sifive.blocks.util.ShiftRegisterInit
class I2CPinsIO extends Bundle { class I2CPins[T <: Pin](pingen: () => T) extends Bundle {
val scl = new GPIOPin
val sda = new GPIOPin
}
class I2CGPIOPort(syncStages: Int = 0) extends Module { val scl: T = pingen()
val io = new Bundle{ val sda: T = pingen()
val i2c = new I2CPort().flip()
val pins = new I2CPinsIO def fromI2CPort(i2c: I2CPort, syncStages: Int = 0) = {
scl.outputPin(i2c.scl.out, pue=true.B, ie = true.B)
scl.o.oe := i2c.scl.oe
i2c.scl.in := ShiftRegisterInit(scl.i.ival, syncStages, Bool(true))
sda.outputPin(i2c.sda.out, pue=true.B, ie = true.B)
sda.o.oe := i2c.sda.oe
i2c.sda.in := ShiftRegisterInit(sda.i.ival, syncStages, Bool(true))
} }
GPIOOutputPinCtrl(io.pins.scl, io.i2c.scl.out, pue=true.B, ie = true.B)
io.pins.scl.o.oe := io.i2c.scl.oe
io.i2c.scl.in := ShiftRegisterInit(io.pins.scl.i.ival, syncStages, Bool(true))
GPIOOutputPinCtrl(io.pins.sda, io.i2c.sda.out, pue=true.B, ie = true.B)
io.pins.sda.o.oe := io.i2c.sda.oe
io.i2c.sda.in := ShiftRegisterInit(io.pins.sda.i.ival, syncStages, Bool(true))
} }

View File

@ -6,20 +6,20 @@ import freechips.rocketchip.config.Parameters
import freechips.rocketchip.diplomacy._ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.tilelink._ import freechips.rocketchip.tilelink._
import freechips.rocketchip.util._ import freechips.rocketchip.util._
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl} import sifive.blocks.devices.pinctrl.{EnhancedPin}
import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync} import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync}
/* The wrapper handles the Clock and Reset Generation for The AON block itself, /* The wrapper handles the Clock and Reset Generation for The AON block itself,
and instantiates real pad controls (aka pull-ups)*/ and instantiates real pad controls (aka pull-ups)*/
class MockAONWrapperPMUIO extends Bundle { class MockAONWrapperPMUIO extends Bundle {
val dwakeup_n = new GPIOPin() val dwakeup_n = new EnhancedPin()
val vddpaden = new GPIOPin() val vddpaden = new EnhancedPin()
} }
class MockAONWrapperPadsIO extends Bundle { class MockAONWrapperPadsIO extends Bundle {
val erst_n = new GPIOPin() val erst_n = new EnhancedPin()
val lfextclk = new GPIOPin() val lfextclk = new EnhancedPin()
val pmu = new MockAONWrapperPMUIO() val pmu = new MockAONWrapperPMUIO()
} }
@ -68,7 +68,7 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
// ----------------------------------------------- // -----------------------------------------------
// ERST // ERST
val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true)) val erst = ~pads.erst_n.inputPin(pue = Bool(true))
aon_io.resetCauses.erst := erst aon_io.resetCauses.erst := erst
aon_io.resetCauses.wdogrst := aon_io.wdog_rst aon_io.resetCauses.wdogrst := aon_io.wdog_rst
@ -94,7 +94,7 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
// Note that the actual mux lives inside AON itself. // Note that the actual mux lives inside AON itself.
// Therefore, the lfclk which comes out of AON is the // Therefore, the lfclk which comes out of AON is the
// true clock that AON and AONWrapper are running off of. // true clock that AON and AONWrapper are running off of.
val lfextclk = GPIOInputPinCtrl(pads.lfextclk, pue=Bool(true)) val lfextclk = pads.lfextclk.inputPin(pue=Bool(true))
aon_io.lfextclk := lfextclk.asClock aon_io.lfextclk := lfextclk.asClock
// Drive AON's clock and Reset // Drive AON's clock and Reset
@ -136,14 +136,14 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
// PMU <--> pads Interface // PMU <--> pads Interface
//-------------------------------------------------- //--------------------------------------------------
val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true)) val dwakeup_n_async = pads.pmu.dwakeup_n.inputPin(pue=Bool(true))
val dwakeup_deglitch = Module (new DeglitchShiftRegister(3)) val dwakeup_deglitch = Module (new DeglitchShiftRegister(3))
dwakeup_deglitch.clock := lfclk dwakeup_deglitch.clock := lfclk
dwakeup_deglitch.io.d := ~dwakeup_n_async dwakeup_deglitch.io.d := ~dwakeup_n_async
aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q aon.module.io.pmu.dwakeup := dwakeup_deglitch.io.q
GPIOOutputPinCtrl(pads.pmu.vddpaden, aon.module.io.pmu.vddpaden) pads.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
//-------------------------------------------------- //--------------------------------------------------
// Connect signals to MOFF // Connect signals to MOFF

View File

@ -0,0 +1,96 @@
//See LICENSE for license details
package sifive.blocks.devices.pinctrl
import Chisel._
// This is the base class of things you "always"
// want to control from a HW block.
class PinCtrl extends Bundle {
val oval = Bool()
val oe = Bool()
val ie = Bool()
}
// Package up the inputs and outputs
// for the Pin
abstract class Pin extends Bundle {
val i = new Bundle {
val ival = Bool(INPUT)
}
val o: PinCtrl
// Must be defined by the subclasses
def inputPin(pue: Bool = Bool(false)): Bool
def outputPin(signal: Bool,
pue: Bool = Bool(false),
ds: Bool = Bool(false),
ie: Bool = Bool(false)
): Unit
def inputPin(pins: Vec[this.type], pue: Bool): Vec[Bool] = {
val signals = Wire(Vec(pins.length, new Bool()))
for ((signal, pin) <- (signals zip pins)) {
signal := pin.inputPin(pue)
}
signals
}
}
////////////////////////////////////////////////////////////////////////////////////
class BasePin extends Pin() {
val o = new PinCtrl().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
}
}
/////////////////////////////////////////////////////////////////////////
class EnhancedPinCtrl extends PinCtrl {
val pue = Bool()
val ds = Bool()
}
class EnhancedPin extends Pin() {
val o = new EnhancedPinCtrl().asOutput
def inputPin(pue: Bool = Bool(false)): Bool = {
this.o.oval := Bool(false)
this.o.oe := Bool(false)
this.o.pue := pue
this.o.ds := Bool(false)
this.o.ie := Bool(true)
this.i.ival
}
def outputPin(signal: Bool,
pue: Bool = Bool(false),
ds: Bool = Bool(false),
ie: Bool = Bool(false)
): Unit = {
this.o.oval := signal
this.o.oe := Bool(true)
this.o.pue := pue
this.o.ds := ds
this.o.ie := ie
}
}

View File

@ -7,25 +7,22 @@ import freechips.rocketchip.diplomacy.{LazyModule,LazyMultiIOModuleImp}
import freechips.rocketchip.chip.HasSystemNetworks import freechips.rocketchip.chip.HasSystemNetworks
import freechips.rocketchip.tilelink.TLFragmenter import freechips.rocketchip.tilelink.TLFragmenter
import freechips.rocketchip.util.HeterogeneousBag import freechips.rocketchip.util.HeterogeneousBag
import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
import sifive.blocks.devices.gpio._
class PWMPortIO(val c: PWMParams) extends Bundle { class PWMPortIO(val c: PWMParams) extends Bundle {
val port = Vec(c.ncmp, Bool()).asOutput val port = Vec(c.ncmp, Bool()).asOutput
override def cloneType: this.type = new PWMPortIO(c).asInstanceOf[this.type] override def cloneType: this.type = new PWMPortIO(c).asInstanceOf[this.type]
} }
class PWMPinsIO(val c: PWMParams) extends Bundle { class PWMPins[T <: Pin] (pingen: ()=> T, val c: PWMParams) extends Bundle {
val pwm = Vec(c.ncmp, new GPIOPin)
}
class PWMGPIOPort(val c: PWMParams) extends Module { val pwm: Vec[T] = Vec(c.ncmp, pingen())
val io = new Bundle {
val pwm = new PWMPortIO(c).flip() def fromPWMPort(port: PWMPortIO) {
val pins = new PWMPinsIO(c) (pwm zip port.port) foreach {case (pin, port) =>
pin.outputPin(port)
}
} }
GPIOOutputPinCtrl(io.pins.pwm, io.pwm.port.asUInt)
} }
case object PeripheryPWMKey extends Field[Seq[PWMParams]] case object PeripheryPWMKey extends Field[Seq[PWMParams]]
@ -43,11 +40,6 @@ trait HasPeripheryPWM extends HasSystemNetworks {
trait HasPeripheryPWMBundle { trait HasPeripheryPWMBundle {
val pwms: HeterogeneousBag[PWMPortIO] val pwms: HeterogeneousBag[PWMPortIO]
def PWMtoGPIOPins(dummy: Int = 1): Seq[PWMPinsIO] = pwms.map { p =>
val pins = Module(new PWMGPIOPort(p.c))
pins.io.pwm <> p
pins.io.pins
}
} }
trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp with HasPeripheryPWMBundle { trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp with HasPeripheryPWMBundle {

View File

@ -23,11 +23,6 @@ trait HasPeripherySPI extends HasSystemNetworks {
trait HasPeripherySPIBundle { trait HasPeripherySPIBundle {
val spis: HeterogeneousBag[SPIPortIO] val spis: HeterogeneousBag[SPIPortIO]
def SPItoGPIOPins(syncStages: Int = 0): Seq[SPIPinsIO] = spis.map { s =>
val pins = Module(new SPIGPIOPort(s.c, syncStages))
pins.io.spi <> s
pins.io.pins
}
} }
trait HasPeripherySPIModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIBundle { trait HasPeripherySPIModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIBundle {
@ -55,14 +50,6 @@ trait HasPeripherySPIFlash extends HasSystemNetworks {
trait HasPeripherySPIFlashBundle { trait HasPeripherySPIFlashBundle {
val qspi: HeterogeneousBag[SPIPortIO] val qspi: HeterogeneousBag[SPIPortIO]
// It is important for SPIFlash that the syncStages is agreed upon, because
// internally it needs to realign the input data to the output SCK.
// Therefore, we rely on the syncStages parameter.
def SPIFlashtoGPIOPins(syncStages: Int = 0): Seq[SPIPinsIO] = qspi.map { s =>
val pins = Module(new SPIGPIOPort(s.c, syncStages))
pins.io.spi <> s
pins.io.pins
}
} }
trait HasPeripherySPIFlashModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIFlashBundle { trait HasPeripherySPIFlashModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIFlashBundle {

View File

@ -2,33 +2,27 @@
package sifive.blocks.devices.spi package sifive.blocks.devices.spi
import Chisel._ import Chisel._
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl} import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
class SPIPinsIO(c: SPIParamsBase) extends SPIBundle(c) { class SPIPins[T <: Pin] (pingen: ()=> T, c: SPIParamsBase) extends SPIBundle(c) {
val sck = new GPIOPin
val dq = Vec(4, new GPIOPin)
val cs = Vec(c.csWidth, new GPIOPin)
}
class SPIGPIOPort(c: SPIParamsBase, syncStages: Int = 0, driveStrength: Bool = Bool(false)) extends Module { val sck: T = pingen()
val io = new SPIBundle(c) { val dq: Vec[T] = Vec(4, pingen())
val spi = new SPIPortIO(c).flip val cs: Vec[T] = Vec(c.csWidth, pingen())
val pins = new SPIPinsIO(c)
}
GPIOOutputPinCtrl(io.pins.sck, io.spi.sck, ds = driveStrength) def fromSPIPort(spi: SPIPortIO, syncStages: Int = 0, driveStrength: Bool = Bool(false)) {
GPIOOutputPinCtrl(io.pins.dq, Bits(0, io.spi.dq.size)) sck.outputPin(spi.sck, ds = driveStrength)
(io.pins.dq zip io.spi.dq).foreach {
case (p, s) => (dq zip spi.dq).foreach {case (p, s) =>
p.o.oval := s.o p.outputPin(s.o, pue = Bool(true), ds = driveStrength)
p.o.oe := s.oe p.o.oe := s.oe
p.o.ie := ~s.oe p.o.ie := ~s.oe
p.o.pue := Bool(true)
p.o.ds := driveStrength
s.i := ShiftRegister(p.i.ival, syncStages) s.i := ShiftRegister(p.i.ival, syncStages)
} }
GPIOOutputPinCtrl(io.pins.cs, io.spi.cs.asUInt) (cs zip spi.cs) foreach { case (c, s) =>
io.pins.cs.foreach(_.o.ds := driveStrength) c.outputPin(s, ds = driveStrength)
}
}
} }

View File

@ -6,7 +6,7 @@ import freechips.rocketchip.config.Field
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp} import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
import freechips.rocketchip.chip.HasSystemNetworks import freechips.rocketchip.chip.HasSystemNetworks
import freechips.rocketchip.tilelink.TLFragmenter import freechips.rocketchip.tilelink.TLFragmenter
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl} import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
import sifive.blocks.util.ShiftRegisterInit import sifive.blocks.util.ShiftRegisterInit
case object PeripheryUARTKey extends Field[Seq[UARTParams]] case object PeripheryUARTKey extends Field[Seq[UARTParams]]
@ -28,11 +28,6 @@ trait HasPeripheryUARTBundle {
uarts.foreach { _.rxd := UInt(1) } uarts.foreach { _.rxd := UInt(1) }
} }
def UARTtoGPIOPins(syncStages: Int = 0): Seq[UARTPinsIO] = uarts.map { u =>
val pins = Module(new UARTGPIOPort(syncStages))
pins.io.uart <> u
pins.io.pins
}
} }
trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUARTBundle { trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUARTBundle {
@ -44,18 +39,14 @@ trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUA
} }
} }
class UARTPinsIO extends Bundle { class UARTPins(pingen: () => Pin) extends Bundle {
val rxd = new GPIOPin val rxd = pingen()
val txd = new GPIOPin val txd = pingen()
}
class UARTGPIOPort(syncStages: Int = 0) extends Module { def fromUARTPort(uart: UARTPortIO, syncStages: Int = 0) {
val io = new Bundle{ txd.outputPin(uart.txd)
val uart = new UARTPortIO().flip() val rxd_t = rxd.inputPin()
val pins = new UARTPinsIO uart.rxd := ShiftRegisterInit(rxd_t, syncStages, Bool(true))
} }
GPIOOutputPinCtrl(io.pins.txd, io.uart.txd)
val rxd = GPIOInputPinCtrl(io.pins.rxd)
io.uart.rxd := ShiftRegisterInit(rxd, syncStages, Bool(true))
} }