forked from M-Labs/artiq
Robert Jordens
307cd07b9d
tested/validated: * servo enable/disable * dds interface, timing, io_update, mask_nu * channel control (en_out, en_iir, profile) * profile configuration (coefficients, delays, offsets, channel) * adc timings and waveforms measured * asf state readback * adc readback individual changes below: suservo: correct rtio readback suservo: example, device_db [wip] suservo: change rtio channel layout suservo: mem ports in rio domain suservo: sck clocked from rio_phy suservo: cleanup, straighten out timing suservo: dds cs polarity suservo: simplify pipeline suservo: drop unused eem names suservo: decouple adc SR from IIR suservo: expand coredevice layer suservo: start the correct stage suservo: actually load ctrl suservo: refactor/tweak adc timing suservo: implement cpld and dds init
96 lines
2.5 KiB
Python
96 lines
2.5 KiB
Python
import logging
|
|
from collections import namedtuple
|
|
|
|
from migen import *
|
|
from migen.genlib.fsm import FSM, NextState
|
|
from migen.genlib import io
|
|
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
# all times in cycles
|
|
SPIParams = namedtuple("SPIParams", [
|
|
"channels", # number of MOSI? data lanes
|
|
"width", # transfer width
|
|
"clk", # CLK half cycle width (in cycles)
|
|
])
|
|
|
|
|
|
class SPISimple(Module):
|
|
"""Simple reduced SPI interface.
|
|
|
|
* Multiple MOSI lines
|
|
* Supports differential CLK/CS_N/MOSI
|
|
* Fixed CLK timing
|
|
* SPI MODE 0 (CPHA=0, CPOL=0)
|
|
"""
|
|
def __init__(self, pads, params):
|
|
self.params = p = params
|
|
self.data = [Signal(p.width, reset_less=True)
|
|
for i in range(p.channels)] # data to be output, MSB first
|
|
self.start = Signal() # start transfer
|
|
self.done = Signal() # transfer complete, next transfer can be
|
|
# started
|
|
|
|
###
|
|
|
|
assert p.clk >= 1
|
|
|
|
cnt = Signal(max=max(2, p.clk), reset_less=True)
|
|
cnt_done = Signal()
|
|
cnt_next = Signal()
|
|
self.comb += cnt_done.eq(cnt == 0)
|
|
self.sync += [
|
|
If(cnt_done,
|
|
If(cnt_next,
|
|
cnt.eq(p.clk - 1)
|
|
)
|
|
).Else(
|
|
cnt.eq(cnt - 1)
|
|
)
|
|
]
|
|
|
|
for i, d in enumerate(self.data):
|
|
self.comb += getattr(pads, "mosi{}".format(i)).eq(d[-1])
|
|
|
|
bits = Signal(max=p.width + 1, reset_less=True)
|
|
|
|
self.submodules.fsm = fsm = CEInserter()(FSM("IDLE"))
|
|
|
|
self.comb += fsm.ce.eq(cnt_done)
|
|
|
|
fsm.act("IDLE",
|
|
self.done.eq(1),
|
|
pads.cs_n.eq(1),
|
|
If(self.start,
|
|
cnt_next.eq(1),
|
|
NextState("SETUP")
|
|
)
|
|
)
|
|
fsm.act("SETUP",
|
|
cnt_next.eq(1),
|
|
If(bits == 0,
|
|
NextState("IDLE")
|
|
).Else(
|
|
NextState("HOLD")
|
|
)
|
|
)
|
|
fsm.act("HOLD",
|
|
cnt_next.eq(1),
|
|
pads.clk.eq(1),
|
|
NextState("SETUP")
|
|
)
|
|
|
|
self.sync += [
|
|
If(fsm.ce,
|
|
If(fsm.before_leaving("HOLD"),
|
|
bits.eq(bits - 1),
|
|
[d[1:].eq(d) for d in self.data]
|
|
),
|
|
If(fsm.ongoing("IDLE"),
|
|
bits.eq(p.width)
|
|
)
|
|
)
|
|
]
|