1 // See LICENSE for license details.
2 package sifive.blocks.devices.spi
5 import sifive.blocks.util.ShiftRegisterInit
7 class SPIMicroOp(c: SPIConfigBase) extends SPIBundle(c) {
8 val fn = Bits(width = 1)
10 val cnt = UInt(width = c.countBits)
11 val data = Bits(width = c.frameBits)
15 def Transfer = UInt(0, 1)
16 def Delay = UInt(1, 1)
19 class SPIPhyControl(c: SPIConfigBase) extends SPIBundle(c) {
20 val sck = new SPIClocking(c)
21 val fmt = new SPIFormat(c)
24 class SPIPhysical(c: SPIConfigBase) extends Module {
25 val io = new SPIBundle(c) {
26 val port = new SPIPortIO(c)
27 val ctrl = new SPIPhyControl(c).asInput
28 val op = Decoupled(new SPIMicroOp(c)).flip
29 val rx = Valid(Bits(width = c.frameBits))
32 private val op = io.op.bits
33 val ctrl = Reg(io.ctrl)
34 val proto = SPIProtocol.decode(ctrl.fmt.proto)
36 val accept = Wire(init = Bool(false))
37 val sample = Wire(init = Bool(false))
38 val setup = Wire(init = Bool(false))
39 val last = Wire(init = Bool(false))
41 val setup_d = Reg(next = setup)
42 val sample_d = ShiftRegisterInit(sample, c.sampleDelay, Bool(false))
43 val last_d = ShiftRegisterInit(last, c.sampleDelay, Bool(false))
45 val scnt = Reg(init = UInt(0, c.countBits))
46 val tcnt = Reg(io.ctrl.sck.div)
48 val stop = (scnt === UInt(0))
49 val beat = (tcnt === UInt(0))
50 val decr = Mux(beat, scnt, tcnt) - UInt(1)
51 val sched = Wire(init = beat)
52 tcnt := Mux(sched, ctrl.sck.div, decr)
55 val cref = Reg(init = Bool(true))
56 val cinv = ctrl.sck.pha ^ ctrl.sck.pol
58 private def convert(data: UInt, fmt: SPIFormat) =
59 Mux(fmt.endian === SPIEndian.MSB, data, Cat(data.toBools))
61 val rxd = Cat(io.port.dq.reverse.map(_.i))
62 val samples = Seq(rxd(1), rxd(1, 0), rxd)
64 val buffer = Reg(op.data)
65 val buffer_in = convert(io.op.bits.data, io.ctrl.fmt)
66 val shift = if (c.sampleDelay > 0) setup_d || (sample_d && stop) else sample_d
67 buffer := Mux1H(proto, samples.zipWithIndex.map { case (data, i) =>
69 val m = c.frameBits -1
70 Cat(Mux(shift, buffer(m-n, 0), buffer(m, n)),
71 Mux(sample_d, data, buffer(n-1, 0)))
74 private def upper(x: UInt, n: Int) = x(c.frameBits-1, c.frameBits-n)
76 val txd = Reg(init = Bits(0, io.port.dq.size))
77 val txd_in = Mux(accept, upper(buffer_in, 4), upper(buffer, 4))
78 val txd_sel = SPIProtocol.decode(Mux(accept, io.ctrl.fmt.proto, ctrl.fmt.proto))
79 val txd_shf = (0 until txd_sel.size).map(i => txd_in(3, 4-(1<<i)))
81 txd := Mux1H(txd_sel, txd_shf)
84 val tx = (ctrl.fmt.iodir === SPIDirection.Tx)
85 val txen_in = (proto.head +: proto.tail.map(_ && tx)).scanRight(Bool(false))(_ || _)
86 val txen = txen_in :+ txen_in.last
89 io.port.cs := Vec.fill(io.port.cs.size)(Bool(true)) // dummy
90 (io.port.dq zip (txd.toBools zip txen)).foreach {
95 io.op.ready := Bool(false)
97 val done = Reg(init = Bool(true))
98 done := done || last_d
101 io.rx.bits := convert(buffer, ctrl.fmt)
103 val xfr = Reg(Bool())
122 when (scnt === UInt(1)) {
123 last := beat && cref && xfr // Final sample
124 when (beat && !cref) { // Final shift
131 when (accept && done) {
132 io.op.ready := Bool(true)
136 ctrl.fmt := io.ctrl.fmt
141 is (SPIMicroOp.Transfer) {
145 done := (op.cnt === UInt(0))
148 is (SPIMicroOp.Delay) {
150 sck := io.ctrl.sck.pol
151 ctrl.sck := io.ctrl.sck