LazyModule: provide Parameters
[sifive-blocks.git] / src / main / scala / devices / spi / TLSPI.scala
1 // See LICENSE for license details.
2 package sifive.blocks.devices.spi
3
4 import Chisel._
5 import config._
6 import uncore.tilelink2._
7 import diplomacy._
8 import regmapper._
9 import junctions._
10 import rocketchip.PeripheryBusConfig
11 import sifive.blocks.util.{NonBlockingEnqueue, NonBlockingDequeue}
12
13 trait SPIConfigBase {
14 val rAddress: BigInt
15 val rSize: BigInt
16 val rxDepth: Int
17 val txDepth: Int
18
19 val csWidth: Int
20 val frameBits: Int
21 val delayBits: Int
22 val divisorBits: Int
23
24 val sampleDelay: Int
25
26 lazy val csIdBits = log2Up(csWidth)
27 lazy val lengthBits = log2Floor(frameBits) + 1
28 lazy val countBits = math.max(lengthBits, delayBits)
29
30 lazy val txDepthBits = log2Floor(txDepth) + 1
31 lazy val rxDepthBits = log2Floor(rxDepth) + 1
32
33 lazy val bc = new SPIBundleConfig(csWidth)
34 }
35
36 case class SPIConfig(
37 rAddress: BigInt,
38 rSize: BigInt = 0x1000,
39 rxDepth: Int = 8,
40 txDepth: Int = 8,
41 csWidth: Int = 1,
42 frameBits: Int = 8,
43 delayBits: Int = 8,
44 divisorBits: Int = 12,
45 sampleDelay: Int = 2)
46 extends SPIConfigBase {
47
48 require(frameBits >= 4)
49 require(sampleDelay >= 0)
50 }
51
52 case class SPIBundleConfig(csWidth: Int)
53 {
54 def union(that: SPIBundleConfig): SPIBundleConfig =
55 SPIBundleConfig(scala.math.max(csWidth, that.csWidth))
56
57 def toSPIConfig: SPIConfig = new SPIConfig(rAddress = -1,
58 csWidth = csWidth)
59 }
60
61 class SPITopBundle(val i: Vec[Vec[Bool]], val r: Vec[TLBundle]) extends Bundle
62
63 class SPITopModule[B <: SPITopBundle](c: SPIConfigBase, bundle: => B, outer: TLSPIBase)
64 extends LazyModuleImp(outer) {
65
66 val io = new Bundle {
67 val port = new SPIPortIO(c)
68 val tl = bundle
69 }
70
71 val ctrl = Reg(init = SPIControl.init(c))
72
73 val fifo = Module(new SPIFIFO(c))
74 val mac = Module(new SPIMedia(c))
75 io.port <> mac.io.port
76
77 fifo.io.ctrl.fmt := ctrl.fmt
78 fifo.io.ctrl.cs <> ctrl.cs
79 fifo.io.ctrl.wm := ctrl.wm
80 mac.io.ctrl.sck := ctrl.sck
81 mac.io.ctrl.dla := ctrl.dla
82 mac.io.ctrl.cs <> ctrl.cs
83
84 val ie = Reg(init = new SPIInterrupts().fromBits(Bits(0)))
85 val ip = fifo.io.ip
86 io.tl.i(0)(0) := (ip.txwm && ie.txwm) || (ip.rxwm && ie.rxwm)
87
88 protected val regmapBase = Seq(
89 SPICRs.sckdiv -> Seq(RegField(c.divisorBits, ctrl.sck.div)),
90 SPICRs.sckmode -> Seq(
91 RegField(1, ctrl.sck.pha),
92 RegField(1, ctrl.sck.pol)),
93 SPICRs.csid -> Seq(RegField(c.csIdBits, ctrl.cs.id)),
94 SPICRs.csdef -> ctrl.cs.dflt.map(x => RegField(1, x)),
95 SPICRs.csmode -> Seq(RegField(SPICSMode.width, ctrl.cs.mode)),
96 SPICRs.dcssck -> Seq(RegField(c.delayBits, ctrl.dla.cssck)),
97 SPICRs.dsckcs -> Seq(RegField(c.delayBits, ctrl.dla.sckcs)),
98 SPICRs.dintercs -> Seq(RegField(c.delayBits, ctrl.dla.intercs)),
99 SPICRs.dinterxfr -> Seq(RegField(c.delayBits, ctrl.dla.interxfr)),
100
101 SPICRs.fmt -> Seq(
102 RegField(SPIProtocol.width, ctrl.fmt.proto),
103 RegField(SPIEndian.width, ctrl.fmt.endian),
104 RegField(SPIDirection.width, ctrl.fmt.iodir)),
105 SPICRs.len -> Seq(RegField(c.lengthBits, ctrl.fmt.len)),
106
107 SPICRs.txfifo -> NonBlockingEnqueue(fifo.io.tx),
108 SPICRs.rxfifo -> NonBlockingDequeue(fifo.io.rx),
109
110 SPICRs.txmark -> Seq(RegField(c.txDepthBits, ctrl.wm.tx)),
111 SPICRs.rxmark -> Seq(RegField(c.rxDepthBits, ctrl.wm.rx)),
112
113 SPICRs.ie -> Seq(
114 RegField(1, ie.txwm),
115 RegField(1, ie.rxwm)),
116 SPICRs.ip -> Seq(
117 RegField.r(1, ip.txwm),
118 RegField.r(1, ip.rxwm)))
119 }
120
121 abstract class TLSPIBase(c: SPIConfigBase)(implicit p: Parameters) extends LazyModule {
122 require(isPow2(c.rSize))
123 val rnode = TLRegisterNode(address = AddressSet(c.rAddress, c.rSize-1), beatBytes = p(PeripheryBusConfig).beatBytes)
124 val intnode = IntSourceNode(1)
125 }
126
127 class TLSPI(c: SPIConfig)(implicit p: Parameters) extends TLSPIBase(c)(p) {
128 lazy val module = new SPITopModule(c, new SPITopBundle(intnode.bundleOut, rnode.bundleIn), this) {
129 mac.io.link <> fifo.io.link
130 rnode.regmap(regmapBase:_*)
131 }
132 }