forked from M-Labs/artiq
suservo: lots of gateware/ runtime changes
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
This commit is contained in:
parent
01f762a8f5
commit
307cd07b9d
132
artiq/coredevice/suservo.py
Normal file
132
artiq/coredevice/suservo.py
Normal file
@ -0,0 +1,132 @@
|
||||
from artiq.language.core import kernel, delay, portable, now_mu
|
||||
from artiq.language.units import us, ms
|
||||
from artiq.coredevice.rtio import rtio_output, rtio_input_data
|
||||
|
||||
from numpy import int32, int64
|
||||
|
||||
from artiq.coredevice import spi2 as spi
|
||||
from artiq.coredevice import urukul, sampler
|
||||
|
||||
|
||||
COEFF_WIDTH = 18
|
||||
COEFF_DEPTH = 10 + 1
|
||||
WE = 1 << COEFF_DEPTH + 1
|
||||
STATE_SEL = 1 << COEFF_DEPTH
|
||||
CONFIG_SEL = 1 << COEFF_DEPTH - 1
|
||||
CONFIG_ADDR = CONFIG_SEL | STATE_SEL
|
||||
|
||||
|
||||
class SUServo:
|
||||
kernel_invariants = {"channel", "core", "pgia", "cpld0", "cpld1",
|
||||
"dds0", "dds1", "ref_period_mu"}
|
||||
|
||||
def __init__(self, dmgr, channel, pgia_device,
|
||||
cpld0_device, cpld1_device,
|
||||
dds0_device, dds1_device,
|
||||
core_device="core"):
|
||||
|
||||
self.core = dmgr.get(core_device)
|
||||
self.pgia = dmgr.get(pgia_device)
|
||||
self.dds0 = dmgr.get(dds0_device)
|
||||
self.dds1 = dmgr.get(dds1_device)
|
||||
self.cpld0 = dmgr.get(cpld0_device)
|
||||
self.cpld1 = dmgr.get(cpld1_device)
|
||||
self.channel = channel
|
||||
self.gains = 0x0000
|
||||
self.ref_period_mu = self.core.seconds_to_mu(
|
||||
self.core.coarse_ref_period)
|
||||
assert self.ref_period_mu == self.core.ref_multiplier
|
||||
|
||||
@kernel
|
||||
def init(self):
|
||||
self.set_config(0)
|
||||
delay(2*us) # pipeline flush
|
||||
|
||||
self.pgia.set_config_mu(
|
||||
sampler.SPI_CONFIG | spi.SPI_END,
|
||||
16, 4, sampler.SPI_CS_PGIA)
|
||||
|
||||
self.cpld0.init(blind=True)
|
||||
cfg0 = self.cpld0.cfg_reg
|
||||
self.cpld0.cfg_write(cfg0 | (0xf << urukul.CFG_MASK_NU))
|
||||
self.dds0.init(blind=True)
|
||||
self.cpld0.cfg_write(cfg0)
|
||||
|
||||
self.cpld1.init(blind=True)
|
||||
cfg1 = self.cpld1.cfg_reg
|
||||
self.cpld1.cfg_write(cfg1 | (0xf << urukul.CFG_MASK_NU))
|
||||
self.dds1.init(blind=True)
|
||||
self.cpld1.cfg_write(cfg1)
|
||||
|
||||
@kernel
|
||||
def write(self, addr, value):
|
||||
rtio_output(now_mu(), self.channel, addr | WE, value)
|
||||
delay_mu(self.ref_period_mu)
|
||||
|
||||
@kernel
|
||||
def read(self, addr):
|
||||
rtio_output(now_mu(), self.channel, addr, 0)
|
||||
return rtio_input_data(self.channel)
|
||||
|
||||
@kernel
|
||||
def set_config(self, start):
|
||||
self.write(CONFIG_ADDR, start)
|
||||
|
||||
@kernel
|
||||
def get_status(self):
|
||||
return self.read(CONFIG_ADDR)
|
||||
|
||||
@kernel
|
||||
def get_adc_mu(self, adc):
|
||||
return self.read(STATE_SEL | (adc << 1) | (1 << 8))
|
||||
|
||||
@kernel
|
||||
def set_gain_mu(self, channel, gain):
|
||||
"""Set instrumentation amplifier gain of a channel.
|
||||
|
||||
The four gain settings (0, 1, 2, 3) corresponds to gains of
|
||||
(1, 10, 100, 1000) respectively.
|
||||
|
||||
:param channel: Channel index
|
||||
:param gain: Gain setting
|
||||
"""
|
||||
gains = self.gains
|
||||
gains &= ~(0b11 << (channel*2))
|
||||
gains |= gain << (channel*2)
|
||||
self.pgia.write(gains << 16)
|
||||
self.gains = gains
|
||||
|
||||
|
||||
class Channel:
|
||||
kernel_invariants = {"channel", "core", "servo", "servo_channel"}
|
||||
|
||||
def __init__(self, dmgr, channel, servo_device,
|
||||
core_device="core"):
|
||||
self.core = dmgr.get(core_device)
|
||||
self.servo = dmgr.get(servo_device)
|
||||
self.channel = channel
|
||||
self.servo_channel = self.channel + 8 - self.servo.channel # FIXME
|
||||
|
||||
@kernel
|
||||
def set(self, en_out, en_iir=0, profile=0):
|
||||
rtio_output(now_mu(), self.channel, 0,
|
||||
en_out | (en_iir << 1) | (profile << 2))
|
||||
|
||||
@kernel
|
||||
def set_profile_mu(self, profile, ftw, adc, offset,
|
||||
a1, b0, b1, delay, pow=0):
|
||||
base = (self.servo_channel << 8) | (profile << 3)
|
||||
data = [ftw >> 16, b1, pow, adc | (delay << 8), offset, a1, ftw, b0]
|
||||
for i in range(8):
|
||||
self.servo.write(base + i, data[i])
|
||||
|
||||
@kernel
|
||||
def get_profile_mu(self, profile, data):
|
||||
base = (self.servo_channel << 8) | (profile << 3)
|
||||
for i in range(8):
|
||||
data[i] = self.servo.read(base + i)
|
||||
delay(2*us)
|
||||
|
||||
@kernel
|
||||
def get_asf_mu(self, profile):
|
||||
return self.servo.read(STATE_SEL | (self.servo_channel << 5) | profile)
|
@ -1,4 +1,4 @@
|
||||
core_addr = "lauda.ber.quartiq.de"
|
||||
core_addr = "10.0.16.119"
|
||||
|
||||
device_db = {
|
||||
"core": {
|
||||
@ -141,9 +141,11 @@ device_db = {
|
||||
"class": "SUServo",
|
||||
"arguments": {
|
||||
"channel": 24,
|
||||
"sampler_pgia_device": "spi_sampler0_pgia",
|
||||
"urukul0_device": "urukul0_cpld",
|
||||
"urukul1_device": "urukul1_cpld"
|
||||
"pgia_device": "spi_sampler0_pgia",
|
||||
"cpld0_device": "urukul0_cpld",
|
||||
"cpld1_device": "urukul1_cpld",
|
||||
"dds0_device": "urukul0_dds",
|
||||
"dds1_device": "urukul1_dds"
|
||||
}
|
||||
},
|
||||
|
||||
@ -215,10 +217,20 @@ device_db = {
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul0",
|
||||
"refclk": 125e6,
|
||||
"refclk": 100e6,
|
||||
"clk_sel": 0
|
||||
}
|
||||
},
|
||||
"urukul0_dds": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 40,
|
||||
"chip_select": 3,
|
||||
"cpld_device": "urukul0_cpld",
|
||||
}
|
||||
},
|
||||
|
||||
"spi_urukul1": {
|
||||
"type": "local",
|
||||
@ -232,10 +244,20 @@ device_db = {
|
||||
"class": "CPLD",
|
||||
"arguments": {
|
||||
"spi_device": "spi_urukul1",
|
||||
"refclk": 125e6,
|
||||
"refclk": 100e6,
|
||||
"clk_sel": 0
|
||||
}
|
||||
},
|
||||
"urukul1_dds": {
|
||||
"type": "local",
|
||||
"module": "artiq.coredevice.ad9910",
|
||||
"class": "AD9910",
|
||||
"arguments": {
|
||||
"pll_n": 40,
|
||||
"chip_select": 3,
|
||||
"cpld_device": "urukul1_cpld",
|
||||
}
|
||||
},
|
||||
|
||||
"led0": {
|
||||
"type": "local",
|
||||
|
@ -1,35 +0,0 @@
|
||||
from artiq.experiment import *
|
||||
|
||||
|
||||
class Sampler(EnvExperiment):
|
||||
def build(self):
|
||||
self.setattr_device("core")
|
||||
self.setattr_device("sampler0")
|
||||
|
||||
def run(self):
|
||||
self.data = []
|
||||
self.sample()
|
||||
for d in self.data:
|
||||
print(d)
|
||||
|
||||
@kernel
|
||||
def sample(self):
|
||||
self.core.break_realtime()
|
||||
self.sampler0.init()
|
||||
for g in range(4):
|
||||
for ch in range(8):
|
||||
self.sampler0.set_gain_mu(ch, g)
|
||||
self.ret([self.sampler0.get_gains_mu()])
|
||||
delay(10*ms)
|
||||
raw = [0] * 8
|
||||
self.sampler0.sample_mu(raw)
|
||||
self.ret(raw)
|
||||
delay(10*ms)
|
||||
data = [0.] * 8
|
||||
self.sampler0.sample(data)
|
||||
self.ret(data)
|
||||
delay(10*ms)
|
||||
|
||||
@rpc(flags={"async"})
|
||||
def ret(self, data):
|
||||
self.data.append(data)
|
33
artiq/examples/kasli_suservo/repository/suservo.py
Normal file
33
artiq/examples/kasli_suservo/repository/suservo.py
Normal file
@ -0,0 +1,33 @@
|
||||
from artiq.experiment import *
|
||||
|
||||
|
||||
class SUServo(EnvExperiment):
|
||||
def build(self):
|
||||
self.setattr_device("core")
|
||||
self.setattr_device("led0")
|
||||
self.setattr_device("suservo0")
|
||||
self.setattr_device("suservo0_ch0")
|
||||
|
||||
def run(self):
|
||||
# self.led()
|
||||
self.init()
|
||||
|
||||
@kernel
|
||||
def init(self):
|
||||
self.core.break_realtime()
|
||||
self.core.reset()
|
||||
|
||||
self.suservo0.init()
|
||||
self.suservo0.set_config(1)
|
||||
print(self.suservo0.get_status())
|
||||
delay(3*ms)
|
||||
self.suservo0.set_config(0)
|
||||
delay(3*ms)
|
||||
print(self.suservo0.get_status())
|
||||
|
||||
@kernel
|
||||
def led(self):
|
||||
self.core.break_realtime()
|
||||
for i in range(10):
|
||||
self.led0.pulse(.1*s)
|
||||
delay(.1*s)
|
@ -7,18 +7,19 @@ class RTServoCtrl(Module):
|
||||
"""Per channel RTIO control interface"""
|
||||
def __init__(self, ctrl):
|
||||
self.rtlink = rtlink.Interface(
|
||||
rtlink.OInterface(len(ctrl)))
|
||||
rtlink.OInterface(len(ctrl.profile) + 2))
|
||||
|
||||
# # #
|
||||
|
||||
self.sync.rio += [
|
||||
If(self.rtlink.o.stb,
|
||||
Cat(ctrl.profile, ctrl.en_out, ctrl.en_iir).eq(
|
||||
self.rtlink.o.data),
|
||||
)
|
||||
]
|
||||
self.comb += [
|
||||
ctrl.stb.eq(self.rtlink.o.stb)
|
||||
ctrl.stb.eq(self.rtlink.o.stb),
|
||||
self.rtlink.o.busy.eq(0)
|
||||
]
|
||||
self.sync.rio_phy += [
|
||||
If(self.rtlink.o.stb,
|
||||
Cat(ctrl.en_out, ctrl.en_iir, ctrl.profile).eq(
|
||||
self.rtlink.o.data)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
@ -26,10 +27,11 @@ class RTServoMem(Module):
|
||||
"""All-channel all-profile coefficient and state RTIO control
|
||||
interface."""
|
||||
def __init__(self, w, servo):
|
||||
m_coeff = servo.m_coeff.get_port(write_capable=True,
|
||||
we_granularity=w.coeff)
|
||||
m_coeff = servo.iir.m_coeff.get_port(write_capable=True,
|
||||
we_granularity=w.coeff, clock_domain="rio")
|
||||
assert len(m_coeff.we) == 2
|
||||
m_state = servo.m_state.get_port(write_capable=True)
|
||||
m_state = servo.iir.m_state.get_port(write_capable=True,
|
||||
clock_domain="rio")
|
||||
self.specials += m_state, m_coeff
|
||||
|
||||
# just expose the w.coeff (18) MSBs of state
|
||||
@ -52,8 +54,8 @@ class RTServoMem(Module):
|
||||
|
||||
# # #
|
||||
|
||||
config = Signal(1, reset=0)
|
||||
status = Signal(2)
|
||||
config = Signal(w.coeff, reset=0)
|
||||
status = Signal(w.coeff)
|
||||
self.comb += [
|
||||
Cat(servo.start).eq(config),
|
||||
status.eq(Cat(servo.start, servo.done))
|
||||
@ -87,16 +89,18 @@ class RTServoMem(Module):
|
||||
m_state.we.eq(self.rtlink.o.stb & we & state_sel & ~config_sel),
|
||||
]
|
||||
read = Signal()
|
||||
read_sel = Signal()
|
||||
read_state = Signal()
|
||||
read_high = Signal()
|
||||
read_config = Signal()
|
||||
self.sync.rio += [
|
||||
If(read,
|
||||
read.eq(0)
|
||||
),
|
||||
If(self.rtlink.o.stb,
|
||||
read.eq(~we),
|
||||
read_sel.eq(state_sel),
|
||||
read_state.eq(state_sel),
|
||||
read_high.eq(high_coeff),
|
||||
read_config.eq(config_sel),
|
||||
)
|
||||
]
|
||||
self.sync.rio_phy += [
|
||||
@ -107,8 +111,8 @@ class RTServoMem(Module):
|
||||
self.comb += [
|
||||
self.rtlink.i.stb.eq(read),
|
||||
self.rtlink.i.data.eq(
|
||||
Mux(state_sel,
|
||||
Mux(config_sel,
|
||||
Mux(read_state,
|
||||
Mux(read_config,
|
||||
status,
|
||||
m_state.dat_r[w.state - w.coeff:]),
|
||||
Mux(read_high,
|
||||
|
@ -55,13 +55,13 @@ class ADC(Module):
|
||||
assert p.lanes*t_read == p.width*p.channels
|
||||
assert all(_ > 0 for _ in (p.t_cnvh, p.t_conv, p.t_rtt))
|
||||
assert p.t_conv > 1
|
||||
count = Signal(max=max(p.t_cnvh, p.t_conv - 1, t_read, p.t_rtt + 1) - 1,
|
||||
count = Signal(max=max(p.t_cnvh, p.t_conv, t_read, p.t_rtt),
|
||||
reset_less=True)
|
||||
count_load = Signal.like(count)
|
||||
count_done = Signal()
|
||||
self.comb += [
|
||||
count_done.eq(count == 0),
|
||||
]
|
||||
update = Signal()
|
||||
|
||||
self.comb += count_done.eq(count == 0)
|
||||
self.sync += [
|
||||
count.eq(count - 1),
|
||||
If(count_done,
|
||||
@ -78,7 +78,7 @@ class ADC(Module):
|
||||
)
|
||||
)
|
||||
fsm.act("CNVH",
|
||||
count_load.eq(p.t_conv - 2), # account for sck ODDR delay
|
||||
count_load.eq(p.t_conv - 1),
|
||||
pads.cnv.eq(1),
|
||||
If(count_done,
|
||||
NextState("CONV")
|
||||
@ -92,7 +92,7 @@ class ADC(Module):
|
||||
)
|
||||
fsm.act("READ",
|
||||
self.reading.eq(1),
|
||||
count_load.eq(p.t_rtt), # again account for sck ODDR delay
|
||||
count_load.eq(p.t_rtt - 1),
|
||||
pads.sck_en.eq(1),
|
||||
If(count_done,
|
||||
NextState("RTT")
|
||||
@ -101,6 +101,7 @@ class ADC(Module):
|
||||
fsm.act("RTT", # account for sck->clkout round trip time
|
||||
self.reading.eq(1),
|
||||
If(count_done,
|
||||
update.eq(1),
|
||||
NextState("IDLE")
|
||||
)
|
||||
)
|
||||
@ -111,10 +112,7 @@ class ADC(Module):
|
||||
sck_en_ret = 1
|
||||
|
||||
self.clock_domains.cd_ret = ClockDomain("ret", reset_less=True)
|
||||
self.comb += [
|
||||
# falling clkout makes two bits available
|
||||
self.cd_ret.clk.eq(pads.clkout)
|
||||
]
|
||||
self.comb += self.cd_ret.clk.eq(pads.clkout)
|
||||
|
||||
k = p.channels//p.lanes
|
||||
assert t_read == k*p.width
|
||||
@ -126,7 +124,9 @@ class ADC(Module):
|
||||
sdo_sr[0].eq(sdo),
|
||||
)
|
||||
]
|
||||
self.comb += [
|
||||
Cat(reversed([self.data[i*k + j] for j in range(k)])
|
||||
).eq(sdo_sr)
|
||||
self.sync += [
|
||||
If(update,
|
||||
Cat(reversed([self.data[i*k + j] for j in range(k)])
|
||||
).eq(sdo_sr)
|
||||
)
|
||||
]
|
||||
|
@ -36,13 +36,8 @@ class DDS(spi.SPISimple):
|
||||
)
|
||||
]
|
||||
|
||||
io_update = pads.io_update
|
||||
# this assumes that the cycle time (1/125 MHz = 8 ns) is >1 SYNC_CLK
|
||||
# cycle (1/250 MHz = 4ns)
|
||||
done = Signal()
|
||||
self.sync += [
|
||||
done.eq(self.done)
|
||||
]
|
||||
self.comb += [
|
||||
io_update.eq(self.done & ~done)
|
||||
]
|
||||
done_old = Signal()
|
||||
self.sync += done_old.eq(self.done)
|
||||
self.comb += pads.io_update.eq(self.done & ~done_old)
|
||||
|
@ -3,17 +3,17 @@ from migen.genlib.io import DifferentialOutput, DifferentialInput, DDROutput
|
||||
|
||||
|
||||
class SamplerPads(Module):
|
||||
def __init__(self, platform, eem0, eem1):
|
||||
def __init__(self, platform, eem):
|
||||
self.sck_en = Signal()
|
||||
self.cnv = Signal()
|
||||
self.clkout = Signal()
|
||||
|
||||
spip = platform.request("{}_adc_spi_p".format(eem0))
|
||||
spin = platform.request("{}_adc_spi_n".format(eem0))
|
||||
cnv = platform.request("{}_cnv".format(eem0))
|
||||
sdr = platform.request("{}_sdr".format(eem0))
|
||||
dp = platform.request("{}_adc_data_p".format(eem0))
|
||||
dn = platform.request("{}_adc_data_n".format(eem0))
|
||||
spip = platform.request("{}_adc_spi_p".format(eem))
|
||||
spin = platform.request("{}_adc_spi_n".format(eem))
|
||||
cnv = platform.request("{}_cnv".format(eem))
|
||||
sdr = platform.request("{}_sdr".format(eem))
|
||||
dp = platform.request("{}_adc_data_p".format(eem))
|
||||
dn = platform.request("{}_adc_data_n".format(eem))
|
||||
|
||||
clkout_se = Signal()
|
||||
sck = Signal()
|
||||
@ -21,7 +21,7 @@ class SamplerPads(Module):
|
||||
self.specials += [
|
||||
DifferentialOutput(self.cnv, cnv.p, cnv.n),
|
||||
DifferentialOutput(1, sdr.p, sdr.n),
|
||||
DDROutput(self.sck_en, 0, sck),
|
||||
DDROutput(0, self.sck_en, sck, ClockSignal("rio_phy")),
|
||||
DifferentialOutput(sck, spip.clk, spin.clk),
|
||||
DifferentialInput(dp.clkout, dn.clkout, clkout_se),
|
||||
Instance("BUFR", i_I=clkout_se, o_O=self.clkout)
|
||||
@ -52,17 +52,17 @@ class SamplerPads(Module):
|
||||
|
||||
|
||||
class UrukulPads(Module):
|
||||
def __init__(self, platform, eem00, eem01, eem10, eem11):
|
||||
def __init__(self, platform, eem0, eem1):
|
||||
spip, spin = [[
|
||||
platform.request("{}_qspi_{}".format(eem, pol), 0)
|
||||
for eem in (eem00, eem10)] for pol in "pn"]
|
||||
for eem in (eem0, eem1)] for pol in "pn"]
|
||||
ioup = [platform.request("{}_io_update".format(eem), 0)
|
||||
for eem in (eem00, eem10)]
|
||||
for eem in (eem0, eem1)]
|
||||
self.cs_n = Signal()
|
||||
self.clk = Signal()
|
||||
self.io_update = Signal()
|
||||
self.specials += [(
|
||||
DifferentialOutput(self.cs_n, spip[i].cs_n, spin[i].cs_n),
|
||||
DifferentialOutput(~self.cs_n, spip[i].cs, spin[i].cs),
|
||||
DifferentialOutput(self.clk, spip[i].clk, spin[i].clk),
|
||||
DifferentialOutput(self.io_update, ioup[i].p, ioup[i].n))
|
||||
for i in range(2)]
|
||||
|
@ -24,38 +24,37 @@ class Servo(Module):
|
||||
assert t_iir + (2 << iir_p.channel) < t_cycle, "need shifting time"
|
||||
|
||||
self.start = Signal()
|
||||
t_restart = t_cycle - t_adc
|
||||
t_restart = t_cycle - t_adc + 1
|
||||
assert t_restart > 0
|
||||
cnt = Signal(max=t_restart + 1)
|
||||
cnt = Signal(max=t_restart)
|
||||
cnt_done = Signal()
|
||||
token = Signal(2)
|
||||
active = Signal(3)
|
||||
self.done = Signal()
|
||||
iir_done = Signal()
|
||||
self.comb += [
|
||||
cnt_done.eq(cnt == 0),
|
||||
iir_done.eq(self.iir.shifting | self.iir.done),
|
||||
self.adc.start.eq(self.start & cnt_done),
|
||||
self.iir.start.eq(token[0] & self.adc.done),
|
||||
self.dds.start.eq(token[1] & iir_done),
|
||||
self.done.eq(self.dds.done),
|
||||
]
|
||||
self.sync += [
|
||||
If(self.adc.done & ~cnt_done,
|
||||
cnt.eq(cnt - 1),
|
||||
If(self.dds.done,
|
||||
active[2].eq(0)
|
||||
),
|
||||
If(self.adc.start,
|
||||
cnt.eq(t_restart),
|
||||
If(self.dds.start & self.dds.done,
|
||||
active[2].eq(1),
|
||||
active[1].eq(0)
|
||||
),
|
||||
If(self.adc.done,
|
||||
token[0].eq(0)
|
||||
If(self.iir.start & self.iir.done,
|
||||
active[1].eq(1),
|
||||
active[0].eq(0)
|
||||
),
|
||||
If(self.adc.start,
|
||||
token[0].eq(1)
|
||||
If(~cnt_done & self.adc.done,
|
||||
cnt.eq(cnt - 1)
|
||||
),
|
||||
If(iir_done,
|
||||
token[1].eq(0)
|
||||
),
|
||||
If(self.iir.start,
|
||||
token[1].eq(1)
|
||||
If(self.adc.start & self.adc.done,
|
||||
active[0].eq(1),
|
||||
cnt.eq(t_restart - 1)
|
||||
)
|
||||
]
|
||||
self.comb += [
|
||||
cnt_done.eq(cnt == 0),
|
||||
self.adc.start.eq(self.start & cnt_done),
|
||||
self.iir.start.eq(active[0] & self.adc.done),
|
||||
self.dds.start.eq(active[1] &
|
||||
(self.iir.shifting | self.iir.done)),
|
||||
self.done.eq(self.dds.done),
|
||||
]
|
||||
|
@ -37,8 +37,6 @@ class SPISimple(Module):
|
||||
|
||||
assert p.clk >= 1
|
||||
|
||||
cs_n = pads.cs_n
|
||||
clk = pads.clk
|
||||
cnt = Signal(max=max(2, p.clk), reset_less=True)
|
||||
cnt_done = Signal()
|
||||
cnt_next = Signal()
|
||||
@ -54,21 +52,17 @@ class SPISimple(Module):
|
||||
]
|
||||
|
||||
for i, d in enumerate(self.data):
|
||||
self.comb += [
|
||||
getattr(pads, "mosi{}".format(i)).eq(d[-1])
|
||||
]
|
||||
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)
|
||||
]
|
||||
self.comb += fsm.ce.eq(cnt_done)
|
||||
|
||||
fsm.act("IDLE",
|
||||
self.done.eq(1),
|
||||
cs_n.eq(1),
|
||||
pads.cs_n.eq(1),
|
||||
If(self.start,
|
||||
cnt_next.eq(1),
|
||||
NextState("SETUP")
|
||||
@ -84,7 +78,7 @@ class SPISimple(Module):
|
||||
)
|
||||
fsm.act("HOLD",
|
||||
cnt_next.eq(1),
|
||||
clk.eq(1),
|
||||
pads.clk.eq(1),
|
||||
NextState("SETUP")
|
||||
)
|
||||
|
||||
|
@ -224,7 +224,7 @@ def _sampler(eem, eem_aux=None):
|
||||
Subsignal("sdod", Pins(_eem_pin(eem_aux, 4, "n"))),
|
||||
IOStandard("LVDS_25"),
|
||||
),
|
||||
]
|
||||
]
|
||||
return ios
|
||||
|
||||
|
||||
@ -362,7 +362,7 @@ def _urukul_qspi(eem0, eem1):
|
||||
))
|
||||
ios += [
|
||||
("{}_qspi_p".format(eem0), 0,
|
||||
Subsignal("cs_n", Pins(_eem_pin(eem0, 5, "p"))),
|
||||
Subsignal("cs", Pins(_eem_pin(eem0, 5, "p"))),
|
||||
Subsignal("clk", Pins(_eem_pin(eem0, 2, "p"))),
|
||||
Subsignal("mosi0", Pins(_eem_pin(eem1, 0, "p"))),
|
||||
Subsignal("mosi1", Pins(_eem_pin(eem1, 1, "p"))),
|
||||
@ -371,7 +371,7 @@ def _urukul_qspi(eem0, eem1):
|
||||
IOStandard("LVDS_25"),
|
||||
),
|
||||
("{}_qspi_n".format(eem0), 0,
|
||||
Subsignal("cs_n", Pins(_eem_pin(eem0, 5, "n"))),
|
||||
Subsignal("cs", Pins(_eem_pin(eem0, 5, "n"))),
|
||||
Subsignal("clk", Pins(_eem_pin(eem0, 2, "n"))),
|
||||
Subsignal("mosi0", Pins(_eem_pin(eem1, 0, "n"))),
|
||||
Subsignal("mosi1", Pins(_eem_pin(eem1, 1, "n"))),
|
||||
@ -525,25 +525,25 @@ class SUServo(_StandaloneBase):
|
||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||
|
||||
# EEM3, EEM2: Sampler
|
||||
sampler_pads = servo_pads.SamplerPads(self.platform, "eem3", "eem2")
|
||||
sampler_pads = servo_pads.SamplerPads(self.platform, "eem3")
|
||||
# EEM5, EEM4 and EEM7, EEM6: Urukul
|
||||
urukul_pads = servo_pads.UrukulPads(self.platform,
|
||||
"eem5", "eem4", "eem7", "eem6")
|
||||
adc_p = servo.ADCParams(width=16, channels=8, lanes=4,
|
||||
t_cnvh=4, t_conv=57, t_rtt=4)
|
||||
iir_p = servo.IIRWidths(state=25, coeff=18, adc=16,
|
||||
asf=14, word=16, accu=48, shift=11,
|
||||
channel=3, profile=5)
|
||||
"eem5", "eem7")
|
||||
adc_p = servo.ADCParams(width=16, channels=8, lanes=4, t_cnvh=4,
|
||||
# account for SCK pipeline latency
|
||||
t_conv=57 - 4, t_rtt=4 + 4)
|
||||
iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16,
|
||||
accu=48, shift=11, channel=3, profile=5)
|
||||
dds_p = servo.DDSParams(width=8 + 32 + 16 + 16,
|
||||
channels=adc_p.channels, clk=1)
|
||||
su = servo.Servo(sampler_pads, urukul_pads, adc_p, iir_p, dds_p)
|
||||
su = ClockDomainsRenamer({"sys": "rio_phy"})(su)
|
||||
su = ClockDomainsRenamer("rio_phy")(su)
|
||||
self.submodules += sampler_pads, urukul_pads, su
|
||||
|
||||
ctrls = [rtservo.RTServoCtrl(ctrl) for ctrl in su.iir.ctrl]
|
||||
self.submodules += ctrls
|
||||
rtio_channels.extend(rtio.Channel.from_phy(ctrl) for ctrl in ctrls)
|
||||
mem = rtservo.RTServoMem(iir_p, su.iir)
|
||||
mem = rtservo.RTServoMem(iir_p, su)
|
||||
self.submodules += mem
|
||||
rtio_channels.append(rtio.Channel.from_phy(mem, ififo_depth=4))
|
||||
|
||||
|
@ -37,7 +37,7 @@ class TB(Module):
|
||||
sr = Signal(p.width*p.channels//p.lanes, reset_less=True)
|
||||
srs.append(sr)
|
||||
self.sync.adc += [
|
||||
sdo.eq(self._dly(sr[-1], -1)),
|
||||
sdo.eq(self._dly(sr[-1], 0)),
|
||||
If(adc_sck_en,
|
||||
sr[1:].eq(sr)
|
||||
)
|
||||
@ -52,10 +52,10 @@ class TB(Module):
|
||||
|
||||
adc_clk_rec = Signal()
|
||||
self.comb += [
|
||||
adc_sck_en.eq(self._dly(self.sck_en, 1)),
|
||||
adc_sck_en.eq(self._dly(self.sck_en, 0)),
|
||||
self.sck_en_ret.eq(self._dly(adc_sck_en)),
|
||||
|
||||
adc_clk_rec.eq(self._dly(self.sck, 1)),
|
||||
adc_clk_rec.eq(self._dly(self.sck, 0)),
|
||||
self.clkout.eq(self._dly(adc_clk_rec)),
|
||||
]
|
||||
|
||||
|
@ -11,10 +11,9 @@ from artiq.gateware.suservo import servo
|
||||
class ServoSim(servo.Servo):
|
||||
def __init__(self):
|
||||
adc_p = servo.ADCParams(width=16, channels=8, lanes=4,
|
||||
t_cnvh=4, t_conv=57, t_rtt=4)
|
||||
iir_p = servo.IIRWidths(state=25, coeff=18, adc=16,
|
||||
asf=14, word=16, accu=48, shift=11,
|
||||
channel=3, profile=5)
|
||||
t_cnvh=4, t_conv=57 - 4, t_rtt=4 + 4)
|
||||
iir_p = servo.IIRWidths(state=25, coeff=18, adc=16, asf=14, word=16,
|
||||
accu=48, shift=11, channel=3, profile=5)
|
||||
dds_p = servo.DDSParams(width=8 + 32 + 16 + 16,
|
||||
channels=adc_p.channels, clk=1)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user