spi: include mem region (#23)
[sifive-blocks.git] / src / main / scala / devices / spi / TLSPIFlash.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 trait SPIFlashParamsBase extends SPIParamsBase {
11 val fAddress: BigInt
12 val fSize: BigInt
13
14 val insnAddrBytes: Int
15 val insnPadLenBits: Int
16 lazy val insnCmdBits = frameBits
17 lazy val insnAddrBits = insnAddrBytes * frameBits
18 lazy val insnAddrLenBits = log2Floor(insnAddrBytes) + 1
19 }
20
21 case class SPIFlashParams(
22 rAddress: BigInt,
23 fAddress: BigInt,
24 rSize: BigInt = 0x1000,
25 fSize: BigInt = 0x20000000,
26 rxDepth: Int = 8,
27 txDepth: Int = 8,
28 csWidth: Int = 1,
29 delayBits: Int = 8,
30 divisorBits: Int = 12,
31 sampleDelay: Int = 2)
32 extends SPIFlashParamsBase {
33 val frameBits = 8
34 val insnAddrBytes = 4
35 val insnPadLenBits = 4
36
37 require(insnPadLenBits <= delayBits)
38 require(sampleDelay >= 0)
39 }
40
41 class SPIFlashTopBundle(i: util.HeterogeneousBag[Vec[Bool]], r: util.HeterogeneousBag[TLBundle], val f: util.HeterogeneousBag[TLBundle]) extends SPITopBundle(i, r)
42
43 class SPIFlashTopModule[B <: SPIFlashTopBundle]
44 (c: SPIFlashParamsBase, bundle: => B, outer: TLSPIFlashBase)
45 extends SPITopModule(c, bundle, outer) {
46
47 val flash = Module(new SPIFlashMap(c))
48 val arb = Module(new SPIArbiter(c, 2))
49
50 private val f = io.tl.f.head
51 // Tie unused channels
52 f.b.valid := Bool(false)
53 f.c.ready := Bool(true)
54 f.e.ready := Bool(true)
55
56 val a = Reg(f.a.bits)
57 val a_msb = log2Ceil(c.fSize) - 1
58
59 when (f.a.fire()) {
60 a := f.a.bits
61 }
62
63 flash.io.addr.bits.next := f.a.bits.address(a_msb, 0)
64 flash.io.addr.bits.hold := a.address(a_msb, 0)
65 flash.io.addr.valid := f.a.valid
66 f.a.ready := flash.io.addr.ready
67
68 f.d.bits := outer.fnode.edgesIn.head.AccessAck(a, UInt(0), flash.io.data.bits)
69 f.d.valid := flash.io.data.valid
70 flash.io.data.ready := f.d.ready
71
72 val insn = Reg(init = SPIFlashInsn.init(c))
73 val flash_en = Reg(init = Bool(true))
74
75 flash.io.ctrl.insn := insn
76 flash.io.ctrl.fmt <> ctrl.fmt
77 flash.io.en := flash_en
78 arb.io.sel := !flash_en
79
80 protected val regmapFlash = Seq(
81 SPICRs.insnmode -> Seq(RegField(1, flash_en)),
82 SPICRs.insnfmt -> Seq(
83 RegField(1, insn.cmd.en),
84 RegField(c.insnAddrLenBits, insn.addr.len),
85 RegField(c.insnPadLenBits, insn.pad.cnt)),
86 SPICRs.insnproto -> Seq(
87 RegField(SPIProtocol.width, insn.cmd.proto),
88 RegField(SPIProtocol.width, insn.addr.proto),
89 RegField(SPIProtocol.width, insn.data.proto)),
90 SPICRs.insncmd -> Seq(RegField(c.insnCmdBits, insn.cmd.code)),
91 SPICRs.insnpad -> Seq(RegField(c.frameBits, insn.pad.code)))
92 }
93
94 abstract class TLSPIFlashBase(w: Int, c: SPIFlashParamsBase)(implicit p: Parameters) extends TLSPIBase(w,c)(p) {
95 require(isPow2(c.fSize))
96 val fnode = TLManagerNode(1, TLManagerParameters(
97 address = Seq(AddressSet(c.fAddress, c.fSize-1)),
98 resources = device.reg("mem"),
99 regionType = RegionType.UNCACHED,
100 executable = true,
101 supportsGet = TransferSizes(1, 1),
102 fifoId = Some(0)))
103 }
104
105 class TLSPIFlash(w: Int, c: SPIFlashParams)(implicit p: Parameters) extends TLSPIFlashBase(w,c)(p) {
106 lazy val module = new SPIFlashTopModule(c,
107 new SPIFlashTopBundle(intnode.bundleOut, rnode.bundleIn, fnode.bundleIn), this) {
108
109 arb.io.inner(0) <> flash.io.link
110 arb.io.inner(1) <> fifo.io.link
111 mac.io.link <> arb.io.outer
112
113 rnode.regmap(regmapBase ++ regmapFlash:_*)
114 }
115 }