Merge pull request #27 from sifive/typed_pad_ctrl
Seperate GPIO Peripheral Functionality
This commit is contained in:
commit
86010395ad
@ -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,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
|
// 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 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,
|
// 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 BasePinToIOF {
|
||||||
|
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 +74,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 +163,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 +181,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 +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
|
// 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)(
|
||||||
|
@ -11,7 +11,7 @@ case object PeripheryGPIOKey extends Field[Seq[GPIOParams]]
|
|||||||
|
|
||||||
trait HasPeripheryGPIO extends HasPeripheryBus with HasInterruptBus {
|
trait HasPeripheryGPIO extends HasPeripheryBus with HasInterruptBus {
|
||||||
val gpioParams = p(PeripheryGPIOKey)
|
val gpioParams = p(PeripheryGPIOKey)
|
||||||
val gpio = gpioParams map { params =>
|
val gpios = gpioParams map { params =>
|
||||||
val gpio = LazyModule(new TLGPIO(pbus.beatBytes, params))
|
val gpio = LazyModule(new TLGPIO(pbus.beatBytes, params))
|
||||||
gpio.node := pbus.toVariableWidthSlaves
|
gpio.node := pbus.toVariableWidthSlaves
|
||||||
ibus.fromSync := gpio.intnode
|
ibus.fromSync := gpio.intnode
|
||||||
@ -27,7 +27,7 @@ trait HasPeripheryGPIOModuleImp extends LazyMultiIOModuleImp with HasPeripheryGP
|
|||||||
val outer: HasPeripheryGPIO
|
val outer: HasPeripheryGPIO
|
||||||
val gpio = IO(HeterogeneousBag(outer.gpioParams.map(new GPIOPortIO(_))))
|
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
|
io <> device.module.io.port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
27
src/main/scala/devices/gpio/GPIOPins.scala
Normal file
27
src/main/scala/devices/gpio/GPIOPins.scala
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
|
||||||
}
|
|
@ -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)
|
||||||
|
|
||||||
|
@ -19,20 +19,14 @@ trait HasPeripheryI2C extends HasPeripheryBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait HasPeripheryI2CBundle {
|
trait HasPeripheryI2CBundle {
|
||||||
val i2cs: Vec[I2CPort]
|
val i2c: 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 {
|
||||||
val outer: HasPeripheryI2C
|
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
|
io <> device.module.io.port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,26 +2,28 @@
|
|||||||
package sifive.blocks.devices.i2c
|
package sifive.blocks.devices.i2c
|
||||||
|
|
||||||
import Chisel._
|
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
|
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
|
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))
|
|
||||||
}
|
}
|
||||||
|
33
src/main/scala/devices/jtag/JTAGPins.scala
Normal file
33
src/main/scala/devices/jtag/JTAGPins.scala
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -6,25 +6,25 @@ 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 MockAONWrapperPins 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
class MockAONWrapperBundle extends Bundle {
|
class MockAONWrapperBundle extends Bundle {
|
||||||
val pads = new MockAONWrapperPadsIO()
|
val pins = new MockAONWrapperPins()
|
||||||
val rsts = new MockAONMOffRstIO()
|
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 aon_io = aon.module.io
|
||||||
val pads = io.pads
|
val pins = io.pins
|
||||||
|
|
||||||
// -----------------------------------------------
|
// -----------------------------------------------
|
||||||
// Generation of aonrst
|
// Generation of aonrst
|
||||||
// -----------------------------------------------
|
// -----------------------------------------------
|
||||||
|
|
||||||
// ERST
|
// 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.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 = pins.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
|
||||||
@ -133,17 +133,17 @@ class MockAONWrapper(w: Int, c: MockAONParams)(implicit p: Parameters) extends L
|
|||||||
isolation.module.io.iso_in := Bool(true)
|
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))
|
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)
|
pins.pmu.vddpaden.outputPin(aon.module.io.pmu.vddpaden)
|
||||||
|
|
||||||
//--------------------------------------------------
|
//--------------------------------------------------
|
||||||
// Connect signals to MOFF
|
// Connect signals to MOFF
|
||||||
|
103
src/main/scala/devices/pinctrl/PinCtrl.scala
Normal file
103
src/main/scala/devices/pinctrl/PinCtrl.scala
Normal 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
|
||||||
|
}
|
||||||
|
}
|
@ -6,24 +6,25 @@ import freechips.rocketchip.config.Field
|
|||||||
import freechips.rocketchip.coreplex.{HasPeripheryBus, HasInterruptBus}
|
import freechips.rocketchip.coreplex.{HasPeripheryBus, HasInterruptBus}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
|
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
|
||||||
import freechips.rocketchip.util.HeterogeneousBag
|
import freechips.rocketchip.util.HeterogeneousBag
|
||||||
import sifive.blocks.devices.gpio._
|
import sifive.blocks.devices.pinctrl.{Pin}
|
||||||
|
|
||||||
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()
|
override def cloneType: this.type =
|
||||||
val pins = new PWMPinsIO(c)
|
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]]
|
case object PeripheryPWMKey extends Field[Seq[PWMParams]]
|
||||||
@ -39,20 +40,15 @@ trait HasPeripheryPWM extends HasPeripheryBus with HasInterruptBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait HasPeripheryPWMBundle {
|
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 {
|
trait HasPeripheryPWMModuleImp extends LazyMultiIOModuleImp with HasPeripheryPWMBundle {
|
||||||
val outer: HasPeripheryPWM
|
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
|
io.port := device.module.io.gpio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,20 +21,15 @@ trait HasPeripherySPI extends HasPeripheryBus with HasInterruptBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait HasPeripherySPIBundle {
|
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 {
|
trait HasPeripherySPIModuleImp extends LazyMultiIOModuleImp with HasPeripherySPIBundle {
|
||||||
val outer: HasPeripherySPI
|
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
|
io <> device.module.io.port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -43,7 +38,7 @@ case object PeripherySPIFlashKey extends Field[Seq[SPIFlashParams]]
|
|||||||
|
|
||||||
trait HasPeripherySPIFlash extends HasPeripheryBus with HasInterruptBus {
|
trait HasPeripherySPIFlash extends HasPeripheryBus with HasInterruptBus {
|
||||||
val spiFlashParams = p(PeripherySPIFlashKey)
|
val spiFlashParams = p(PeripherySPIFlashKey)
|
||||||
val qspi = spiFlashParams map { params =>
|
val qspis = spiFlashParams map { params =>
|
||||||
val qspi = LazyModule(new TLSPIFlash(pbus.beatBytes, params))
|
val qspi = LazyModule(new TLSPIFlash(pbus.beatBytes, params))
|
||||||
qspi.rnode := pbus.toVariableWidthSlaves
|
qspi.rnode := pbus.toVariableWidthSlaves
|
||||||
qspi.fnode := TLFragmenter(1, pbus.blockBytes)(pbus.toFixedWidthSlaves)
|
qspi.fnode := TLFragmenter(1, pbus.blockBytes)(pbus.toFixedWidthSlaves)
|
||||||
@ -55,21 +50,13 @@ trait HasPeripherySPIFlash extends HasPeripheryBus with HasInterruptBus {
|
|||||||
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 {
|
||||||
val outer: HasPeripherySPIFlash
|
val outer: HasPeripherySPIFlash
|
||||||
val qspi = IO(HeterogeneousBag(outer.spiFlashParams.map(new SPIPortIO(_))))
|
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
|
io <> device.module.io.port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,33 +2,34 @@
|
|||||||
package sifive.blocks.devices.spi
|
package sifive.blocks.devices.spi
|
||||||
|
|
||||||
import Chisel._
|
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) {
|
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 = pingen()
|
||||||
val io = new SPIBundle(c) {
|
val dq = Vec(4, pingen())
|
||||||
val spi = new SPIPortIO(c).flip
|
val cs = Vec(c.csWidth, pingen())
|
||||||
val pins = new SPIPinsIO(c)
|
|
||||||
|
override def cloneType: this.type =
|
||||||
|
this.getClass.getConstructors.head.newInstance(pingen, c).asInstanceOf[this.type]
|
||||||
|
|
||||||
|
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
|
||||||
|
s.i := ShiftRegister(p.i.ival, syncStages)
|
||||||
|
}
|
||||||
|
|
||||||
|
(cs zip spi.cs) foreach { case (c, s) =>
|
||||||
|
c.outputPin(s, ds = driveStrength)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GPIOOutputPinCtrl(io.pins.sck, io.spi.sck, ds = driveStrength)
|
|
||||||
|
|
||||||
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
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
package sifive.blocks.devices.uart
|
package sifive.blocks.devices.uart
|
||||||
|
|
||||||
import Chisel._
|
import Chisel._
|
||||||
|
import chisel3.experimental.{withClockAndReset}
|
||||||
import freechips.rocketchip.config.Field
|
import freechips.rocketchip.config.Field
|
||||||
import freechips.rocketchip.coreplex.{HasPeripheryBus, PeripheryBusParams, HasInterruptBus}
|
import freechips.rocketchip.coreplex.{HasPeripheryBus, PeripheryBusParams, HasInterruptBus}
|
||||||
import freechips.rocketchip.diplomacy.{LazyModule, LazyMultiIOModuleImp}
|
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
|
import sifive.blocks.util.ShiftRegisterInit
|
||||||
|
|
||||||
case object PeripheryUARTKey extends Field[Seq[UARTParams]]
|
case object PeripheryUARTKey extends Field[Seq[UARTParams]]
|
||||||
@ -22,40 +23,36 @@ trait HasPeripheryUART extends HasPeripheryBus with HasInterruptBus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait HasPeripheryUARTBundle {
|
trait HasPeripheryUARTBundle {
|
||||||
val uarts: Vec[UARTPortIO]
|
val uart: Vec[UARTPortIO]
|
||||||
|
|
||||||
def tieoffUARTs(dummy: Int = 1) {
|
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 {
|
trait HasPeripheryUARTModuleImp extends LazyMultiIOModuleImp with HasPeripheryUARTBundle {
|
||||||
val outer: HasPeripheryUART
|
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
|
io <> device.module.io.port
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class UARTPinsIO extends Bundle {
|
class UARTPins[T <: Pin] (pingen: () => T) extends Bundle {
|
||||||
val rxd = new GPIOPin
|
val rxd = pingen()
|
||||||
val txd = new GPIOPin
|
val txd = pingen()
|
||||||
}
|
|
||||||
|
|
||||||
class UARTGPIOPort(syncStages: Int = 0) extends Module {
|
override def cloneType: this.type =
|
||||||
val io = new Bundle{
|
this.getClass.getConstructors.head.newInstance(pingen).asInstanceOf[this.type]
|
||||||
val uart = new UARTPortIO().flip()
|
|
||||||
val pins = new UARTPinsIO
|
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))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user