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