1
0
Fork 0
sifive-blocks/src/main/scala/devices/spi/TLSPI.scala

133 lines
3.8 KiB
Scala

// See LICENSE for license details.
package sifive.blocks.devices.spi
import Chisel._
import config._
import uncore.tilelink2._
import diplomacy._
import regmapper._
import junctions._
import rocketchip.PeripheryBusConfig
import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
trait SPIConfigBase {
val rAddress: BigInt
val rSize: BigInt
val rxDepth: Int
val txDepth: Int
val csWidth: Int
val frameBits: Int
val delayBits: Int
val divisorBits: Int
val sampleDelay: Int
lazy val csIdBits = log2Up(csWidth)
lazy val lengthBits = log2Floor(frameBits) + 1
lazy val countBits = math.max(lengthBits, delayBits)
lazy val txDepthBits = log2Floor(txDepth) + 1
lazy val rxDepthBits = log2Floor(rxDepth) + 1
lazy val bc = new SPIBundleConfig(csWidth)
}
case class SPIConfig(
rAddress: BigInt,
rSize: BigInt = 0x1000,
rxDepth: Int = 8,
txDepth: Int = 8,
csWidth: Int = 1,
frameBits: Int = 8,
delayBits: Int = 8,
divisorBits: Int = 12,
sampleDelay: Int = 2)
extends SPIConfigBase {
require(frameBits >= 4)
require(sampleDelay >= 0)
}
case class SPIBundleConfig(csWidth: Int)
{
def union(that: SPIBundleConfig): SPIBundleConfig =
SPIBundleConfig(scala.math.max(csWidth, that.csWidth))
def toSPIConfig: SPIConfig = new SPIConfig(rAddress = -1,
csWidth = csWidth)
}
class SPITopBundle(val i: Vec[Vec[Bool]], val r: Vec[TLBundle]) extends Bundle
class SPITopModule[B <: SPITopBundle](c: SPIConfigBase, bundle: => B, outer: TLSPIBase)
extends LazyModuleImp(outer) {
val io = new Bundle {
val port = new SPIPortIO(c)
val tl = bundle
}
val ctrl = Reg(init = SPIControl.init(c))
val fifo = Module(new SPIFIFO(c))
val mac = Module(new SPIMedia(c))
io.port <> mac.io.port
fifo.io.ctrl.fmt := ctrl.fmt
fifo.io.ctrl.cs <> ctrl.cs
fifo.io.ctrl.wm := ctrl.wm
mac.io.ctrl.sck := ctrl.sck
mac.io.ctrl.dla := ctrl.dla
mac.io.ctrl.cs <> ctrl.cs
val ie = Reg(init = new SPIInterrupts().fromBits(Bits(0)))
val ip = fifo.io.ip
io.tl.i(0)(0) := (ip.txwm && ie.txwm) || (ip.rxwm && ie.rxwm)
protected val regmapBase = Seq(
SPICRs.sckdiv -> Seq(RegField(c.divisorBits, ctrl.sck.div)),
SPICRs.sckmode -> Seq(
RegField(1, ctrl.sck.pha),
RegField(1, ctrl.sck.pol)),
SPICRs.csid -> Seq(RegField(c.csIdBits, ctrl.cs.id)),
SPICRs.csdef -> ctrl.cs.dflt.map(x => RegField(1, x)),
SPICRs.csmode -> Seq(RegField(SPICSMode.width, ctrl.cs.mode)),
SPICRs.dcssck -> Seq(RegField(c.delayBits, ctrl.dla.cssck)),
SPICRs.dsckcs -> Seq(RegField(c.delayBits, ctrl.dla.sckcs)),
SPICRs.dintercs -> Seq(RegField(c.delayBits, ctrl.dla.intercs)),
SPICRs.dinterxfr -> Seq(RegField(c.delayBits, ctrl.dla.interxfr)),
SPICRs.fmt -> Seq(
RegField(SPIProtocol.width, ctrl.fmt.proto),
RegField(SPIEndian.width, ctrl.fmt.endian),
RegField(SPIDirection.width, ctrl.fmt.iodir)),
SPICRs.len -> Seq(RegField(c.lengthBits, ctrl.fmt.len)),
SPICRs.txfifo -> NonBlockingEnqueue(fifo.io.tx),
SPICRs.rxfifo -> NonBlockingDequeue(fifo.io.rx),
SPICRs.txmark -> Seq(RegField(c.txDepthBits, ctrl.wm.tx)),
SPICRs.rxmark -> Seq(RegField(c.rxDepthBits, ctrl.wm.rx)),
SPICRs.ie -> Seq(
RegField(1, ie.txwm),
RegField(1, ie.rxwm)),
SPICRs.ip -> Seq(
RegField.r(1, ip.txwm),
RegField.r(1, ip.rxwm)))
}
abstract class TLSPIBase(c: SPIConfigBase)(implicit val p: Parameters) extends LazyModule {
require(isPow2(c.rSize))
val rnode = TLRegisterNode(address = AddressSet(c.rAddress, c.rSize-1), beatBytes = p(PeripheryBusConfig).beatBytes)
val intnode = IntSourceNode(1)
}
class TLSPI(c: SPIConfig)(implicit p: Parameters) extends TLSPIBase(c)(p) {
lazy val module = new SPITopModule(c, new SPITopBundle(intnode.bundleOut, rnode.bundleIn), this) {
mac.io.link <> fifo.io.link
rnode.regmap(regmapBase:_*)
}
}