1
0

Merge pull request #27 from sifive/typed_pad_ctrl

Seperate GPIO Peripheral Functionality
This commit is contained in:
Yunsup Lee 2017-07-25 16:37:46 -07:00 committed by GitHub
commit 86010395ad
14 changed files with 306 additions and 280 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,42 @@ 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 default(): Unit = {
this.o.oval := Bool(false)
this.o.oe := Bool(false)
this.o.ie := Bool(false)
this.o.valid := Bool(false)
}
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 = {
object BasePinToIOF {
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 +74,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 +163,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 +181,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 +225,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)(

View File

@ -11,7 +11,7 @@ case object PeripheryGPIOKey extends Field[Seq[GPIOParams]]
trait HasPeripheryGPIO extends HasPeripheryBus with HasInterruptBus {
val gpioParams = p(PeripheryGPIOKey)
val gpio = gpioParams map { params =>
val gpios = gpioParams map { params =>
val gpio = LazyModule(new TLGPIO(pbus.beatBytes, params))
gpio.node := pbus.toVariableWidthSlaves
ibus.fromSync := gpio.intnode
@ -27,7 +27,7 @@ trait HasPeripheryGPIOModuleImp extends LazyMultiIOModuleImp with HasPeripheryGP
val outer: HasPeripheryGPIO
val gpio = IO(HeterogeneousBag(outer.gpioParams.map(new GPIOPortIO(_))))
(gpio zip outer.gpio) foreach { case (io, device) =>
(gpio zip outer.gpios) foreach { case (io, device) =>
io <> device.module.io.port
}
}

View File

@ -0,0 +1,27 @@
// See LICENSE for license details.
package sifive.blocks.devices.gpio
import Chisel._
import sifive.blocks.devices.pinctrl.{Pin}
// While this is a bit pendantic, it keeps the GPIO
// device more similar to the other devices. It's not 'special'
// even though it looks like something that more directly talks to
// a pin. It also makes it possible to change the exact
// type of pad this connects to.
class GPIOPins[T <: Pin] (pingen: ()=> T, c: GPIOParams) extends Bundle {
val pins = Vec(c.width, pingen())
override def cloneType: this.type =
this.getClass.getConstructors.head.newInstance(pingen, c).asInstanceOf[this.type]
def fromPort(port: GPIOPortIO){
// This will just match up the components of the Bundle that
// exist in both.
(pins zip port.pins) foreach {case (pin, port) =>
pin <> port
}
}
}

View File

@ -1,41 +0,0 @@
// See LICENSE for license details.
package sifive.blocks.devices.gpio
import Chisel._
// ------------------------------------------------------------
// SPI, UART, etc are with their
// respective packages,
// This file is for those that don't seem to have a good place
// to put them otherwise.
// ------------------------------------------------------------
import freechips.rocketchip.config._
import freechips.rocketchip.jtag.{JTAGIO}
class JTAGPinsIO(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
}
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
}

View File

@ -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)

View File

@ -19,20 +19,14 @@ trait HasPeripheryI2C extends HasPeripheryBus {
}
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
}
val i2c: Vec[I2CPort]
}
trait HasPeripheryI2CModuleImp extends LazyMultiIOModuleImp with HasPeripheryI2CBundle {
val outer: HasPeripheryI2C
val i2cs = IO(Vec(outer.i2cParams.size, new I2CPort))
val i2c = IO(Vec(outer.i2cParams.size, new I2CPort))
(i2cs zip outer.i2c).foreach { case (io, device) =>
(i2c zip outer.i2c).foreach { case (io, device) =>
io <> device.module.io.port
}
}

View File

@ -2,26 +2,28 @@
package sifive.blocks.devices.i2c
import Chisel._
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl}
import chisel3.experimental.{withClockAndReset}
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()
override def cloneType: this.type =
this.getClass.getConstructors.head.newInstance(pingen).asInstanceOf[this.type]
def fromPort(i2c: I2CPort, clock: Clock, reset: Bool, syncStages: Int = 0) = {
withClockAndReset(clock, reset) {
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

@ -0,0 +1,33 @@
// See LICENSE for license details.
package sifive.blocks.devices.jtag
import Chisel._
// ------------------------------------------------------------
// SPI, UART, etc are with their respective packages,
// JTAG doesn't really correspond directly to a device, but it does
// define pins as those devices do.
// ------------------------------------------------------------
import freechips.rocketchip.config._
import freechips.rocketchip.jtag.{JTAGIO}
import sifive.blocks.devices.pinctrl.{Pin, PinCtrl}
class JTAGPins[T <: Pin](pingen: () => T, hasTRSTn: Boolean = true) extends Bundle {
val TCK = pingen()
val TMS = pingen()
val TDI = pingen()
val TDO = pingen()
val TRSTn = if (hasTRSTn) Option(pingen()) else None
def fromPort(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
}
}

View File

@ -6,25 +6,25 @@ 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()
class MockAONWrapperPins extends Bundle {
val erst_n = new EnhancedPin()
val lfextclk = new EnhancedPin()
val pmu = new MockAONWrapperPMUIO()
}
class MockAONWrapperBundle extends Bundle {
val pads = new MockAONWrapperPadsIO()
val pins = new MockAONWrapperPins()
val rsts = new MockAONMOffRstIO()
}
@ -61,14 +61,14 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
}
val aon_io = aon.module.io
val pads = io.pads
val pins = io.pins
// -----------------------------------------------
// Generation of aonrst
// -----------------------------------------------
// ERST
val erst = ~ GPIOInputPinCtrl(pads.erst_n, pue = Bool(true))
val erst = ~pins.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 = pins.lfextclk.inputPin(pue=Bool(true))
aon_io.lfextclk := lfextclk.asClock
// Drive AON's clock and Reset
@ -133,17 +133,17 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
isolation.module.io.iso_in := Bool(true)
//--------------------------------------------------
// PMU <--> pads Interface
// PMU <--> pins Interface
//--------------------------------------------------
val dwakeup_n_async = GPIOInputPinCtrl(pads.pmu.dwakeup_n, pue=Bool(true))
val dwakeup_n_async = pins.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)
pins.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
//--------------------------------------------------
// Connect signals to MOFF

View File

@ -0,0 +1,103 @@
//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 default(): Unit
def inputPin(pue: Bool = Bool(false)): Bool
def outputPin(signal: Bool,
pue: Bool = Bool(false),
ds: Bool = Bool(false),
ie: Bool = Bool(false)
): Unit
}
////////////////////////////////////////////////////////////////////////////////////
class BasePin extends Pin() {
val o = new PinCtrl().asOutput
def default(): Unit = {
this.o.oval := Bool(false)
this.o.oe := Bool(false)
this.o.ie := Bool(false)
}
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 default(): Unit = {
this.o.oval := Bool(false)
this.o.oe := Bool(false)
this.o.ie := Bool(false)
this.o.ds := Bool(false)
this.o.pue := Bool(false)
}
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

@ -6,24 +6,25 @@ import freechips.rocketchip.config.Field
import freechips.rocketchip.coreplex.{HasPeripheryBus, HasInterruptBus}
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
import freechips.rocketchip.util.HeterogeneousBag
import sifive.blocks.devices.gpio._
import sifive.blocks.devices.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())
override def cloneType: this.type =
this.getClass.getConstructors.head.newInstance(pingen, c).asInstanceOf[this.type]
def fromPort(port: PWMPortIO) {
(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]]
@ -39,20 +40,15 @@ trait HasPeripheryPWM extends HasPeripheryBus with HasInterruptBus {
}
trait HasPeripheryPWMBundle {
val pwms: HeterogeneousBag[PWMPortIO]
val pwm: 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 {
val outer: HasPeripheryPWM
val pwms = IO(HeterogeneousBag(outer.pwmParams.map(new PWMPortIO(_))))
val pwm = IO(HeterogeneousBag(outer.pwmParams.map(new PWMPortIO(_))))
(pwms zip outer.pwms) foreach { case (io, device) =>
(pwm zip outer.pwms) foreach { case (io, device) =>
io.port := device.module.io.gpio
}
}

View File

@ -21,20 +21,15 @@ trait HasPeripherySPI extends HasPeripheryBus with HasInterruptBus {
}
trait HasPeripherySPIBundle {
val spis: HeterogeneousBag[SPIPortIO]
val spi: 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 {
val outer: HasPeripherySPI
val spis = IO(HeterogeneousBag(outer.spiParams.map(new SPIPortIO(_))))
val spi = IO(HeterogeneousBag(outer.spiParams.map(new SPIPortIO(_))))
(spis zip outer.spis).foreach { case (io, device) =>
(spi zip outer.spis).foreach { case (io, device) =>
io <> device.module.io.port
}
}
@ -43,7 +38,7 @@ case object PeripherySPIFlashKey extends Field[Seq[SPIFlashParams]]
trait HasPeripherySPIFlash extends HasPeripheryBus with HasInterruptBus {
val spiFlashParams = p(PeripherySPIFlashKey)
val qspi = spiFlashParams map { params =>
val qspis = spiFlashParams map { params =>
val qspi = LazyModule(new TLSPIFlash(pbus.beatBytes, params))
qspi.rnode := pbus.toVariableWidthSlaves
qspi.fnode := TLFragmenter(1, pbus.blockBytes)(pbus.toFixedWidthSlaves)
@ -55,21 +50,13 @@ trait HasPeripherySPIFlash extends HasPeripheryBus with HasInterruptBus {
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 {
val outer: HasPeripherySPIFlash
val qspi = IO(HeterogeneousBag(outer.spiFlashParams.map(new SPIPortIO(_))))
(qspi zip outer.qspi) foreach { case (io, device) =>
(qspi zip outer.qspis) foreach { case (io, device) =>
io <> device.module.io.port
}
}

View File

@ -2,33 +2,34 @@
package sifive.blocks.devices.spi
import Chisel._
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
import chisel3.experimental.{withClockAndReset}
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 = pingen()
val dq = Vec(4, pingen())
val cs = Vec(c.csWidth, pingen())
GPIOOutputPinCtrl(io.pins.sck, io.spi.sck, ds = driveStrength)
override def cloneType: this.type =
this.getClass.getConstructors.head.newInstance(pingen, c).asInstanceOf[this.type]
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
def fromPort(spi: SPIPortIO, clock: Clock, reset: Bool,
syncStages: Int = 0, driveStrength: Bool = Bool(false)) {
withClockAndReset(clock, reset) {
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)
}
}
}
}

View File

@ -2,10 +2,11 @@
package sifive.blocks.devices.uart
import Chisel._
import chisel3.experimental.{withClockAndReset}
import freechips.rocketchip.config.Field
import freechips.rocketchip.coreplex.{HasPeripheryBus, PeripheryBusParams, HasInterruptBus}
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
import sifive.blocks.devices.gpio.{GPIOPin, GPIOOutputPinCtrl, GPIOInputPinCtrl}
import sifive.blocks.devices.pinctrl.{Pin}
import sifive.blocks.util.ShiftRegisterInit
case object PeripheryUARTKey extends Field[Seq[UARTParams]]
@ -22,40 +23,36 @@ trait HasPeripheryUART extends HasPeripheryBus with HasInterruptBus {
}
trait HasPeripheryUARTBundle {
val uarts: Vec[UARTPortIO]
val uart: Vec[UARTPortIO]
def tieoffUARTs(dummy: Int = 1) {
uarts.foreach { _.rxd := UInt(1) }
uart.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 {
val outer: HasPeripheryUART
val uarts = IO(Vec(outer.uartParams.size, new UARTPortIO))
val uart = IO(Vec(outer.uartParams.size, new UARTPortIO))
(uarts zip outer.uarts).foreach { case (io, device) =>
(uart zip outer.uarts).foreach { case (io, device) =>
io <> device.module.io.port
}
}
class UARTPinsIO extends Bundle {
val rxd = new GPIOPin
val txd = new GPIOPin
}
class UARTPins[T <: Pin] (pingen: () => T) extends Bundle {
val rxd = pingen()
val txd = pingen()
class UARTGPIOPort(syncStages: Int = 0) extends Module {
val io = new Bundle{
val uart = new UARTPortIO().flip()
val pins = new UARTPinsIO
override def cloneType: this.type =
this.getClass.getConstructors.head.newInstance(pingen).asInstanceOf[this.type]
def fromPort(uart: UARTPortIO, clock: Clock, reset: Bool, syncStages: Int = 0) {
withClockAndReset(clock, reset) {
txd.outputPin(uart.txd)
val rxd_t = rxd.inputPin()
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))
}