1 // See LICENSE for license details.
2 package sifive.blocks.devices.spi
5 import freechips.rocketchip.config.Parameters
6 import freechips.rocketchip.diplomacy._
7 import freechips.rocketchip.regmapper._
8 import freechips.rocketchip.tilelink._
9 import freechips.rocketchip.util.HeterogeneousBag
10 import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
25 lazy val csIdBits = log2Up(csWidth)
26 lazy val lengthBits = log2Floor(frameBits) + 1
27 lazy val countBits = math.max(lengthBits, delayBits)
29 lazy val txDepthBits = log2Floor(txDepth) + 1
30 lazy val rxDepthBits = log2Floor(rxDepth) + 1
36 rSize: BigInt = 0x1000,
42 divisorBits: Int = 12,
44 extends SPIParamsBase {
46 require(frameBits >= 4)
47 require(sampleDelay >= 0)
50 class SPITopModule(c: SPIParamsBase, outer: TLSPIBase)
51 extends LazyModuleImp(outer) {
53 val io = IO(new Bundle {
54 val port = new SPIPortIO(c)
57 val ctrl = Reg(init = SPIControl.init(c))
59 val fifo = Module(new SPIFIFO(c))
60 val mac = Module(new SPIMedia(c))
61 io.port <> mac.io.port
63 fifo.io.ctrl.fmt := ctrl.fmt
64 fifo.io.ctrl.cs <> ctrl.cs
65 fifo.io.ctrl.wm := ctrl.wm
66 mac.io.ctrl.sck := ctrl.sck
67 mac.io.ctrl.dla := ctrl.dla
68 mac.io.ctrl.cs <> ctrl.cs
70 val ie = Reg(init = new SPIInterrupts().fromBits(Bits(0)))
72 val (io_int, _) = outer.intnode.out(0)
73 io_int(0) := (ip.txwm && ie.txwm) || (ip.rxwm && ie.rxwm)
75 protected val regmapBase = Seq(
76 SPICRs.sckdiv -> Seq(RegField(c.divisorBits, ctrl.sck.div)),
77 SPICRs.sckmode -> Seq(
78 RegField(1, ctrl.sck.pha),
79 RegField(1, ctrl.sck.pol)),
80 SPICRs.csid -> Seq(RegField(c.csIdBits, ctrl.cs.id)),
81 SPICRs.csdef -> ctrl.cs.dflt.map(x => RegField(1, x)),
82 SPICRs.csmode -> Seq(RegField(SPICSMode.width, ctrl.cs.mode)),
83 SPICRs.dcssck -> Seq(RegField(c.delayBits, ctrl.dla.cssck)),
84 SPICRs.dsckcs -> Seq(RegField(c.delayBits, ctrl.dla.sckcs)),
85 SPICRs.dintercs -> Seq(RegField(c.delayBits, ctrl.dla.intercs)),
86 SPICRs.dinterxfr -> Seq(RegField(c.delayBits, ctrl.dla.interxfr)),
89 RegField(SPIProtocol.width, ctrl.fmt.proto),
90 RegField(SPIEndian.width, ctrl.fmt.endian),
91 RegField(SPIDirection.width, ctrl.fmt.iodir)),
92 SPICRs.len -> Seq(RegField(c.lengthBits, ctrl.fmt.len)),
94 SPICRs.txfifo -> NonBlockingEnqueue(fifo.io.tx),
95 SPICRs.rxfifo -> NonBlockingDequeue(fifo.io.rx),
97 SPICRs.txmark -> Seq(RegField(c.txDepthBits, ctrl.wm.tx)),
98 SPICRs.rxmark -> Seq(RegField(c.rxDepthBits, ctrl.wm.rx)),
101 RegField(1, ie.txwm),
102 RegField(1, ie.rxwm)),
104 RegField.r(1, ip.txwm),
105 RegField.r(1, ip.rxwm)))
108 abstract class TLSPIBase(w: Int, c: SPIParamsBase)(implicit p: Parameters) extends LazyModule {
109 require(isPow2(c.rSize))
110 val device = new SimpleDevice("spi", Seq("sifive,spi0"))
111 val rnode = TLRegisterNode(address = Seq(AddressSet(c.rAddress, c.rSize-1)), device = device, beatBytes = w)
112 val intnode = IntSourceNode(IntSourcePortSimple(resources = device.int))
115 class TLSPI(w: Int, c: SPIParams)(implicit p: Parameters) extends TLSPIBase(w,c)(p) {
116 lazy val module = new SPITopModule(c, this) {
117 mac.io.link <> fifo.io.link
118 rnode.regmap(regmapBase:_*)