1 // See LICENSE for license details.
2 package sifive.blocks.devices.spi
6 import uncore.tilelink2._
10 import rocketchip.PeripheryBusConfig
11 import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
26 lazy val csIdBits = log2Up(csWidth)
27 lazy val lengthBits = log2Floor(frameBits) + 1
28 lazy val countBits = math.max(lengthBits, delayBits)
30 lazy val txDepthBits = log2Floor(txDepth) + 1
31 lazy val rxDepthBits = log2Floor(rxDepth) + 1
37 rSize: BigInt = 0x1000,
43 divisorBits: Int = 12,
45 extends SPIConfigBase {
47 require(frameBits >= 4)
48 require(sampleDelay >= 0)
51 class SPITopBundle(val i: Vec[Vec[Bool]], val r: Vec[TLBundle]) extends Bundle
53 class SPITopModule[B <: SPITopBundle](c: SPIConfigBase, bundle: => B, outer: TLSPIBase)
54 extends LazyModuleImp(outer) {
57 val port = new SPIPortIO(c)
61 val ctrl = Reg(init = SPIControl.init(c))
63 val fifo = Module(new SPIFIFO(c))
64 val mac = Module(new SPIMedia(c))
65 io.port <> mac.io.port
67 fifo.io.ctrl.fmt := ctrl.fmt
68 fifo.io.ctrl.cs <> ctrl.cs
69 fifo.io.ctrl.wm := ctrl.wm
70 mac.io.ctrl.sck := ctrl.sck
71 mac.io.ctrl.dla := ctrl.dla
72 mac.io.ctrl.cs <> ctrl.cs
74 val ie = Reg(init = new SPIInterrupts().fromBits(Bits(0)))
76 io.tl.i(0)(0) := (ip.txwm && ie.txwm) || (ip.rxwm && ie.rxwm)
78 protected val regmapBase = Seq(
79 SPICRs.sckdiv -> Seq(RegField(c.divisorBits, ctrl.sck.div)),
80 SPICRs.sckmode -> Seq(
81 RegField(1, ctrl.sck.pha),
82 RegField(1, ctrl.sck.pol)),
83 SPICRs.csid -> Seq(RegField(c.csIdBits, ctrl.cs.id)),
84 SPICRs.csdef -> ctrl.cs.dflt.map(x => RegField(1, x)),
85 SPICRs.csmode -> Seq(RegField(SPICSMode.width, ctrl.cs.mode)),
86 SPICRs.dcssck -> Seq(RegField(c.delayBits, ctrl.dla.cssck)),
87 SPICRs.dsckcs -> Seq(RegField(c.delayBits, ctrl.dla.sckcs)),
88 SPICRs.dintercs -> Seq(RegField(c.delayBits, ctrl.dla.intercs)),
89 SPICRs.dinterxfr -> Seq(RegField(c.delayBits, ctrl.dla.interxfr)),
92 RegField(SPIProtocol.width, ctrl.fmt.proto),
93 RegField(SPIEndian.width, ctrl.fmt.endian),
94 RegField(SPIDirection.width, ctrl.fmt.iodir)),
95 SPICRs.len -> Seq(RegField(c.lengthBits, ctrl.fmt.len)),
97 SPICRs.txfifo -> NonBlockingEnqueue(fifo.io.tx),
98 SPICRs.rxfifo -> NonBlockingDequeue(fifo.io.rx),
100 SPICRs.txmark -> Seq(RegField(c.txDepthBits, ctrl.wm.tx)),
101 SPICRs.rxmark -> Seq(RegField(c.rxDepthBits, ctrl.wm.rx)),
104 RegField(1, ie.txwm),
105 RegField(1, ie.rxwm)),
107 RegField.r(1, ip.txwm),
108 RegField.r(1, ip.rxwm)))
111 abstract class TLSPIBase(c: SPIConfigBase)(implicit p: Parameters) extends LazyModule {
112 require(isPow2(c.rSize))
113 val rnode = TLRegisterNode(address = AddressSet(c.rAddress, c.rSize-1), beatBytes = p(PeripheryBusConfig).beatBytes)
114 val intnode = IntSourceNode(1)
117 class TLSPI(c: SPIConfig)(implicit p: Parameters) extends TLSPIBase(c)(p) {
118 lazy val module = new SPITopModule(c, new SPITopBundle(intnode.bundleOut, rnode.bundleIn), this) {
119 mac.io.link <> fifo.io.link
120 rnode.regmap(regmapBase:_*)