diff --git a/artiq/gateware/spi.py b/artiq/gateware/spi.py index 0713bb3f0..17ab523ad 100644 --- a/artiq/gateware/spi.py +++ b/artiq/gateware/spi.py @@ -1,163 +1,8 @@ from itertools import product from migen import * -from migen.genlib.fsm import FSM, NextState from misoc.interconnect import wishbone - - -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), - ] +from misoc.cores.spi.core import SPIMachine class SPIMaster(Module):