urukul: add sync_in generator

for #1143

Signed-off-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
Robert Jördens 2018-10-25 09:51:21 +00:00
parent f62c1ff0bb
commit 0433e8f4fe
4 changed files with 63 additions and 22 deletions

View File

@ -115,6 +115,7 @@ class CPLD:
:param spi_device: SPI bus device name :param spi_device: SPI bus device name
:param io_update_device: IO update RTIO TTLOut channel name :param io_update_device: IO update RTIO TTLOut channel name
:param dds_reset_device: DDS reset RTIO TTLOut channel name :param dds_reset_device: DDS reset RTIO TTLOut channel name
:param sync_device: AD9910 SYNC_IN RTIO TTLClockGen channel name
:param refclk: Reference clock (SMA, MMCX or on-board 100 MHz oscillator) :param refclk: Reference clock (SMA, MMCX or on-board 100 MHz oscillator)
frequency in Hz frequency in Hz
:param clk_sel: Reference clock selection. For hardware revision >= 1.3 :param clk_sel: Reference clock selection. For hardware revision >= 1.3
@ -122,8 +123,8 @@ class CPLD:
internal MMCX. For hardware revision <= v1.2 valid options are: 0 - internal MMCX. For hardware revision <= v1.2 valid options are: 0 -
either XO or MMCX dependent on component population; 1 SMA. Unsupported either XO or MMCX dependent on component population; 1 SMA. Unsupported
clocking options are silently ignored. clocking options are silently ignored.
:param sync_sel: SYNC clock selection. 0 corresponds to SYNC clock over EEM :param sync_sel: SYNC_IN selection. 0 corresponds to SYNC_IN over EEM
from FPGA. 1 corresponds to SYNC clock from DDS0. from FPGA. 1 corresponds to SYNC_IN from DDS0.
:param rf_sw: Initial CPLD RF switch register setting (default: 0x0). :param rf_sw: Initial CPLD RF switch register setting (default: 0x0).
Knowledge of this state is not transferred between experiments. Knowledge of this state is not transferred between experiments.
:param att: Initial attenuator setting shift register (default: :param att: Initial attenuator setting shift register (default:
@ -134,7 +135,8 @@ class CPLD:
kernel_invariants = {"refclk", "bus", "core", "io_update"} kernel_invariants = {"refclk", "bus", "core", "io_update"}
def __init__(self, dmgr, spi_device, io_update_device=None, def __init__(self, dmgr, spi_device, io_update_device=None,
dds_reset_device=None, sync_sel=0, clk_sel=0, rf_sw=0, dds_reset_device=None, sync_device=None,
sync_sel=0, clk_sel=0, rf_sw=0,
refclk=125e6, att=0x00000000, core_device="core"): refclk=125e6, att=0x00000000, core_device="core"):
self.core = dmgr.get(core_device) self.core = dmgr.get(core_device)
@ -147,6 +149,8 @@ class CPLD:
self.io_update = _RegIOUpdate(self) self.io_update = _RegIOUpdate(self)
if dds_reset_device is not None: if dds_reset_device is not None:
self.dds_reset = dmgr.get(dds_reset_device) self.dds_reset = dmgr.get(dds_reset_device)
if sync_device is not None:
self.sync = dmgr.get(sync_device)
self.cfg_reg = urukul_cfg(rf_sw=rf_sw, led=0, profile=0, self.cfg_reg = urukul_cfg(rf_sw=rf_sw, led=0, profile=0,
io_update=0, mask_nu=0, clk_sel=clk_sel, io_update=0, mask_nu=0, clk_sel=clk_sel,
@ -289,3 +293,20 @@ class CPLD:
SPIT_ATT_RD, CS_ATT) SPIT_ATT_RD, CS_ATT)
self.bus.write(self.att_reg) self.bus.write(self.att_reg)
return self.bus.read() return self.bus.read()
@kernel
def set_sync_div(self, div):
"""Set the SYNC_IN AD9910 pulse generator frequency
and align it to the current RTIO timestamp.
The SYNC_IN signal is derived from the coarse RTIO clock
and the divider must be a power of two two.
Configure ``sync_sel == 0``.
:param div: SYNC_IN frequency divider. Must be a power of two.
Minimum division ratio is 2. Maximum division ratio is 16.
"""
ftw_max = 1 << 4
ftw = ftw_max//div
assert ftw*div == ftw_max
self.sync.set_mu(ftw)

View File

@ -87,36 +87,42 @@ device_db.update({
"class": "SPIMaster", "class": "SPIMaster",
"arguments": {"channel": 27} "arguments": {"channel": 27}
}, },
"ttl_urukul0_io_update": { "ttl_urukul0_sync": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLClockGen",
"arguments": {"channel": 28} "arguments": {"channel": 28, "acc_width": 4}
}, },
"ttl_urukul0_sw0": { "ttl_urukul0_io_update": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 29} "arguments": {"channel": 29}
}, },
"ttl_urukul0_sw1": { "ttl_urukul0_sw0": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 30} "arguments": {"channel": 30}
}, },
"ttl_urukul0_sw2": { "ttl_urukul0_sw1": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 31} "arguments": {"channel": 31}
}, },
"ttl_urukul0_sw3": { "ttl_urukul0_sw2": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 32} "arguments": {"channel": 32}
}, },
"ttl_urukul0_sw3": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLOut",
"arguments": {"channel": 33}
},
"urukul0_cpld": { "urukul0_cpld": {
"type": "local", "type": "local",
"module": "artiq.coredevice.urukul", "module": "artiq.coredevice.urukul",
@ -124,6 +130,7 @@ device_db.update({
"arguments": { "arguments": {
"spi_device": "spi_urukul0", "spi_device": "spi_urukul0",
"io_update_device": "ttl_urukul0_io_update", "io_update_device": "ttl_urukul0_io_update",
"sync_device": "ttl_urukul0_sync",
"refclk": 100e6, "refclk": 100e6,
"clk_sel": 0 "clk_sel": 0
} }
@ -150,13 +157,19 @@ device_db.update({
"type": "local", "type": "local",
"module": "artiq.coredevice.spi2", "module": "artiq.coredevice.spi2",
"class": "SPIMaster", "class": "SPIMaster",
"arguments": {"channel": 33} "arguments": {"channel": 34}
},
"ttl_urukul1_sync": {
"type": "local",
"module": "artiq.coredevice.ttl",
"class": "TTLClockGen",
"arguments": {"channel": 35, "acc_width": 4}
}, },
"ttl_urukul1_io_update": { "ttl_urukul1_io_update": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 34} "arguments": {"channel": 36}
}, },
"urukul1_cpld": { "urukul1_cpld": {
"type": "local", "type": "local",
@ -190,13 +203,13 @@ device_db.update({
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 35} "arguments": {"channel": 37}
}, },
"led1": { "led1": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 36} "arguments": {"channel": 38}
} }
}) })
@ -206,19 +219,19 @@ device_db.update({
"type": "local", "type": "local",
"module": "artiq.coredevice.spi2", "module": "artiq.coredevice.spi2",
"class": "SPIMaster", "class": "SPIMaster",
"arguments": {"channel": 37} "arguments": {"channel": 39}
}, },
"ttl_zotino0_ldac": { "ttl_zotino0_ldac": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 38} "arguments": {"channel": 40}
}, },
"ttl_zotino0_clr": { "ttl_zotino0_clr": {
"type": "local", "type": "local",
"module": "artiq.coredevice.ttl", "module": "artiq.coredevice.ttl",
"class": "TTLOut", "class": "TTLOut",
"arguments": {"channel": 40} "arguments": {"channel": 41}
}, },
"zotino0": { "zotino0": {
"type": "local", "type": "local",

View File

@ -148,7 +148,8 @@ class Urukul(_EEM):
return ios return ios
@classmethod @classmethod
def add_std(cls, target, eem, eem_aux, ttl_out_cls, iostandard="LVDS_25"): def add_std(cls, target, eem, eem_aux, ttl_out_cls, sync_gen_cls=None,
iostandard="LVDS_25"):
cls.add_extension(target, eem, eem_aux, iostandard=iostandard) cls.add_extension(target, eem, eem_aux, iostandard=iostandard)
phy = spi2.SPIMaster(target.platform.request("urukul{}_spi_p".format(eem)), phy = spi2.SPIMaster(target.platform.request("urukul{}_spi_p".format(eem)),
@ -157,7 +158,12 @@ class Urukul(_EEM):
target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4)) target.rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=4))
pads = target.platform.request("urukul{}_dds_reset".format(eem)) pads = target.platform.request("urukul{}_dds_reset".format(eem))
target.specials += DifferentialOutput(0, pads.p, pads.n) pad = Signal(reset=0)
target.specials += DifferentialOutput(pad, pads.p, pads.n)
if sync_gen_cls is not None: # AD9910 variant and SYNC_IN from EEM
phy = sync_gen_cls(pad, ftw_width=4)
target.submodules += phy
target.rtio_channels.append(rtio.Channel.from_phy(phy))
pads = target.platform.request("urukul{}_io_update".format(eem)) pads = target.platform.request("urukul{}_io_update".format(eem))
phy = ttl_out_cls(pads.p, pads.n) phy = ttl_out_cls(pads.p, pads.n)
@ -170,7 +176,6 @@ class Urukul(_EEM):
target.submodules += phy target.submodules += phy
target.rtio_channels.append(rtio.Channel.from_phy(phy)) target.rtio_channels.append(rtio.Channel.from_phy(phy))
class Sampler(_EEM): class Sampler(_EEM):
@staticmethod @staticmethod
def io(eem, eem_aux, iostandard="LVDS_25"): def io(eem, eem_aux, iostandard="LVDS_25"):

View File

@ -516,8 +516,10 @@ class PTB(_StandaloneBase):
eem.DIO.add_std(self, 2, eem.DIO.add_std(self, 2,
ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X) ttl_serdes_7series.Output_8X, ttl_serdes_7series.Output_8X)
eem.Sampler.add_std(self, 3, None, ttl_serdes_7series.Output_8X) eem.Sampler.add_std(self, 3, None, ttl_serdes_7series.Output_8X)
eem.Urukul.add_std(self, 5, 4, ttl_serdes_7series.Output_8X) eem.Urukul.add_std(self, 5, 4, ttl_serdes_7series.Output_8X,
eem.Urukul.add_std(self, 6, None, ttl_serdes_7series.Output_8X) ttl_simple.ClockGen)
eem.Urukul.add_std(self, 6, None, ttl_serdes_7series.Output_8X,
ttl_simple.ClockGen)
for i in (1, 2): for i in (1, 2):
sfp_ctl = self.platform.request("sfp_ctl", i) sfp_ctl = self.platform.request("sfp_ctl", i)