231 lines
8.8 KiB
Scala
231 lines
8.8 KiB
Scala
// See LICENSE for license details.
|
|
package sifive.freedom.everywhere.e300artydevkit
|
|
|
|
import Chisel._
|
|
import config._
|
|
import diplomacy._
|
|
import coreplex._
|
|
import rocketchip._
|
|
import uncore.devices.DebugBusIO
|
|
import sifive.blocks.devices.gpio.{GPIOConfig, PeripheryGPIO, PeripheryGPIOBundle, PeripheryGPIOModule, GPIOPin, GPIOPinToIOF, GPIOPinIOFCtrl, GPIOInputPinCtrl, JTAGPinsIO, JTAGGPIOPort}
|
|
import sifive.blocks.devices.mockaon.{MockAONConfig, PeripheryMockAON, PeripheryMockAONBundle, PeripheryMockAONModule, MockAONWrapperPadsIO}
|
|
import sifive.blocks.devices.pwm.{PWMConfig, PeripheryPWM, PeripheryPWMBundle, PeripheryPWMModule, PWMGPIOPort}
|
|
import sifive.blocks.devices.spi.{SPIConfig, PeripherySPI, PeripherySPIBundle, PeripherySPIModule, SPIFlashConfig, PeripherySPIFlash, PeripherySPIFlashBundle, PeripherySPIFlashModule, SPIPinsIO, SPIGPIOPort}
|
|
import sifive.blocks.devices.uart.{UARTConfig, PeripheryUART, PeripheryUARTBundle, PeripheryUARTModule, UARTGPIOPort}
|
|
import sifive.blocks.util.ResetCatchAndSync
|
|
import util._
|
|
|
|
// Coreplex and Periphery
|
|
|
|
trait E300ArtyDevKitPeripheryConfigs {
|
|
val mockAONConfig = MockAONConfig(address = 0x10000000)
|
|
val gpioConfig = GPIOConfig(address = 0x10012000, width = 32)
|
|
val pwmConfigs = List(
|
|
PWMConfig(address = 0x10015000, cmpWidth = 8),
|
|
PWMConfig(address = 0x10025000, cmpWidth = 16),
|
|
PWMConfig(address = 0x10035000, cmpWidth = 16))
|
|
val spiConfigs = List(
|
|
SPIConfig(csWidth = 4, rAddress = 0x10024000, sampleDelay = 3),
|
|
SPIConfig(csWidth = 1, rAddress = 0x10034000, sampleDelay = 3))
|
|
val spiFlashConfig = SPIFlashConfig(
|
|
fAddress = 0x20000000, rAddress = 0x10014000, sampleDelay = 3)
|
|
val uartConfigs = List(
|
|
UARTConfig(address = 0x10013000),
|
|
UARTConfig(address = 0x10023000))
|
|
}
|
|
|
|
// This custom E300ArtyDevKit coreplex has no port into the L2 and no memory subsystem
|
|
|
|
class E300ArtyDevKitCoreplex(implicit p: Parameters) extends BareCoreplex
|
|
with CoreplexNetwork
|
|
with CoreplexRISCVPlatform
|
|
with RocketTiles {
|
|
override lazy val module = new E300ArtyDevKitCoreplexModule(this, () => new E300ArtyDevKitCoreplexBundle(this))
|
|
}
|
|
|
|
class E300ArtyDevKitCoreplexBundle[+L <: E300ArtyDevKitCoreplex](_outer: L) extends BareCoreplexBundle(_outer)
|
|
with CoreplexNetworkBundle
|
|
with CoreplexRISCVPlatformBundle
|
|
with RocketTilesBundle
|
|
|
|
class E300ArtyDevKitCoreplexModule[+L <: E300ArtyDevKitCoreplex, +B <: E300ArtyDevKitCoreplexBundle[L]](_outer: L, _io: () => B)
|
|
extends BareCoreplexModule(_outer, _io)
|
|
with CoreplexNetworkModule
|
|
with CoreplexRISCVPlatformModule
|
|
with RocketTilesModule
|
|
|
|
class E300ArtyDevKitSystem(implicit p: Parameters) extends BaseTop
|
|
with E300ArtyDevKitPeripheryConfigs
|
|
with PeripheryBootROM
|
|
with PeripheryDebug
|
|
with PeripheryMockAON
|
|
with PeripheryUART
|
|
with PeripherySPIFlash
|
|
with PeripherySPI
|
|
with PeripheryGPIO
|
|
with PeripheryPWM
|
|
with HardwiredResetVector {
|
|
override lazy val module = new E300ArtyDevKitSystemModule(this, () => new E300ArtyDevKitSystemBundle(this))
|
|
|
|
val coreplex = LazyModule(new E300ArtyDevKitCoreplex)
|
|
socBus.node := coreplex.mmio
|
|
coreplex.mmioInt := intBus.intnode
|
|
}
|
|
|
|
class E300ArtyDevKitSystemBundle[+L <: E300ArtyDevKitSystem](_outer: L) extends BaseTopBundle(_outer)
|
|
with E300ArtyDevKitPeripheryConfigs
|
|
with PeripheryBootROMBundle
|
|
with PeripheryDebugBundle
|
|
with PeripheryUARTBundle
|
|
with PeripherySPIBundle
|
|
with PeripheryGPIOBundle
|
|
with PeripherySPIFlashBundle
|
|
with PeripheryMockAONBundle
|
|
with PeripheryPWMBundle
|
|
with HardwiredResetVectorBundle
|
|
|
|
class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem, +B <: E300ArtyDevKitSystemBundle[L]](_outer: L, _io: () => B)
|
|
extends BaseTopModule(_outer, _io)
|
|
with E300ArtyDevKitPeripheryConfigs
|
|
with PeripheryBootROMModule
|
|
with PeripheryDebugModule
|
|
with PeripheryUARTModule
|
|
with PeripherySPIModule
|
|
with PeripheryGPIOModule
|
|
with PeripherySPIFlashModule
|
|
with PeripheryMockAONModule
|
|
with PeripheryPWMModule
|
|
with HardwiredResetVectorModule
|
|
|
|
// Top
|
|
|
|
class E300ArtyDevKitTopIO(implicit val p: Parameters) extends Bundle with E300ArtyDevKitPeripheryConfigs {
|
|
val pads = new Bundle {
|
|
val jtag = new JTAGPinsIO
|
|
val gpio = Vec(gpioConfig.width, new GPIOPin)
|
|
val qspi = new SPIPinsIO(spiFlashConfig)
|
|
val aon = new MockAONWrapperPadsIO()
|
|
}
|
|
}
|
|
|
|
class E300ArtyDevKitTop(implicit val p: Parameters) extends Module with E300ArtyDevKitPeripheryConfigs {
|
|
val sys = Module(LazyModule(new E300ArtyDevKitSystem).module)
|
|
val io = new E300ArtyDevKitTopIO
|
|
|
|
// This needs to be de-asserted synchronously to the coreClk.
|
|
val async_corerst = sys.io.aon.rsts.corerst
|
|
sys.reset := ResetCatchAndSync(clock, async_corerst, 20)
|
|
|
|
// ------------------------------------------------------------
|
|
// Check for unsupported RCT Connections
|
|
// ------------------------------------------------------------
|
|
|
|
require (p(NExtTopInterrupts) == 0, "No Top-level interrupts supported");
|
|
|
|
// ------------------------------------------------------------
|
|
// Build GPIO Pin Mux
|
|
// ------------------------------------------------------------
|
|
|
|
// Pin Mux for UART, SPI, PWM
|
|
// First convert the System outputs into "IOF" using the respective *GPIOPort
|
|
// converters.
|
|
val sys_uarts = sys.io.uarts
|
|
val sys_pwms = sys.io.pwms
|
|
val sys_spis = sys.io.spis
|
|
|
|
val uart_pins = uartConfigs.map { c => Module (new UARTGPIOPort) }
|
|
val pwm_pins = pwmConfigs.map { c => Module (new PWMGPIOPort(c.bc)) }
|
|
val spi_pins = spiConfigs.map { c => Module (new SPIGPIOPort(c)) }
|
|
|
|
(uart_pins zip sys_uarts) map {case (p, r) => p.io.uart <> r}
|
|
(pwm_pins zip sys_pwms) map {case (p, r) => p.io.pwm <> r}
|
|
(spi_pins zip sys_spis) map {case (p, r) => p.io.spi <> r}
|
|
|
|
// ------------------------------------------------------------
|
|
// Default Pin connections before attaching pinmux
|
|
|
|
for (iof_0 <- sys.io.gpio.iof_0) {
|
|
iof_0.o := GPIOPinIOFCtrl()
|
|
}
|
|
|
|
for (iof_1 <- sys.io.gpio.iof_1) {
|
|
iof_1.o := GPIOPinIOFCtrl()
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// TODO: Make this mapping more programmatic.
|
|
|
|
val iof_0 = sys.io.gpio.iof_0
|
|
val iof_1 = sys.io.gpio.iof_1
|
|
|
|
// SPI1 (0 is the dedicated)
|
|
GPIOPinToIOF(spi_pins(0).io.pins.cs(0), iof_0(2))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.dq(0), iof_0(3))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.dq(1), iof_0(4))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.sck, iof_0(5))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.dq(2), iof_0(6))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.dq(3), iof_0(7))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.cs(1), iof_0(8))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.cs(2), iof_0(9))
|
|
GPIOPinToIOF(spi_pins(0).io.pins.cs(3), iof_0(10))
|
|
|
|
// SPI2
|
|
GPIOPinToIOF(spi_pins(1).io.pins.cs(0), iof_0(26))
|
|
GPIOPinToIOF(spi_pins(1).io.pins.dq(0), iof_0(27))
|
|
GPIOPinToIOF(spi_pins(1).io.pins.dq(1), iof_0(28))
|
|
GPIOPinToIOF(spi_pins(1).io.pins.sck, iof_0(29))
|
|
GPIOPinToIOF(spi_pins(1).io.pins.dq(2), iof_0(30))
|
|
GPIOPinToIOF(spi_pins(1).io.pins.dq(3), iof_0(31))
|
|
|
|
// UART0
|
|
GPIOPinToIOF(uart_pins(0).io.pins.rxd, iof_0(16))
|
|
GPIOPinToIOF(uart_pins(0).io.pins.txd, iof_0(17))
|
|
|
|
// UART1
|
|
GPIOPinToIOF(uart_pins(1).io.pins.rxd, iof_0(24))
|
|
GPIOPinToIOF(uart_pins(1).io.pins.txd, iof_0(25))
|
|
|
|
//PWM
|
|
GPIOPinToIOF(pwm_pins(0).io.pins.pwm(0), iof_1(0) )
|
|
GPIOPinToIOF(pwm_pins(0).io.pins.pwm(1), iof_1(1) )
|
|
GPIOPinToIOF(pwm_pins(0).io.pins.pwm(2), iof_1(2) )
|
|
GPIOPinToIOF(pwm_pins(0).io.pins.pwm(3), iof_1(3) )
|
|
|
|
GPIOPinToIOF(pwm_pins(1).io.pins.pwm(1), iof_1(19))
|
|
GPIOPinToIOF(pwm_pins(1).io.pins.pwm(0), iof_1(20))
|
|
GPIOPinToIOF(pwm_pins(1).io.pins.pwm(2), iof_1(21))
|
|
GPIOPinToIOF(pwm_pins(1).io.pins.pwm(3), iof_1(22))
|
|
|
|
GPIOPinToIOF(pwm_pins(2).io.pins.pwm(0), iof_1(10))
|
|
GPIOPinToIOF(pwm_pins(2).io.pins.pwm(1), iof_1(11))
|
|
GPIOPinToIOF(pwm_pins(2).io.pins.pwm(2), iof_1(12))
|
|
GPIOPinToIOF(pwm_pins(2).io.pins.pwm(3), iof_1(13))
|
|
|
|
// ------------------------------------------------------------
|
|
// Drive actual Pads
|
|
// ------------------------------------------------------------
|
|
|
|
// Result of Pin Mux
|
|
io.pads.gpio <> sys.io.gpio.pins
|
|
|
|
val dedicated_spi_pins = Module (new SPIGPIOPort(spiFlashConfig, syncStages=3, driveStrength=Bool(true)))
|
|
dedicated_spi_pins.clock := sys.clock
|
|
dedicated_spi_pins.reset := sys.reset
|
|
io.pads.qspi <> dedicated_spi_pins.io.pins
|
|
dedicated_spi_pins.io.spi <> sys.io.qspi
|
|
|
|
// JTAG Debug Interface
|
|
|
|
val jtag_pins = Module (new JTAGGPIOPort(true))
|
|
io.pads.jtag <> jtag_pins.io.pins
|
|
sys.io.jtag.get <> jtag_pins.io.jtag
|
|
// Override TRST to reset this logic IFF the core is in reset.
|
|
// This will require 3 ticks of TCK before the debug logic
|
|
// comes out of reset, but JTAG needs 5 ticks anyway.
|
|
// This means that the "real" TRST is never actually used in this design.
|
|
sys.io.jtag.get.TRST := ResetCatchAndSync(sys.io.jtag.get.TCK, async_corerst)
|
|
|
|
// AON Pads
|
|
io.pads.aon <> sys.io.aon.pads
|
|
}
|