1 // See LICENSE for license details.
2 package sifive.blocks.devices.spi
6 class SPILinkIO(c: SPIParamsBase) extends SPIBundle(c) {
7 val tx = Decoupled(Bits(width = c.frameBits))
8 val rx = Valid(Bits(width = c.frameBits)).flip
10 val cnt = UInt(OUTPUT, c.countBits)
11 val fmt = new SPIFormat(c).asOutput
13 val set = Bool(OUTPUT)
14 val clear = Bool(OUTPUT) // Deactivate CS
15 val hold = Bool(OUTPUT) // Supress automatic CS deactivation
17 val active = Bool(INPUT)
20 class SPIMedia(c: SPIParamsBase) extends Module {
22 val port = new SPIPortIO(c)
23 val ctrl = new Bundle {
24 val sck = new SPIClocking(c).asInput
25 val dla = new SPIDelay(c).asInput
26 val cs = new SPIChipSelect(c).asInput
28 val link = new SPILinkIO(c).flip
31 val phy = Module(new SPIPhysical(c))
32 phy.io.ctrl.sck := io.ctrl.sck
33 phy.io.ctrl.fmt := io.link.fmt
35 private val op = phy.io.op
36 op.valid := Bool(true)
37 op.bits.fn := SPIMicroOp.Delay
38 op.bits.stb := Bool(false)
39 op.bits.cnt := io.link.cnt
40 op.bits.data := io.link.tx.bits
42 val cs = Reg(io.ctrl.cs)
43 val cs_set = Reg(Bool())
44 val cs_active = io.ctrl.cs.toggle(io.link.cs.set)
45 val cs_update = (cs_active.asUInt =/= cs.dflt.asUInt)
47 val clear = Reg(init = Bool(false))
48 val cs_assert = Reg(init = Bool(false))
49 val cs_deassert = clear || (cs_update && !io.link.cs.hold)
51 clear := clear || (io.link.cs.clear && cs_assert)
53 val continuous = (io.ctrl.dla.interxfr === UInt(0))
55 io.port.sck := phy.io.port.sck
56 io.port.dq <> phy.io.port.dq
59 io.link.rx := phy.io.rx
60 io.link.tx.ready := Bool(false)
61 io.link.active := cs_assert
63 val (s_main :: s_interxfr :: s_intercs :: Nil) = Enum(UInt(), 3)
64 val state = Reg(init = s_main)
70 op.bits.cnt := io.ctrl.dla.sckcs
75 op.bits.fn := SPIMicroOp.Transfer
76 op.bits.stb := Bool(true)
78 op.valid := io.link.tx.valid
79 io.link.tx.ready := op.ready
84 } .elsewhen (io.link.tx.valid) {
86 op.bits.cnt := io.ctrl.dla.cssck
88 cs_assert := Bool(true)
89 cs_set := io.link.cs.set
94 op.bits.cnt := UInt(0)
95 op.bits.stb := Bool(true)
101 // Skip if interxfr delay is zero
102 op.valid := !continuous
103 op.bits.cnt := io.ctrl.dla.interxfr
104 when (op.ready || continuous) {
111 op.bits.cnt := io.ctrl.dla.intercs
112 op.bits.stb := Bool(true)
113 cs_assert := Bool(false)
116 cs.dflt := cs.toggle(cs_set)