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:
		| @@ -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))} | ||||
|  | ||||
| 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) | ||||
|     TDO.outputPin(jtag.TDO.data) | ||||
|     TDO.o.oe := jtag.TDO.driven | ||||
|   } | ||||
|  | ||||
|   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() | ||||
|  | ||||
|   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)) | ||||
| } | ||||
|   | ||||
| @@ -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()) | ||||
|  | ||||
|   def fromPWMPort(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]] | ||||
| @@ -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)) { | ||||
|      | ||||
|     sck.outputPin(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 | ||||
|     (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) | ||||
|   } | ||||
|     } | ||||
|  | ||||
|   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() | ||||
|  | ||||
| class UARTGPIOPort(syncStages: Int = 0) extends Module { | ||||
|   val io = new Bundle{ | ||||
|     val uart = new UARTPortIO().flip() | ||||
|     val pins = new UARTPinsIO | ||||
|   def fromUARTPort(uart: UARTPortIO, syncStages: Int = 0) { | ||||
|     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)) | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user