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