forked from M-Labs/artiq
urukul: add sync_in generator
for #1143 Signed-off-by: Robert Jördens <rj@quartiq.de>
This commit is contained in:
parent
f62c1ff0bb
commit
0433e8f4fe
|
@ -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)
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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"):
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue