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:
parent
fb9dd31374
commit
4d74e8f67f
@ -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)(
|
||||
|
@ -12,30 +12,23 @@ import Chisel._
|
||||
|
||||
import freechips.rocketchip.config._
|
||||
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 TMS = new GPIOPin()
|
||||
val TDI = new GPIOPin()
|
||||
val TDO = new GPIOPin()
|
||||
val TRSTn = if (hasTRSTn) Option(new GPIOPin()) else None
|
||||
val TCK = pingen()
|
||||
val TMS = pingen()
|
||||
val TDI = pingen()
|
||||
val TDO = pingen()
|
||||
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))}
|
||||
|
||||
TDO.outputPin(jtag.TDO.data)
|
||||
TDO.o.oe := jtag.TDO.driven
|
||||
}
|
||||
|
||||
class JTAGGPIOPort(hasTRSTn: Boolean = true)(implicit p: Parameters) extends Module {
|
||||
|
||||
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
|
||||
}
|
||||
|
@ -46,7 +46,6 @@ import freechips.rocketchip.config._
|
||||
import freechips.rocketchip.regmapper._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util.{AsyncResetRegVec, Majority}
|
||||
import sifive.blocks.devices.gpio.{GPIOPinCtrl}
|
||||
|
||||
case class I2CParams(address: BigInt)
|
||||
|
||||
|
@ -21,12 +21,6 @@ trait HasPeripheryI2C extends HasSystemNetworks {
|
||||
|
||||
trait HasPeripheryI2CBundle {
|
||||
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 {
|
||||
|
@ -2,26 +2,22 @@
|
||||
package sifive.blocks.devices.i2c
|
||||
|
||||
import Chisel._
|
||||
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl}
|
||||
import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
|
||||
import sifive.blocks.util.ShiftRegisterInit
|
||||
|
||||
|
||||
class I2CPinsIO extends Bundle {
|
||||
val scl = new GPIOPin
|
||||
val sda = new GPIOPin
|
||||
}
|
||||
class I2CPins[T <: Pin](pingen: () => T) extends Bundle {
|
||||
|
||||
class I2CGPIOPort(syncStages: Int = 0) extends Module {
|
||||
val io = new Bundle{
|
||||
val i2c = new I2CPort().flip()
|
||||
val pins = new I2CPinsIO
|
||||
}
|
||||
val scl: T = pingen()
|
||||
val sda: T = pingen()
|
||||
|
||||
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))
|
||||
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))
|
||||
|
||||
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))
|
||||
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))
|
||||
}
|
||||
}
|
||||
|
@ -6,20 +6,20 @@ import freechips.rocketchip.config.Parameters
|
||||
import freechips.rocketchip.diplomacy._
|
||||
import freechips.rocketchip.tilelink._
|
||||
import freechips.rocketchip.util._
|
||||
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
|
||||
import sifive.blocks.devices.pinctrl.{EnhancedPin}
|
||||
import sifive.blocks.util.{DeglitchShiftRegister, ResetCatchAndSync}
|
||||
|
||||
/* The wrapper handles the Clock and Reset Generation for The AON block itself,
|
||||
and instantiates real pad controls (aka pull-ups)*/
|
||||
|
||||
class MockAONWrapperPMUIO extends Bundle {
|
||||
val dwakeup_n = new GPIOPin()
|
||||
val vddpaden = new GPIOPin()
|
||||
val dwakeup_n = new EnhancedPin()
|
||||
val vddpaden = new EnhancedPin()
|
||||
}
|
||||
|
||||
class MockAONWrapperPadsIO extends Bundle {
|
||||
val erst_n = new GPIOPin()
|
||||
val lfextclk = new GPIOPin()
|
||||
val erst_n = new EnhancedPin()
|
||||
val lfextclk = new EnhancedPin()
|
||||
val pmu = new MockAONWrapperPMUIO()
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
|
||||
// -----------------------------------------------
|
||||
|
||||
// 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.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.
|
||||
// Therefore, the lfclk which comes out of AON is the
|
||||
// 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
|
||||
|
||||
// Drive AON's clock and Reset
|
||||
@ -136,14 +136,14 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
|
||||
// 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))
|
||||
dwakeup_deglitch.clock := lfclk
|
||||
dwakeup_deglitch.io.d := ~dwakeup_n_async
|
||||
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
|
||||
|
96
src/main/scala/devices/pinctrl/PinCtrl.scala
Normal file
96
src/main/scala/devices/pinctrl/PinCtrl.scala
Normal 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
|
||||
}
|
||||
}
|
@ -7,25 +7,22 @@ import freechips.rocketchip.diplomacy.{LazyModule,LazyMultiIOModuleImp}
|
||||
import freechips.rocketchip.chip.HasSystemNetworks
|
||||
import freechips.rocketchip.tilelink.TLFragmenter
|
||||
import freechips.rocketchip.util.HeterogeneousBag
|
||||
|
||||
import sifive.blocks.devices.gpio._
|
||||
import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
|
||||
|
||||
class PWMPortIO(val c: PWMParams) extends Bundle {
|
||||
val port = Vec(c.ncmp, Bool()).asOutput
|
||||
override def cloneType: this.type = new PWMPortIO(c).asInstanceOf[this.type]
|
||||
}
|
||||
|
||||
class PWMPinsIO(val c: PWMParams) extends Bundle {
|
||||
val pwm = Vec(c.ncmp, new GPIOPin)
|
||||
}
|
||||
class PWMPins[T <: Pin] (pingen: ()=> T, val c: PWMParams) extends Bundle {
|
||||
|
||||
class PWMGPIOPort(val c: PWMParams) extends Module {
|
||||
val io = new Bundle {
|
||||
val pwm = new PWMPortIO(c).flip()
|
||||
val pins = new PWMPinsIO(c)
|
||||
}
|
||||
val pwm: Vec[T] = Vec(c.ncmp, pingen())
|
||||
|
||||
GPIOOutputPinCtrl(io.pins.pwm, io.pwm.port.asUInt)
|
||||
def fromPWMPort(port: PWMPortIO) {
|
||||
(pwm zip port.port) foreach {case (pin, port) =>
|
||||
pin.outputPin(port)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case object PeripheryPWMKey extends Field[Seq[PWMParams]]
|
||||
@ -43,11 +40,6 @@ trait HasPeripheryPWM extends HasSystemNetworks {
|
||||
trait HasPeripheryPWMBundle {
|
||||
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 {
|
||||
|
@ -23,11 +23,6 @@ trait HasPeripherySPI extends HasSystemNetworks {
|
||||
trait HasPeripherySPIBundle {
|
||||
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 {
|
||||
@ -55,14 +50,6 @@ trait HasPeripherySPIFlash extends HasSystemNetworks {
|
||||
trait HasPeripherySPIFlashBundle {
|
||||
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 {
|
||||
|
@ -2,33 +2,27 @@
|
||||
package sifive.blocks.devices.spi
|
||||
|
||||
import Chisel._
|
||||
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
|
||||
import sifive.blocks.devices.pinctrl.{PinCtrl, Pin}
|
||||
|
||||
class SPIPinsIO(c: SPIParamsBase) extends SPIBundle(c) {
|
||||
val sck = new GPIOPin
|
||||
val dq = Vec(4, new GPIOPin)
|
||||
val cs = Vec(c.csWidth, new GPIOPin)
|
||||
}
|
||||
class SPIPins[T <: Pin] (pingen: ()=> T, c: SPIParamsBase) extends SPIBundle(c) {
|
||||
|
||||
class SPIGPIOPort(c: SPIParamsBase, syncStages: Int = 0, driveStrength: Bool = Bool(false)) extends Module {
|
||||
val io = new SPIBundle(c) {
|
||||
val spi = new SPIPortIO(c).flip
|
||||
val pins = new SPIPinsIO(c)
|
||||
}
|
||||
val sck: T = pingen()
|
||||
val dq: Vec[T] = Vec(4, pingen())
|
||||
val cs: Vec[T] = Vec(c.csWidth, pingen())
|
||||
|
||||
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))
|
||||
(io.pins.dq zip io.spi.dq).foreach {
|
||||
case (p, s) =>
|
||||
p.o.oval := s.o
|
||||
sck.outputPin(spi.sck, ds = driveStrength)
|
||||
|
||||
(dq zip spi.dq).foreach {case (p, s) =>
|
||||
p.outputPin(s.o, pue = Bool(true), ds = driveStrength)
|
||||
p.o.oe := s.oe
|
||||
p.o.ie := ~s.oe
|
||||
p.o.pue := Bool(true)
|
||||
p.o.ds := driveStrength
|
||||
s.i := ShiftRegister(p.i.ival, syncStages)
|
||||
}
|
||||
|
||||
GPIOOutputPinCtrl(io.pins.cs, io.spi.cs.asUInt)
|
||||
io.pins.cs.foreach(_.o.ds := driveStrength)
|
||||
(cs zip spi.cs) foreach { case (c, s) =>
|
||||
c.outputPin(s, ds = driveStrength)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import freechips.rocketchip.config.Field
|
||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
|
||||
import freechips.rocketchip.chip.HasSystemNetworks
|
||||
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
|
||||
|
||||
case object PeripheryUARTKey extends Field[Seq[UARTParams]]
|
||||
@ -28,11 +28,6 @@ trait HasPeripheryUARTBundle {
|
||||
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 {
|
||||
@ -44,18 +39,14 @@ trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUA
|
||||
}
|
||||
}
|
||||
|
||||
class UARTPinsIO extends Bundle {
|
||||
val rxd = new GPIOPin
|
||||
val txd = new GPIOPin
|
||||
class UARTPins(pingen: () => Pin) extends Bundle {
|
||||
val rxd = pingen()
|
||||
val txd = pingen()
|
||||
|
||||
def fromUARTPort(uart: UARTPortIO, syncStages: Int = 0) {
|
||||
txd.outputPin(uart.txd)
|
||||
val rxd_t = rxd.inputPin()
|
||||
uart.rxd := ShiftRegisterInit(rxd_t, syncStages, Bool(true))
|
||||
}
|
||||
}
|
||||
|
||||
class UARTGPIOPort(syncStages: Int = 0) extends Module {
|
||||
val io = new Bundle{
|
||||
val uart = new UARTPortIO().flip()
|
||||
val pins = new UARTPinsIO
|
||||
}
|
||||
|
||||
GPIOOutputPinCtrl(io.pins.txd, io.uart.txd)
|
||||
val rxd = GPIOInputPinCtrl(io.pins.rxd)
|
||||
io.uart.rxd := ShiftRegisterInit(rxd, syncStages, Bool(true))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user