mirror of https://github.com/m-labs/artiq.git
spi: use misoc SPIMachine, closes #314
This commit is contained in:
parent
91b59cd584
commit
051e6e0447
|
@ -1,163 +1,8 @@
|
||||||
from itertools import product
|
from itertools import product
|
||||||
|
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.fsm import FSM, NextState
|
|
||||||
from misoc.interconnect import wishbone
|
from misoc.interconnect import wishbone
|
||||||
|
from misoc.cores.spi.core import SPIMachine
|
||||||
|
|
||||||
class SPIClockGen(Module):
|
|
||||||
def __init__(self, width):
|
|
||||||
self.load = Signal(width)
|
|
||||||
self.bias = Signal() # bias this clock phase to longer times
|
|
||||||
self.edge = Signal()
|
|
||||||
self.clk = Signal(reset=1)
|
|
||||||
|
|
||||||
cnt = Signal.like(self.load)
|
|
||||||
bias = Signal()
|
|
||||||
zero = Signal()
|
|
||||||
self.comb += [
|
|
||||||
zero.eq(cnt == 0),
|
|
||||||
self.edge.eq(zero & ~bias),
|
|
||||||
]
|
|
||||||
self.sync += [
|
|
||||||
If(zero,
|
|
||||||
bias.eq(0),
|
|
||||||
).Else(
|
|
||||||
cnt.eq(cnt - 1),
|
|
||||||
),
|
|
||||||
If(self.edge,
|
|
||||||
cnt.eq(self.load[1:]),
|
|
||||||
bias.eq(self.load[0] & (self.clk ^ self.bias)),
|
|
||||||
self.clk.eq(~self.clk),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SPIRegister(Module):
|
|
||||||
def __init__(self, width):
|
|
||||||
self.data = Signal(width)
|
|
||||||
self.o = Signal()
|
|
||||||
self.i = Signal()
|
|
||||||
self.lsb = Signal()
|
|
||||||
self.shift = Signal()
|
|
||||||
self.sample = Signal()
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.o.eq(Mux(self.lsb, self.data[0], self.data[-1])),
|
|
||||||
]
|
|
||||||
self.sync += [
|
|
||||||
If(self.shift,
|
|
||||||
If(self.lsb,
|
|
||||||
self.data[:-1].eq(self.data[1:]),
|
|
||||||
).Else(
|
|
||||||
self.data[1:].eq(self.data[:-1]),
|
|
||||||
)
|
|
||||||
),
|
|
||||||
If(self.sample,
|
|
||||||
If(self.lsb,
|
|
||||||
self.data[-1].eq(self.i),
|
|
||||||
).Else(
|
|
||||||
self.data[0].eq(self.i),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SPIBitCounter(Module):
|
|
||||||
def __init__(self, width):
|
|
||||||
self.n_read = Signal(width)
|
|
||||||
self.n_write = Signal(width)
|
|
||||||
self.read = Signal()
|
|
||||||
self.write = Signal()
|
|
||||||
self.done = Signal()
|
|
||||||
|
|
||||||
self.comb += [
|
|
||||||
self.write.eq(self.n_write != 0),
|
|
||||||
self.read.eq(self.n_read != 0),
|
|
||||||
self.done.eq(~(self.write | self.read)),
|
|
||||||
]
|
|
||||||
self.sync += [
|
|
||||||
If(self.write,
|
|
||||||
self.n_write.eq(self.n_write - 1),
|
|
||||||
).Elif(self.read,
|
|
||||||
self.n_read.eq(self.n_read - 1),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SPIMachine(Module):
|
|
||||||
def __init__(self, data_width, clock_width, bits_width):
|
|
||||||
ce = CEInserter()
|
|
||||||
self.submodules.cg = ce(SPIClockGen(clock_width))
|
|
||||||
self.submodules.reg = ce(SPIRegister(data_width))
|
|
||||||
self.submodules.bits = ce(SPIBitCounter(bits_width))
|
|
||||||
self.div_write = Signal.like(self.cg.load)
|
|
||||||
self.div_read = Signal.like(self.cg.load)
|
|
||||||
self.clk_phase = Signal()
|
|
||||||
self.start = Signal()
|
|
||||||
self.cs = Signal()
|
|
||||||
self.oe = Signal()
|
|
||||||
self.done = Signal()
|
|
||||||
|
|
||||||
# # #
|
|
||||||
|
|
||||||
fsm = CEInserter()(FSM("IDLE"))
|
|
||||||
self.submodules += fsm
|
|
||||||
|
|
||||||
fsm.act("IDLE",
|
|
||||||
If(self.start,
|
|
||||||
If(self.clk_phase,
|
|
||||||
NextState("WAIT"),
|
|
||||||
).Else(
|
|
||||||
NextState("SETUP"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
fsm.act("SETUP",
|
|
||||||
self.reg.sample.eq(1),
|
|
||||||
NextState("HOLD"),
|
|
||||||
)
|
|
||||||
fsm.act("HOLD",
|
|
||||||
If(self.bits.done & ~self.start,
|
|
||||||
If(self.clk_phase,
|
|
||||||
NextState("IDLE"),
|
|
||||||
).Else(
|
|
||||||
NextState("WAIT"),
|
|
||||||
)
|
|
||||||
).Else(
|
|
||||||
self.reg.shift.eq(~self.start),
|
|
||||||
NextState("SETUP"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
fsm.act("WAIT",
|
|
||||||
If(self.bits.done,
|
|
||||||
NextState("IDLE"),
|
|
||||||
).Else(
|
|
||||||
NextState("SETUP"),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
write0 = Signal()
|
|
||||||
self.sync += [
|
|
||||||
If(self.cg.edge & self.reg.shift,
|
|
||||||
write0.eq(self.bits.write),
|
|
||||||
)
|
|
||||||
]
|
|
||||||
self.comb += [
|
|
||||||
self.cg.ce.eq(self.start | self.cs | ~self.cg.edge),
|
|
||||||
If(self.bits.write | ~self.bits.read,
|
|
||||||
self.cg.load.eq(self.div_write),
|
|
||||||
).Else(
|
|
||||||
self.cg.load.eq(self.div_read),
|
|
||||||
),
|
|
||||||
self.cg.bias.eq(self.clk_phase),
|
|
||||||
fsm.ce.eq(self.cg.edge),
|
|
||||||
self.cs.eq(~fsm.ongoing("IDLE")),
|
|
||||||
self.reg.ce.eq(self.cg.edge),
|
|
||||||
self.bits.ce.eq(self.cg.edge & self.reg.sample),
|
|
||||||
self.done.eq(self.cg.edge & self.bits.done & fsm.ongoing("HOLD")),
|
|
||||||
self.oe.eq(write0 | self.bits.write),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class SPIMaster(Module):
|
class SPIMaster(Module):
|
||||||
|
|
Loading…
Reference in New Issue