diff --git a/README_PHASER.rst b/README_PHASER.rst new file mode 100644 index 000000000..aa0b5f187 --- /dev/null +++ b/README_PHASER.rst @@ -0,0 +1,117 @@ +ARTIQ Phaser +============ + +This ARTIQ branch contains a proof-of-concept design of a GHz-datarate, multi-channel, interpolating, multi-tone, direct digital synthesizer (DDS) compatible with ARTIQ's RTIO channels. +Ultimately it will be the basis for the ARTIQ Sayma Smart Arbitrary Waveform Generator project. See https://github.com/m-labs/sinara and https://github.com/m-labs/artiq-hardware. + +*Features*: + +* up to 4 channels +* up to 500 MHz data rate per channel (KC705 limitation) +* up to 8x interpolation to 2.4 GHz DAC sample rate +* Real-time sample-coherent control over amplitude, frequency, phase of each channel through ARTIQ RTIO commands +* Full configurability of the AD9154 and AD9516 through SPI with ARTIQ kernel support +* All SPI registers and register bits exposed as human readable names +* Parametrized JESD204B core (also capable of operation with eight lanes) +* The code can be reconfigured. Possible example configurations are: support 2 channels at 1 GHz datarate, support 4 channels at 300 MHz data rate, no interpolation, and using mix mode to stress the second and third Nyquist zones (150-300 MHz and 300-450 MHz). + +The hardware required to use the ARTIQ phaser branch is a KC705 with an AD9154-FMC-EBZ plugged into the HPC connector and a low-noise sample rate reference clock. + +This work was supported by the Army Research Lab and the University of Maryland. + +The code that was developed for this project is located in several repositories: + +* In ARTIQ, the SAWG and Phaser code: https://github.com/m-labs/artiq/compare/phaser2 +* The Migen/MiSoC JESD204B core: https://github.com/m-labs/jesd204b + + +Installation +------------ + +These installation instructions are a short form of those in the ARTIQ manual. +Please refer to and follow the ARTIQ manual for more details: +https://m-labs.hk/artiq/manual-master/index.html + +* Set up a new conda environment and activate it. +* Install the standard ARTIQ runtime/install dependencies. + See ``conda/artiq/meta.yaml`` for a list. + They are all packaged as conda packages in ``m-labs/main``. + +* Install the standard ARTIQ build dependencies. + They are all available as conda packages in m-labs/main or m-labs/dev for linux-64: + + - migen + - misoc + - jesd204b + - llvm-or1k + - rust-core-or1k + - cargo + - binutils-or1k-linux + +* Install a recent version of Vivado (tested and developed with 2016.2). +* Do a checkout of the ARTIQ phaser2 branch: :: + + mkdir ~/src + cd ~/src + git clone --recursive -b phaser2 https://github.com/m-labs/artiq.git + cd ../artiq + python setup.py develop + + +Setup +----- + +* Setup the KC705 (jumpers, etc.) observing the ARTIQ manual. + VADJ does not need to be changed. +* On the AD9154-FMC-EBZ put jumpers: + + - on XP1, between pin 5 and 6 (will keep the PIC in reset) + - on JP3 (will force output enable on FXLA108) + +* Compile the ARTIQ Phaser bitstream, bios, and runtime (c.f. ARTIQ manual): :: + + python -m artiq.gateware.targets.phaser + +* Generate an ARTIQ configuration flash image with MAC and IP address (see the + documentation for ``artiq_mkfs``). Name it ``phaser_config.bin``. +* Run the following OpenOCD command to flash the ARTIQ phaser design: :: + + openocd -f board/kc705.cfg -c "init; jtagspi_init 0 bscan_spi_xc7k325t.bit; jtagspi_program misoc_phaser_kc705/gateware/top.bin 0x000000; jtagspi_program misoc_phaser_kc705/software/bios/bios.bin 0xaf0000; jtagspi_program misoc_phaser_kc705/software/runtime/runtime.fbi 0xb00000;jtagspi_program phaser_config.bin 0xb80000; xc7_program xc7.tap; exit" + + The proxy bitstream ``bscan_spi_xc7k325t.bit`` can be found at https://github.com/jordens/bscan_spi_bitstreams or in any ARTIQ conda package for the KC705. + See the source code of ``artiq_flash.py`` from ARTIQ for more details. + + If you are using the OpenOCD Conda package: + + * locate the OpenOCD scripts directory with: ``python3 -c "import artiq.frontend.artiq_flash as af; print(af.scripts_path)"`` + * add ``-s `` to the OpenOCD command line. + +* Refer to the ARTIQ documentation to configure an IP address and other settings for the transmitter device. + If the board was running stock ARTIQ before, the settings will be kept. +* A 300 MHz clock of roughly 10 dBm (0.2 to 3.4 V peak-to-peak into 50 Ohm) must be connected to the AD9154-FMC-EBZ J1. + The external RTIO clock, DAC deviceclock, FPGA deviceclock, and SYSREF are derived from this signal. There is no internal RTIO clock. +* An example device database, several status and test scripts are provided in ``artiq/examples/phaser/``. :: + + cd artiq/examples/phaser + +* Edit ``device_db.pyon`` to match the hostname or IP address of the core device. +* The ``startup_clock`` needs to be set to internal (``i``) for bootstrapping the clock distribution tree. +* Compile and flash the startup kernel in ``artiq/examples/phaser/startup_kernel.py``. +* Erase any possible idle kernels. +* Use ``ping`` and ``flterm`` to verify that the core device starts up and boots correctly. + +Usage +----- + +* After each boot, run the ``dac_setup.py`` experiment to establish the JESD204B links (``artiq_run repository/dac_setup.py``). +* Run ``artiq_run repository/ad9154_test_status.py`` to retrieve and print several status registers from the AD9154 DAC. +* Run ``artiq_run repository/ad9154_test_prbs.py`` to test the JESD204B PHY layer for bit errors. Reboot the core device afterwards. +* Run ``artiq_run repository/ad9154_test_stpl.py`` to executes a JESD204B short transport layer test. +* Run ``artiq_run repository/demo.py`` for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates. + for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates. +* Run ``artiq_run repository/demo_2tone.py`` for an example that emits a shaped two-tone pulse. +* Implement your own experiments using the SAWG channels. +* Verify clock stability between the sample rate reference clock and the DAC outputs. +* Changes to the AD9154 configuration can also be performed at runtime in experiments. + See the example ``dac_setup.py``. + This can e.g. be used to enable and evaluate mix mode without having to change any other code (bitstream/bios/runtime/startup_kernel). diff --git a/artiq/coredevice/ad9154.py b/artiq/coredevice/ad9154.py new file mode 100644 index 000000000..64bb7fbf3 --- /dev/null +++ b/artiq/coredevice/ad9154.py @@ -0,0 +1,106 @@ +from artiq.language.core import kernel, syscall +from artiq.language.types import TInt32, TNone + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_init() -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_write(addr: TInt32, data: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_read(addr: TInt32) -> TInt32: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9516_write(addr: TInt32, data: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9516_read(addr: TInt32) -> TInt32: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_jesd_enable(en: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_jesd_ready() -> TInt32: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_jesd_prbs(prbs: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +@syscall(flags={"nounwind", "nowrite"}) +def ad9154_jesd_stpl(prbs: TInt32) -> TNone: + raise NotImplementedError("syscall not simulated") + + +class AD9154: + """AD9154-FMC-EBZ SPI support + + There are two devices on the SPI bus, a AD9154 DAC and a AD9516 clock + divider/fanout. + + Register and bit names are in :mod:`artiq.coredevice.ad9154_reg` and + :mod:`artiq.coredevice.ad9516_reg` respectively. + + The SPI bus does not operate over RTIO but directly. This class does not + interact with the timeline. + """ + def __init__(self, dmgr, core_device="core"): + self.core = dmgr.get(core_device) + + @kernel + def init(self): + """Initialize and configure the SPI bus.""" + ad9154_init() + + @kernel + def dac_write(self, addr, data): + """Write `data` to AD9154 SPI register at `addr`.""" + ad9154_write(addr, data) + + @kernel + def dac_read(self, addr): + """Read AD9154 SPI register at `addr`.""" + return ad9154_read(addr) + + @kernel + def clock_write(self, addr, data): + """Write `data` to AD9516 SPI register at `addr`.""" + ad9516_write(addr, data) + + @kernel + def clock_read(self, addr): + """Read AD9516 SPI register at `addr`.""" + return ad9516_read(addr) + + @kernel + def jesd_enable(self, en): + """Enables the JESD204B core startup sequence.""" + ad9154_jesd_enable(en) + + @kernel + def jesd_ready(self): + """Returns `True` if the JESD links are up.""" + return ad9154_jesd_ready() + + @kernel + def jesd_prbs(self, prbs): + ad9154_jesd_prbs(prbs) + + @kernel + def jesd_stpl(self, enable): + ad9154_jesd_stpl(enable) diff --git a/artiq/coredevice/ad9154_reg.py b/artiq/coredevice/ad9154_reg.py new file mode 100644 index 000000000..a7d414e96 --- /dev/null +++ b/artiq/coredevice/ad9154_reg.py @@ -0,0 +1,2996 @@ +# auto-generated, do not edit +from artiq.language.core import portable +from artiq.language.types import TInt32 + +AD9154_SPI_INTFCONFA = 0x000 +# default: 0x00, access: R/W +@portable +def AD9154_SOFTRESET_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_SOFTRESET_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LSBFIRST_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_LSBFIRST_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ADDRINC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_ADDRINC_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SDOACTIVE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SDOACTIVE_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SDOACTIVE_M_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SDOACTIVE_M_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ADDRINC_M_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_ADDRINC_M_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LSBFIRST_M_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_LSBFIRST_M_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SOFTRESET_M_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_SOFTRESET_M_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_CHIPTYPE = 0x003 + +AD9154_PRODIDL = 0x004 + +AD9154_PRODIDH = 0x005 + +AD9154_CHIPGRADE = 0x006 +# default: 0x02, access: R +@portable +def AD9154_DEV_REVISION_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R +@portable +def AD9154_PROD_GRADE_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_SPI_PAGEINDX = 0x008 + +AD9154_PWRCNTRL0 = 0x011 +# default: 0x01, access: R/W +@portable +def AD9154_PD_DAC3_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_PD_DAC3_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_DAC2_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_PD_DAC2_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_DAC1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_PD_DAC1_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_DAC0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_PD_DAC0_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PD_BG_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_PD_BG_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_TXENMASK1 = 0x012 +# default: 0x00, access: R/W +@portable +def AD9154_DACA_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_DACA_MASK_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_DACB_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_DACB_MASK_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_PWRCNTRL3 = 0x013 +# default: 0x00, access: R/W +@portable +def AD9154_SPI_TXEN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_SPI_TXEN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ENA_SPI_TXEN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_ENA_SPI_TXEN_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_PA_CTRL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_PA_CTRL_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ENA_PA_CTRL_FROM_SPI_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_ENA_PA_CTRL_FROM_SPI_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ENA_PA_CTRL_FROM_BLSM_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_ENA_PA_CTRL_FROM_BLSM_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_ENA_PA_CTRL_FROM_TXENSM_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_ENA_PA_CTRL_FROM_TXENSM_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ENA_PA_CTRL_FROM_PARROT_ERR_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_ENA_PA_CTRL_FROM_PARROT_ERR_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_GROUP_DLY = 0x014 +# default: 0x08, access: R/W +@portable +def AD9154_COARSE_GROUP_DELAY_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_COARSE_GROUP_DELAY_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x08, access: R/W +@portable +def AD9154_GROUP_DELAY_RESERVED_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_GROUP_DELAY_RESERVED_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_IRQEN_STATUSMODE0 = 0x01f +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_LANEFIFOERR_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_IRQEN_SMODE_LANEFIFOERR_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SERPLLLOCK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_IRQEN_SMODE_SERPLLLOCK_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SERPLLLOST_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_IRQEN_SMODE_SERPLLLOST_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_DACPLLLOCK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_IRQEN_SMODE_DACPLLLOCK_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_DACPLLLOST_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_IRQEN_SMODE_DACPLLLOST_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_IRQEN_STATUSMODE1 = 0x020 +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PRBS0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_IRQEN_SMODE_PRBS0_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PRBS1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_IRQEN_SMODE_PRBS1_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PRBS2_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_IRQEN_SMODE_PRBS2_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PRBS3_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_IRQEN_SMODE_PRBS3_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + + +AD9154_IRQEN_STATUSMODE2 = 0x021 +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_TRIP0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_IRQEN_SMODE_SYNC_TRIP0_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_WLIM0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_IRQEN_SMODE_SYNC_WLIM0_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_ROTATE0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_IRQEN_SMODE_SYNC_ROTATE0_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_LOCK0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_IRQEN_SMODE_SYNC_LOCK0_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_NCO_ALIGN0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_IRQEN_SMODE_NCO_ALIGN0_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_BLNKDONE0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_IRQEN_SMODE_BLNKDONE0_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PDPERR0_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_IRQEN_SMODE_PDPERR0_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_IRQEN_STATUSMODE3 = 0x022 +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_TRIP1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_IRQEN_SMODE_SYNC_TRIP1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_WLIM1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_IRQEN_SMODE_SYNC_WLIM1_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_ROTATE1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_IRQEN_SMODE_SYNC_ROTATE1_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_SYNC_LOCK1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_IRQEN_SMODE_SYNC_LOCK1_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_NCO_ALIGN1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_IRQEN_SMODE_NCO_ALIGN1_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_BLNKDONE1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_IRQEN_SMODE_BLNKDONE1_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_IRQEN_SMODE_PDPERR1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_IRQEN_SMODE_PDPERR1_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_IRQ_STATUS0 = 0x023 +# default: 0x00, access: R +@portable +def AD9154_LANEFIFOERR_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERPLLLOCK_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERPLLLOST_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_DACPLLLOCK_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_DACPLLLOST_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_IRQ_STATUS1 = 0x024 +# default: 0x00, access: R +@portable +def AD9154_PRBS0_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PRBS1_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PRBS2_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PRBS3_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + + +AD9154_IRQ_STATUS2 = 0x025 +# default: 0x00, access: R +@portable +def AD9154_SYNC_TRIP0_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_WLIM0_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_ROTATE0_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_LOCK0_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_NCO_ALIGN0_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_BLNKDONE0_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PDPERR0_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_IRQ_STATUS3 = 0x026 +# default: 0x00, access: R +@portable +def AD9154_SYNC_TRIP1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_WLIM1_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_ROTATE1_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_LOCK1_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_NCO_ALIGN1_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_BLNKDONE1_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PDPERR1_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_JESD_CHECKS = 0x030 +# default: 0x00, access: R +@portable +def AD9154_ERR_INTSUPP_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ERR_SUBCLASS_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ERR_KUNSUPP_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ERR_JESDBAD_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ERR_WINLIMIT_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ERR_DLYOVER_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_SYNC_ERRWINDOW = 0x034 + +AD9154_SYNC_LASTERR_L = 0x038 + +AD9154_SYNC_LASTERR_H = 0x039 +# default: 0x00, access: R +@portable +def AD9154_LASTERROR_H_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_LASTOVER_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_LASTUNDER_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_SYNC_CONTROL = 0x03a +# default: 0x00, access: R/W +@portable +def AD9154_SYNCMODE_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_SYNCMODE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R/W +@portable +def AD9154_SYNCCLRLAST_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SYNCCLRLAST_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SYNCCLRSTKY_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_SYNCCLRSTKY_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SYNCARM_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_SYNCARM_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SYNCENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_SYNCENABLE_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_SYNC_STATUS = 0x03b +# default: 0x00, access: R +@portable +def AD9154_SYNC_TRIP_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_WLIM_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_ROTATE_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_LOCK_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SYNC_BUSY_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_SYNC_CURRERR_L = 0x03c + +AD9154_SYNC_CURRERR_H = 0x03d +# default: 0x00, access: R +@portable +def AD9154_CURRERROR_H_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_CURROVER_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_CURRUNDER_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACGAIN0_I = 0x040 + +AD9154_DACGAIN1_I = 0x041 + +AD9154_DACGAIN0_Q = 0x042 + +AD9154_DACGAIN1_Q = 0x043 + +AD9154_GROUPDELAY_COMP_I = 0x044 + +AD9154_GROUPDELAY_COMP_Q = 0x045 + +AD9154_GROUPDELAY_COMP_BYP = 0x046 +# default: 0x01, access: R/W +@portable +def AD9154_GROUPCOMP_BYPQ_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_GROUPCOMP_BYPQ_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_GROUPCOMP_BYPI_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_GROUPCOMP_BYPI_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + + +AD9154_MIX_MODE = 0x04a + +AD9154_NCOALIGN_MODE = 0x050 +# default: 0x00, access: R/W +@portable +def AD9154_NCO_ALIGN_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_NCO_ALIGN_MODE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R +@portable +def AD9154_NCO_ALIGN_FAIL_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_NCO_ALIGN_PASS_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_NCO_ALIGN_MTCH_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_NCO_ALIGN_ARM_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_NCO_ALIGN_ARM_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_NCOKEY_ILSB = 0x051 + +AD9154_NCOKEY_IMSB = 0x052 + +AD9154_NCOKEY_QLSB = 0x053 + +AD9154_NCOKEY_QMSB = 0x054 + +AD9154_PDP_THRES0 = 0x060 + +AD9154_PDP_THRES1 = 0x061 + +AD9154_PDP_AVG_TIME = 0x062 +# default: 0x00, access: R/W +@portable +def AD9154_PDP_AVG_TIME__SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_PDP_AVG_TIME__GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R/W +@portable +def AD9154_PA_BUS_SWAP_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_PA_BUS_SWAP_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PDP_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_PDP_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_PDP_POWER0 = 0x063 + +AD9154_PDP_POWER1 = 0x064 + +AD9154_CLKCFG0 = 0x080 +# default: 0x00, access: R/W +@portable +def AD9154_REF_CLKDIV_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_REF_CLKDIV_EN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_RF_SYNC_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_RF_SYNC_EN_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_DUTY_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_DUTY_EN_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_CLK_REC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_PD_CLK_REC_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_SERDES_PCLK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_PD_SERDES_PCLK_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_CLK_DIG_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_PD_CLK_DIG_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_CLK23_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_PD_CLK23_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_CLK01_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_PD_CLK01_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_SYSREF_ACTRL0 = 0x081 +# default: 0x00, access: R/W +@portable +def AD9154_HYS_CNTRL1_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_HYS_CNTRL1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_SYSREF_RISE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SYSREF_RISE_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_HYS_ON_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_HYS_ON_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PD_SYSREF_BUFFER_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_PD_SYSREF_BUFFER_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + + +AD9154_SYSREF_ACTRL1 = 0x082 + +AD9154_DACPLLCNTRL = 0x083 +# default: 0x00, access: R/W +@portable +def AD9154_ENABLE_DACPLL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_ENABLE_DACPLL_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_RECAL_DACPLL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_RECAL_DACPLL_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACPLLSTATUS = 0x084 +# default: 0x00, access: R +@portable +def AD9154_DACPLL_LOCK_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_VCO_CAL_PROGRESS_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_CP_CAL_VALID_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_CP_OVERRANGE_L_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_CP_OVERRANGE_H_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_DACINTEGERWORD0 = 0x085 + +AD9154_DACLOOPFILT1 = 0x087 +# default: 0x08, access: R/W +@portable +def AD9154_LF_C1_WORD_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_LF_C1_WORD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x08, access: R/W +@portable +def AD9154_LF_C2_WORD_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_LF_C2_WORD_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_DACLOOPFILT2 = 0x088 +# default: 0x08, access: R/W +@portable +def AD9154_LF_C3_WORD_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_LF_C3_WORD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x08, access: R/W +@portable +def AD9154_LF_R1_WORD_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_LF_R1_WORD_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_DACLOOPFILT3 = 0x089 +# default: 0x08, access: R/W +@portable +def AD9154_LF_R3_WORD_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_LF_R3_WORD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R/W +@portable +def AD9154_LF_BYPASS_C1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_LF_BYPASS_C1_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LF_BYPASS_C2_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_LF_BYPASS_C2_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LF_BYPASS_R1_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_LF_BYPASS_R1_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LF_BYPASS_R3_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_LF_BYPASS_R3_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACCPCNTRL = 0x08a +# default: 0x20, access: R/W +@portable +def AD9154_CP_CURRENT_SET(x: TInt32) -> TInt32: + return (x & 0x3f) << 0 + +@portable +def AD9154_CP_CURRENT_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3f + +# default: 0x00, access: R/W +@portable +def AD9154_VT_FORCE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_VT_FORCE_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_DACLOGENCNTRL = 0x08b +# default: 0x00, access: R/W +@portable +def AD9154_LODIVMODE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_LODIVMODE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_LO_POWER_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 4 + +@portable +def AD9154_LO_POWER_MODE_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x3 + + +AD9154_DACLDOCNTRL1 = 0x08c +# default: 0x00, access: R/W +@portable +def AD9154_REFDIVMODE_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_REFDIVMODE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x00, access: R/W +@portable +def AD9154_LDO_BYPASS_FLT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_LDO_BYPASS_FLT_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LDO_REF_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_LDO_REF_SEL_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACLDOCNTRL2 = 0x08d +# default: 0x03, access: R/W +@portable +def AD9154_LDO_VDROP_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_LDO_VDROP_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x02, access: R/W +@portable +def AD9154_LDO_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 2 + +@portable +def AD9154_LDO_SEL_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_LDO_INRUSH_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 5 + +@portable +def AD9154_LDO_INRUSH_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_LDO_BYPASS_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_LDO_BYPASS_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DATA_FORMAT = 0x110 +# default: 0x00, access: R/W +@portable +def AD9154_BINARY_FORMAT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_BINARY_FORMAT_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DATAPATH_CTRL = 0x111 +# default: 0x00, access: R/W +@portable +def AD9154_I_TO_Q_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_I_TO_Q_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SEL_SIDEBAND_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_SEL_SIDEBAND_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_MODULATION_TYPE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 2 + +@portable +def AD9154_MODULATION_TYPE_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_PHASE_ADJ_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_PHASE_ADJ_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_DIG_GAIN_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_DIG_GAIN_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_INVSINC_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_INVSINC_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_INTERP_MODE = 0x112 + +AD9154_NCO_FTW_UPDATE = 0x113 +# default: 0x00, access: R/W +@portable +def AD9154_FTW_UPDATE_REQ_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_FTW_UPDATE_REQ_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_FTW_UPDATE_ACK_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + + +AD9154_FTW0 = 0x114 + +AD9154_FTW1 = 0x115 + +AD9154_FTW2 = 0x116 + +AD9154_FTW3 = 0x117 + +AD9154_FTW4 = 0x118 + +AD9154_FTW5 = 0x119 + +AD9154_NCO_PHASE_OFFSET0 = 0x11a + +AD9154_NCO_PHASE_OFFSET1 = 0x11b + +AD9154_PHASE_ADJ0 = 0x11c + +AD9154_PHASE_ADJ1 = 0x11d + +AD9154_TXEN_SM_0 = 0x11f +# default: 0x01, access: R/W +@portable +def AD9154_TXEN_SM_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_TXEN_SM_EN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_GP_PA_CTRL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_GP_PA_CTRL_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_GP_PA_ON_INVERT_SET(x: TInt32) -> TInt32: + return (x & 0x0) << 2 + +@portable +def AD9154_GP_PA_ON_INVERT_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x0 + +# default: 0x00, access: R/W +@portable +def AD9154_RISE_COUNTERS_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 4 + +@portable +def AD9154_RISE_COUNTERS_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x3 + +# default: 0x02, access: R/W +@portable +def AD9154_FALL_COUNTERS_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 6 + +@portable +def AD9154_FALL_COUNTERS_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_TXEN_RISE_COUNT_0 = 0x121 + +AD9154_TXEN_RISE_COUNT_1 = 0x122 + +AD9154_TXEN_FALL_COUNT_0 = 0x123 + +AD9154_TXEN_FALL_COUNT_1 = 0x124 + +AD9154_DEVICE_CONFIG_REG_0 = 0x12d + +AD9154_DIE_TEMP_CTRL0 = 0x12f +# default: 0x00, access: R/W +@portable +def AD9154_AUXADC_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_AUXADC_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x10, access: R/W +@portable +def AD9154_AUXADC_RESERVED_SET(x: TInt32) -> TInt32: + return (x & 0x7f) << 1 + +@portable +def AD9154_AUXADC_RESERVED_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x7f + + +AD9154_DIE_TEMP0 = 0x132 + +AD9154_DIE_TEMP1 = 0x133 + +AD9154_DIE_TEMP_UPDATE = 0x134 + +AD9154_DC_OFFSET_CTRL = 0x135 + +AD9154_IPATH_DC_OFFSET_1PART0 = 0x136 + +AD9154_IPATH_DC_OFFSET_1PART1 = 0x137 + +AD9154_QPATH_DC_OFFSET_1PART0 = 0x138 + +AD9154_QPATH_DC_OFFSET_1PART1 = 0x139 + +AD9154_IPATH_DC_OFFSET_2PART = 0x13a + +AD9154_QPATH_DC_OFFSET_2PART = 0x13b + +AD9154_IDAC_DIG_GAIN0 = 0x13c + +AD9154_IDAC_DIG_GAIN1 = 0x13d + +AD9154_QDAC_DIG_GAIN0 = 0x13e + +AD9154_QDAC_DIG_GAIN1 = 0x13f + +AD9154_GAIN_RAMP_UP_STEP0 = 0x140 + +AD9154_GAIN_RAMP_UP_STEP1 = 0x141 + +AD9154_GAIN_RAMP_DOWN_STEP0 = 0x142 + +AD9154_GAIN_RAMP_DOWN_STEP1 = 0x143 + +AD9154_DEVICE_CONFIG_REG_1 = 0x146 + +AD9154_BSM_STAT = 0x147 +# default: 0x00, access: R +@portable +def AD9154_SOFTBLANKRB_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_PRBS = 0x14b +# default: 0x00, access: R/W +@portable +def AD9154_PRBS_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_PRBS_EN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PRBS_RESET_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_PRBS_RESET_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PRBS_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_PRBS_MODE_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PRBS_GOOD_I_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_PRBS_GOOD_Q_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_PRBS_ERROR_I = 0x14c + +AD9154_PRBS_ERROR_Q = 0x14d + +AD9154_DACPLLT0 = 0x1b0 +# default: 0x01, access: R/W +@portable +def AD9154_LOGEN_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_LOGEN_PD_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_LDO_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_LDO_PD_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SYNTH_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SYNTH_PD_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_VCO_PD_ALC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_VCO_PD_ALC_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_VCO_PD_PTAT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_VCO_PD_PTAT_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_VCO_PD_IN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_VCO_PD_IN_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACPLLT1 = 0x1b1 +# default: 0x00, access: R/W +@portable +def AD9154_PFD_EDGE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_PFD_EDGE_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_PFD_DELAY_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 2 + +@portable +def AD9154_PFD_DELAY_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x3 + + +AD9154_DACPLLT2 = 0x1b2 +# default: 0x00, access: R/W +@portable +def AD9154_EXT_ALC_WORD_SET(x: TInt32) -> TInt32: + return (x & 0x7f) << 0 + +@portable +def AD9154_EXT_ALC_WORD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7f + +# default: 0x00, access: R/W +@portable +def AD9154_EXT_ALC_WORD_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_EXT_ALC_WORD_EN_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACPLLT3 = 0x1b3 +# default: 0x00, access: W +@portable +def AD9154_EXT_BAND1_SET(x: TInt32) -> TInt32: + return (x & 0xff) << 0 + + +AD9154_DACPLLT4 = 0x1b4 +# default: 0x00, access: R/W +@portable +def AD9154_EXT_BAND2_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_EXT_BAND2_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_EXT_BAND_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_EXT_BAND_EN_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x0f, access: R/W +@portable +def AD9154_VCO_CAL_OFFSET_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 3 + +@portable +def AD9154_VCO_CAL_OFFSET_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0xf + +# default: 0x00, access: R/W +@portable +def AD9154_BYP_LOAD_DELAY_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_BYP_LOAD_DELAY_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_DACPLLT5 = 0x1b5 + +AD9154_DACPLLT6 = 0x1b6 + +AD9154_DACPLLT7 = 0x1b7 + +AD9154_DACPLLT8 = 0x1b8 + +AD9154_DACPLLT9 = 0x1b9 + +AD9154_DACPLLTA = 0x1ba + +AD9154_DACPLLTB = 0x1bb +# default: 0x04, access: R/W +@portable +def AD9154_VCO_BIAS_REF_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_VCO_BIAS_REF_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_VCO_BIAS_TCF_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 3 + +@portable +def AD9154_VCO_BIAS_TCF_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x3 + + +AD9154_DACPLLTC = 0x1bc + +AD9154_DACPLLTD = 0x1bd + +AD9154_DACPLLTE = 0x1be + +AD9154_DACPLLTF = 0x1bf + +AD9154_DACPLLT10 = 0x1c0 + +AD9154_DACPLLT11 = 0x1c1 + +AD9154_DACPLLT15 = 0x1c2 + +AD9154_DACPLLT16 = 0x1c3 + +AD9154_DACPLLT17 = 0x1c4 + +AD9154_DACPLLT18 = 0x1c5 + +AD9154_MASTER_PD = 0x200 + +AD9154_PHY_PD = 0x201 + +AD9154_GENERIC_PD = 0x203 +# default: 0x00, access: R/W +@portable +def AD9154_PD_SYNCOUT1B_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_PD_SYNCOUT1B_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PD_SYNCOUT0B_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_PD_SYNCOUT0B_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + + +AD9154_CDR_RESET = 0x206 + +AD9154_CDR_OPERATING_MODE_REG_0 = 0x230 +# default: 0x00, access: R/W +@portable +def AD9154_CDR_OVERSAMP_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_CDR_OVERSAMP_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x02, access: R/W +@portable +def AD9154_CDR_RESERVED_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 2 + +@portable +def AD9154_CDR_RESERVED_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_ENHALFRATE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_ENHALFRATE_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_EQ_BIAS_REG = 0x268 +# default: 0x22, access: R/W +@portable +def AD9154_EQ_BIAS_RESERVED_SET(x: TInt32) -> TInt32: + return (x & 0x3f) << 0 + +@portable +def AD9154_EQ_BIAS_RESERVED_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3f + +# default: 0x01, access: R/W +@portable +def AD9154_EQ_POWER_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 6 + +@portable +def AD9154_EQ_POWER_MODE_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_SERDESPLL_ENABLE_CNTRL = 0x280 +# default: 0x00, access: R/W +@portable +def AD9154_ENABLE_SERDESPLL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_ENABLE_SERDESPLL_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_RECAL_SERDESPLL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_RECAL_SERDESPLL_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + + +AD9154_PLL_STATUS = 0x281 +# default: 0x00, access: R +@portable +def AD9154_SERDES_PLL_LOCK_RB_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERDES_CURRENTS_READY_RB_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERDES_VCO_CAL_IN_PROGRESS_RB_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERDES_PLL_CAL_VALID_RB_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERDES_PLL_OVERRANGE_L_RB_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_SERDES_PLL_OVERRANGE_H_RB_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_LDO_FILTER_1 = 0x284 + +AD9154_LDO_FILTER_2 = 0x285 + +AD9154_LDO_FILTER_3 = 0x286 + +AD9154_CP_CURRENT_SPI = 0x287 +# default: 0x3f, access: R/W +@portable +def AD9154_SPI_CP_CURRENT_SET(x: TInt32) -> TInt32: + return (x & 0x3f) << 0 + +@portable +def AD9154_SPI_CP_CURRENT_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3f + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_SERDES_LOGEN_POWER_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_SPI_SERDES_LOGEN_POWER_MODE_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_REF_CLK_DIVIDER_LDO = 0x289 +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CDR_OVERSAMP_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_SPI_CDR_OVERSAMP_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_LDO_BYPASS_FILT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_LDO_BYPASS_FILT_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_LDO_REF_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SPI_LDO_REF_SEL_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + + +AD9154_VCO_LDO = 0x28a + +AD9154_PLL_RD_REG = 0x28b +# default: 0x01, access: R/W +@portable +def AD9154_SPI_SERDES_LOGEN_PD_CORE_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_SPI_SERDES_LOGEN_PD_CORE_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_SERDES_LDO_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_SERDES_LDO_PD_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_SYN_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SPI_SYN_PD_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_VCO_PD_ALC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SPI_VCO_PD_ALC_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_VCO_PD_PTAT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_SPI_VCO_PD_PTAT_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_VCO_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_SPI_VCO_PD_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_ALC_VARACTOR = 0x290 +# default: 0x03, access: R/W +@portable +def AD9154_SPI_VCO_VARACTOR_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_SPI_VCO_VARACTOR_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x08, access: R/W +@portable +def AD9154_SPI_INIT_ALC_VALUE_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_SPI_INIT_ALC_VALUE_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_VCO_OUTPUT = 0x291 +# default: 0x09, access: R/W +@portable +def AD9154_SPI_VCO_OUTPUT_LEVEL_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_SPI_VCO_OUTPUT_LEVEL_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x04, access: R/W +@portable +def AD9154_SPI_VCO_OUTPUT_RESERVED_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_SPI_VCO_OUTPUT_RESERVED_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_CP_CONFIG = 0x294 +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CP_TEST_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_SPI_CP_TEST_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CP_CAL_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_CP_CAL_EN_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CP_FORCE_CALBITS_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SPI_CP_FORCE_CALBITS_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_CP_OFFSET_OFF_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SPI_CP_OFFSET_OFF_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_CP_ENABLE_MACHINE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_SPI_CP_ENABLE_MACHINE_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CP_DITHER_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_SPI_CP_DITHER_MODE_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_CP_HALF_VCO_CAL_CLK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_SPI_CP_HALF_VCO_CAL_CLK_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_VCO_BIAS_1 = 0x296 +# default: 0x04, access: R/W +@portable +def AD9154_SPI_VCO_BIAS_REF_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_SPI_VCO_BIAS_REF_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_VCO_BIAS_TCF_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 3 + +@portable +def AD9154_SPI_VCO_BIAS_TCF_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x3 + + +AD9154_VCO_BIAS_2 = 0x297 +# default: 0x00, access: R/W +@portable +def AD9154_SPI_PRESCALE_BIAS_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_SPI_PRESCALE_BIAS_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_LAST_ALC_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_LAST_ALC_EN_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_PRESCALE_BYPASS_R_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SPI_PRESCALE_BYPASS_R_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_COMP_BYPASS_BIASR_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_SPI_VCO_COMP_BYPASS_BIASR_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_BYPASS_DAC_R_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_SPI_VCO_BYPASS_DAC_R_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + + +AD9154_VCO_PD_OVERRIDES = 0x299 +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VCO_BUF_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VCO_BUF_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_CAL_TCF_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_CAL_TCF_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_TCF_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_TCF_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + + +AD9154_VCO_CAL = 0x29a +# default: 0x02, access: R/W +@portable +def AD9154_SPI_FB_CLOCK_ADV_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_SPI_FB_CLOCK_ADV_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x03, access: R/W +@portable +def AD9154_SPI_VCO_CAL_COUNT_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 2 + +@portable +def AD9154_SPI_VCO_CAL_COUNT_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x3 + +# default: 0x07, access: R/W +@portable +def AD9154_SPI_VCO_CAL_ALC_WAIT_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 4 + +@portable +def AD9154_SPI_VCO_CAL_ALC_WAIT_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_SPI_VCO_CAL_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_SPI_VCO_CAL_EN_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_CP_LEVEL_DETECT = 0x29c +# default: 0x07, access: R/W +@portable +def AD9154_SPI_CP_LEVEL_THRESHOLD_HIGH_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_SPI_CP_LEVEL_THRESHOLD_HIGH_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x02, access: R/W +@portable +def AD9154_SPI_CP_LEVEL_THRESHOLD_LOW_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 3 + +@portable +def AD9154_SPI_CP_LEVEL_THRESHOLD_LOW_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x7 + +# default: 0x00, access: R/W +@portable +def AD9154_SPI_CP_LEVEL_DET_PD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_SPI_CP_LEVEL_DET_PD_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_VCO_VARACTOR_CTRL_0 = 0x29f +# default: 0x03, access: R/W +@portable +def AD9154_SPI_VCO_VARACTOR_OFFSET_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_SPI_VCO_VARACTOR_OFFSET_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x03, access: R/W +@portable +def AD9154_SPI_VCO_VARACTOR_REF_TCF_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 4 + +@portable +def AD9154_SPI_VCO_VARACTOR_REF_TCF_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x7 + + +AD9154_VCO_VARACTOR_CTRL_1 = 0x2a0 +# default: 0x08, access: R/W +@portable +def AD9154_SPI_VCO_VARACTOR_REF_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_SPI_VCO_VARACTOR_REF_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + + +AD9154_TERM_BLK1_CTRLREG0 = 0x2a7 + +AD9154_TERM_BLK2_CTRLREG0 = 0x2ae + +AD9154_GENERAL_JRX_CTRL_0 = 0x300 +# default: 0x00, access: R/W +@portable +def AD9154_LINK_EN_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +@portable +def AD9154_LINK_EN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_LINK_PAGE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +@portable +def AD9154_LINK_PAGE_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_LINK_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_LINK_MODE_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_CHECKSUM_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_CHECKSUM_MODE_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_GENERAL_JRX_CTRL_1 = 0x301 + +AD9154_DYN_LINK_LATENCY_0 = 0x302 + +AD9154_DYN_LINK_LATENCY_1 = 0x303 + +AD9154_LMFC_DELAY_0 = 0x304 + +AD9154_LMFC_DELAY_1 = 0x305 + +AD9154_LMFC_VAR_0 = 0x306 + +AD9154_LMFC_VAR_1 = 0x307 + +AD9154_XBAR_LN_0_1 = 0x308 +# default: 0x00, access: R/W +@portable +def AD9154_LOGICAL_LANE0_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_LOGICAL_LANE0_SRC_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x01, access: R/W +@portable +def AD9154_LOGICAL_LANE1_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 3 + +@portable +def AD9154_LOGICAL_LANE1_SRC_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x7 + + +AD9154_XBAR_LN_2_3 = 0x309 +# default: 0x02, access: R/W +@portable +def AD9154_LOGICAL_LANE2_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_LOGICAL_LANE2_SRC_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x03, access: R/W +@portable +def AD9154_LOGICAL_LANE3_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 3 + +@portable +def AD9154_LOGICAL_LANE3_SRC_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x7 + + +AD9154_XBAR_LN_4_5 = 0x30a +# default: 0x04, access: R/W +@portable +def AD9154_LOGICAL_LANE4_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_LOGICAL_LANE4_SRC_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x05, access: R/W +@portable +def AD9154_LOGICAL_LANE5_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 3 + +@portable +def AD9154_LOGICAL_LANE5_SRC_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x7 + + +AD9154_XBAR_LN_6_7 = 0x30b +# default: 0x06, access: R/W +@portable +def AD9154_LOGICAL_LANE6_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +@portable +def AD9154_LOGICAL_LANE6_SRC_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x7 + +# default: 0x07, access: R/W +@portable +def AD9154_LOGICAL_LANE7_SRC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 3 + +@portable +def AD9154_LOGICAL_LANE7_SRC_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x7 + + +AD9154_FIFO_STATUS_REG_0 = 0x30c + +AD9154_FIFO_STATUS_REG_1 = 0x30d + +AD9154_SYNCB_GEN_1 = 0x312 +# default: 0x00, access: R/W +@portable +def AD9154_SYNCB_ERR_DUR_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 4 + +@portable +def AD9154_SYNCB_ERR_DUR_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x7 + + +AD9154_SERDES_SPI_REG = 0x314 + +AD9154_PHY_PRBS_TEST_EN = 0x315 + +AD9154_PHY_PRBS_TEST_CTRL = 0x316 +# default: 0x00, access: R/W +@portable +def AD9154_PHY_TEST_RESET_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_PHY_TEST_RESET_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PHY_TEST_START_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_PHY_TEST_START_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_PHY_PRBS_PAT_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 2 + +@portable +def AD9154_PHY_PRBS_PAT_SEL_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_PHY_SRC_ERR_CNT_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 4 + +@portable +def AD9154_PHY_SRC_ERR_CNT_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x7 + + +AD9154_PHY_PRBS_TEST_THRESHOLD_LOBITS = 0x317 + +AD9154_PHY_PRBS_TEST_THRESHOLD_MIDBITS = 0x318 + +AD9154_PHY_PRBS_TEST_THRESHOLD_HIBITS = 0x319 + +AD9154_PHY_PRBS_TEST_ERRCNT_LOBITS = 0x31a + +AD9154_PHY_PRBS_TEST_ERRCNT_MIDBITS = 0x31b + +AD9154_PHY_PRBS_TEST_ERRCNT_HIBITS = 0x31c + +AD9154_PHY_PRBS_TEST_STATUS = 0x31d + +AD9154_SHORT_TPL_TEST_0 = 0x32c +# default: 0x00, access: R/W +@portable +def AD9154_SHORT_TPL_TEST_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +@portable +def AD9154_SHORT_TPL_TEST_EN_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SHORT_TPL_TEST_RESET_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_SHORT_TPL_TEST_RESET_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_SHORT_TPL_DAC_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 2 + +@portable +def AD9154_SHORT_TPL_DAC_SEL_GET(x: TInt32) -> TInt32: + return (x >> 2) & 0x3 + +# default: 0x00, access: R/W +@portable +def AD9154_SHORT_TPL_SP_SEL_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 4 + +@portable +def AD9154_SHORT_TPL_SP_SEL_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x3 + + +AD9154_SHORT_TPL_TEST_1 = 0x32d + +AD9154_SHORT_TPL_TEST_2 = 0x32e + +AD9154_SHORT_TPL_TEST_3 = 0x32f + +AD9154_DEVICE_CONFIG_REG_2 = 0x333 + +AD9154_JESD_BIT_INVERSE_CTRL = 0x334 + +AD9154_DID_REG = 0x400 + +AD9154_BID_REG = 0x401 +# default: 0x00, access: R +@portable +def AD9154_BID_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R +@portable +def AD9154_ADJCNT_RD_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_LID0_REG = 0x402 +# default: 0x00, access: R +@portable +def AD9154_LID0_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_PHADJ_RD_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R +@portable +def AD9154_ADJDIR_RD_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_SCR_L_REG = 0x403 +# default: 0x00, access: R +@portable +def AD9154_L_1_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_SCR_RD_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_F_REG = 0x404 + +AD9154_K_REG = 0x405 + +AD9154_M_REG = 0x406 + +AD9154_CS_N_REG = 0x407 +# default: 0x00, access: R +@portable +def AD9154_N_1_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_CS_RD_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_NP_REG = 0x408 +# default: 0x00, access: R +@portable +def AD9154_NP_1_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_SUBCLASSV_RD_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x7 + + +AD9154_S_REG = 0x409 +# default: 0x00, access: R +@portable +def AD9154_S_1_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_JESDV_RD_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x7 + + +AD9154_HD_CF_REG = 0x40a +# default: 0x00, access: R +@portable +def AD9154_CF_RD_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R +@portable +def AD9154_HD_RD_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_RES1_REG = 0x40b + +AD9154_RES2_REG = 0x40c + +AD9154_CHECKSUM0_REG = 0x40d + +AD9154_COMPSUM0_REG = 0x40e + +AD9154_LID1_REG = 0x412 + +AD9154_CHECKSUM1_REG = 0x415 + +AD9154_COMPSUM1_REG = 0x416 + +AD9154_LID2_REG = 0x41a + +AD9154_CHECKSUM2_REG = 0x41d + +AD9154_COMPSUM2_REG = 0x41e + +AD9154_LID3_REG = 0x422 + +AD9154_CHECKSUM3_REG = 0x425 + +AD9154_COMPSUM3_REG = 0x426 + +AD9154_LID4_REG = 0x42a + +AD9154_CHECKSUM4_REG = 0x42d + +AD9154_COMPSUM4_REG = 0x42e + +AD9154_LID5_REG = 0x432 + +AD9154_CHECKSUM5_REG = 0x435 + +AD9154_COMPSUM5_REG = 0x436 + +AD9154_LID6_REG = 0x43a + +AD9154_CHECKSUM6_REG = 0x43d + +AD9154_COMPSUM6_REG = 0x43e + +AD9154_LID7_REG = 0x442 + +AD9154_CHECKSUM7_REG = 0x445 + +AD9154_COMPSUM7_REG = 0x446 + +AD9154_ILS_DID = 0x450 + +AD9154_ILS_BID = 0x451 +# default: 0x00, access: R/W +@portable +def AD9154_BID_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 0 + +@portable +def AD9154_BID_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0xf + +# default: 0x00, access: R/W +@portable +def AD9154_ADJCNT_SET(x: TInt32) -> TInt32: + return (x & 0xf) << 4 + +@portable +def AD9154_ADJCNT_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0xf + + +AD9154_ILS_LID0 = 0x452 +# default: 0x00, access: R/W +@portable +def AD9154_LID0_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_LID0_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R/W +@portable +def AD9154_PHADJ_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_PHADJ_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ADJDIR_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_ADJDIR_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + + +AD9154_ILS_SCR_L = 0x453 +# default: 0x03, access: R/W +@portable +def AD9154_L_1_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_L_1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x01, access: R/W +@portable +def AD9154_SCR_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_SCR_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_ILS_F = 0x454 + +AD9154_ILS_K = 0x455 + +AD9154_ILS_M = 0x456 + +AD9154_ILS_CS_N = 0x457 +# default: 0x0f, access: R/W +@portable +def AD9154_N_1_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_N_1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x00, access: R/W +@portable +def AD9154_CS_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 6 + +@portable +def AD9154_CS_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x3 + + +AD9154_ILS_NP = 0x458 +# default: 0x0f, access: R/W +@portable +def AD9154_NP_1_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_NP_1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x01, access: R/W +@portable +def AD9154_SUBCLASSV_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 5 + +@portable +def AD9154_SUBCLASSV_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x7 + + +AD9154_ILS_S = 0x459 +# default: 0x00, access: R/W +@portable +def AD9154_S_1_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_S_1_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x01, access: R/W +@portable +def AD9154_JESDV_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 5 + +@portable +def AD9154_JESDV_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x7 + + +AD9154_ILS_HD_CF = 0x45a +# default: 0x00, access: R/W +@portable +def AD9154_CF_SET(x: TInt32) -> TInt32: + return (x & 0x1f) << 0 + +@portable +def AD9154_CF_GET(x: TInt32) -> TInt32: + return (x >> 0) & 0x1f + +# default: 0x01, access: R/W +@portable +def AD9154_HD_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_HD_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_ILS_RES1 = 0x45b + +AD9154_ILS_RES2 = 0x45c + +AD9154_ILS_CHECKSUM = 0x45d + +AD9154_ERRCNTRMON = 0x46b +# default: 0x00, access: W +@portable +def AD9154_CNTRSEL_SET(x: TInt32) -> TInt32: + return (x & 0x3) << 0 + +# default: 0x00, access: W +@portable +def AD9154_LANESEL_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 4 + + +AD9154_LANEDESKEW = 0x46c + +AD9154_BADDISPARITY = 0x46d +# default: 0x00, access: W +@portable +def AD9154_LANE_ADDR_DIS_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +# default: 0x00, access: W +@portable +def AD9154_RST_ERR_CNTR_DIS_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +# default: 0x00, access: W +@portable +def AD9154_DISABLE_ERR_CNTR_DIS_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +# default: 0x00, access: W +@portable +def AD9154_RST_IRQ_DIS_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + + +AD9154_NIT_W = 0x46e +# default: 0x00, access: W +@portable +def AD9154_LANE_ADDR_NIT_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +# default: 0x00, access: W +@portable +def AD9154_RST_ERR_CNTR_NIT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +# default: 0x00, access: W +@portable +def AD9154_DISABLE_ERR_CNTR_NIT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +# default: 0x00, access: W +@portable +def AD9154_RST_IRQ_NIT_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + + +AD9154_UNEXPECTEDCONTROL_W = 0x46f +# default: 0x00, access: W +@portable +def AD9154_LANE_ADDR_UCC_SET(x: TInt32) -> TInt32: + return (x & 0x7) << 0 + +# default: 0x00, access: W +@portable +def AD9154_RST_ERR_CNTR_UCC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +# default: 0x00, access: W +@portable +def AD9154_DISABLE_ERR_CNTR_UCC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +# default: 0x00, access: W +@portable +def AD9154_RST_IRQ_UCC_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + + +AD9154_CODEGRPSYNCFLG = 0x470 + +AD9154_FRAMESYNCFLG = 0x471 + +AD9154_GOODCHKSUMFLG = 0x472 + +AD9154_INITLANESYNCFLG = 0x473 + +AD9154_CTRLREG1 = 0x476 + +AD9154_CTRLREG2 = 0x477 +# default: 0x00, access: R/W +@portable +def AD9154_THRESHOLD_MASK_EN_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_THRESHOLD_MASK_EN_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_ILAS_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_ILAS_MODE_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_KVAL = 0x478 + +AD9154_IRQVECTOR_MASK = 0x47a +# default: 0x00, access: W +@portable +def AD9154_CODEGRPSYNC_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 0 + +# default: 0x00, access: W +@portable +def AD9154_BADCHECKSUM_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 2 + +# default: 0x00, access: W +@portable +def AD9154_INITIALLANESYNC_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +# default: 0x00, access: W +@portable +def AD9154_UCC_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +# default: 0x00, access: W +@portable +def AD9154_NIT_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +# default: 0x00, access: W +@portable +def AD9154_BADDIS_MASK_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + + +AD9154_SYNCASSERTIONMASK = 0x47b +# default: 0x01, access: R/W +@portable +def AD9154_CMM_ENABLE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 3 + +@portable +def AD9154_CMM_ENABLE_GET(x: TInt32) -> TInt32: + return (x >> 3) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_CMM_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 4 + +@portable +def AD9154_CMM_GET(x: TInt32) -> TInt32: + return (x >> 4) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_UCC_S_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 5 + +@portable +def AD9154_UCC_S_GET(x: TInt32) -> TInt32: + return (x >> 5) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_NIT_S_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 6 + +@portable +def AD9154_NIT_S_GET(x: TInt32) -> TInt32: + return (x >> 6) & 0x1 + +# default: 0x00, access: R/W +@portable +def AD9154_BADDIS_S_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 7 + +@portable +def AD9154_BADDIS_S_GET(x: TInt32) -> TInt32: + return (x >> 7) & 0x1 + + +AD9154_ERRORTHRES = 0x47c + +AD9154_LANEENABLE = 0x47d + +AD9154_RAMP_ENA = 0x47e + +AD9154_DIG_TEST0 = 0x520 +# default: 0x00, access: R/W +@portable +def AD9154_DC_TEST_MODE_SET(x: TInt32) -> TInt32: + return (x & 0x1) << 1 + +@portable +def AD9154_DC_TEST_MODE_GET(x: TInt32) -> TInt32: + return (x >> 1) & 0x1 + + +AD9154_DC_TEST_VALUEI0 = 0x521 + +AD9154_DC_TEST_VALUEI1 = 0x522 + +AD9154_DC_TEST_VALUEQ0 = 0x523 + +AD9154_DC_TEST_VALUEQ1 = 0x524 diff --git a/artiq/coredevice/ad9516_reg.py b/artiq/coredevice/ad9516_reg.py new file mode 100644 index 000000000..7b228baa1 --- /dev/null +++ b/artiq/coredevice/ad9516_reg.py @@ -0,0 +1,291 @@ +# = auto-generated, do not edit +from artiq.language.core import kernel + + +AD9516_SERIAL_PORT_CONFIGURATION = 0x000 +AD9516_SDO_ACTIVE = 1 << 0 # 1, 0x00 R/W +AD9516_LSB_FIRST = 1 << 1 # 1, 0x00 R/W +AD9516_SOFT_RESET = 1 << 2 # 1, 0x00 R/W +AD9516_LONG_INSTRUCTION = 1 << 3 # 1, 0x01 R/W +AD9516_LONG_INSTRUCTION_MIRRORED = 1 << 4 # 1, 0x01 R/W +AD9516_SOFT_RESET_MIRRORED = 1 << 5 # 1, 0x00 R/W +AD9516_LSB_FIRST_MIRRORED = 1 << 6 # 1, 0x00 R/W +AD9516_SDO_ACTIVE_MIRRORED = 1 << 7 # 1, 0x00 R/W + +AD9516_PART_ID = 0x003 + +AD9516_READBACK_CONTROL = 0x004 +AD9516_READ_BACK_ACTIVE_REGISTERS = 1 << 0 # 1, 0x00 R/W + +AD9516_PFD_AND_CHARGE_PUMP = 0x010 +AD9516_PLL_POWER_DOWN = 1 << 0 # 2, 0x01 R/W +AD9516_CHARGE_PUMP_MODE = 1 << 2 # 2, 0x03 R/W +AD9516_CHARGE_PUMP_CURRENT = 1 << 4 # 3, 0x07 R/W +AD9516_PFD_POLARITY = 1 << 7 # 1, 0x00 R/W + +AD9516_R_COUNTER_LSB = 0x011 +AD9516_R_COUNTER_MSB = 0x012 + +AD9516_A_COUNTER = 0x013 + +AD9516_B_COUNTER_LSB = 0x014 +AD9516_B_COUNTER_MSB = 0x015 + +AD9516_PLL_CONTROL_1 = 0x016 +AD9516_PRESCALER_P = 1 << 0 # 3, 0x06 R/W +AD9516_B_COUNTER_BYPASS = 1 << 3 # 1, 0x00 R/W +AD9516_RESET_ALL_COUNTERS = 1 << 4 # 1, 0x00 R/W +AD9516_RESET_A_AND_B_COUNTERS = 1 << 5 # 1, 0x00 R/W +AD9516_RESET_R_COUNTER = 1 << 6 # 1, 0x00 R/W +AD9516_SET_CP_PIN_TO_VCP_2 = 1 << 7 # 1, 0x00 R/W + +AD9516_PLL_CONTROL_2 = 0x017 +AD9516_ANTIBACKLASH_PULSE_WIDTH = 1 << 0 # 2, 0x00 R/W +AD9516_STATUS_PIN_CONTROL = 1 << 2 # 6, 0x00 R/W + +AD9516_PLL_CONTROL_3 = 0x018 +AD9516_VCO_CAL_NOW = 1 << 0 # 1, 0x00 R/W +AD9516_VCO_CALIBRATION_DIVIDER = 1 << 1 # 2, 0x03 R/W +AD9516_DISABLE_DIGITAL_LOCK_DETECT = 1 << 3 # 1, 0x00 R/W +AD9516_DIGITAL_LOCK_DETECT_WINDOW = 1 << 4 # 1, 0x00 R/W +AD9516_LOCK_DETECT_COUNTER = 1 << 5 # 2, 0x00 R/W + +AD9516_PLL_CONTROL_4 = 0x019 +AD9516_N_PATH_DELAY = 1 << 0 # 3, 0x00 R/W +AD9516_R_PATH_DELAY = 1 << 3 # 3, 0x00 R/W +AD9516_R_A_B_COUNTERS_SYNC_PIN_RESET = 1 << 6 # 2, 0x00 R/W + +AD9516_PLL_CONTROL_5 = 0x01a +AD9516_LD_PIN_CONTROL = 1 << 0 # 6, 0x00 R/W +AD9516_REFERENCE_FREQUENCY_MONITOR_THRESHOLD = 1 << 6 # 1, 0x00 R/W + +AD9516_PLL_CONTROL_6 = 0x01b +AD9516_REFMON_PIN_CONTROL = 1 << 0 # 5, 0x00 R/W +AD9516_REF1_REFIN_FREQUENCY_MONITOR = 1 << 5 # 1, 0x00 R/W +AD9516_REF2_REFIN_FREQUENCY_MONITOR = 1 << 6 # 1, 0x00 R/W +AD9516_VCO_FREQUENCY_MONITOR = 1 << 7 # 1, 0x00 R/W + +AD9516_PLL_CONTROL_7 = 0x01c +AD9516_DIFFERENTIAL_REFERENCE = 1 << 0 # 1, 0x00 R/W +AD9516_REF1_POWER_ON = 1 << 1 # 1, 0x00 R/W +AD9516_REF2_POWER_ON = 1 << 2 # 1, 0x00 R/W +AD9516_USE_REF_SEL_PIN = 1 << 5 # 1, 0x00 R/W +AD9516_SELECT_REF2 = 1 << 6 # 1, 0x00 R/W +AD9516_DISABLE_SWITCHOVER_DEGLITCH = 1 << 7 # 1, 0x00 R/W + +AD9516_PLL_CONTROL_8 = 0x01d +AD9516_HOLDOVER_ENABLE = 1 << 0 # 1, 0x00 R/W +AD9516_EXTERNAL_HOLDOVER_CONTROL = 1 << 1 # 1, 0x00 R/W +AD9516_HOLDOVER_ENABLEreg001D = 1 << 2 # 1, 0x00 R/W +AD9516_LD_PIN_COMPARATOR_ENABLE = 1 << 3 # 1, 0x00 R/W +AD9516_PLL_STATUS_REGISTER_DISABLE = 1 << 4 # 1, 0x00 R/W + +AD9516_PLL_READBACK = 0x01f +AD9516_DIGITAL_LOCK_DETECT = 1 << 0 # 1, 0x00 R +AD9516_REF1_FREQUENCY_THRESHOLD = 1 << 1 # 1, 0x00 R +AD9516_REF2_FREQUENCY_THRESHOLD = 1 << 2 # 1, 0x00 R +AD9516_VCO_FREQUENCY_THRESHOLD = 1 << 3 # 1, 0x00 R +AD9516_REF2_SELECTED = 1 << 4 # 1, 0x00 R +AD9516_HOLDOVER_ACTIVE = 1 << 5 # 1, 0x00 R +AD9516_VCO_CAL_FINISHED = 1 << 6 # 1, 0x00 R + +AD9516_OUT6_DELAY_BYPASS = 0x0a0 + +AD9516_OUT6_DELAY_FULL_SCALE = 0x0a1 +AD9516_OUT6_RAMP_CURRENT = 1 << 0 # 3, 0x00 R/W +AD9516_OUT6_RAMP_CAPACITORS = 1 << 3 # 3, 0x00 R/W + +AD9516_OUT6_DELAY_FRACTION = 0x0a2 + +AD9516_OUT7_DELAY_BYPASS = 0x0a3 + +AD9516_OUT7_DELAY_FULL_SCALE = 0x0a4 +AD9516_OUT7_RAMP_CURRENT = 1 << 0 # 3, 0x00 R/W +AD9516_OUT7_RAMP_CAPACITORS = 1 << 3 # 3, 0x00 R/W + +AD9516_OUT7_DELAY_FRACTION = 0x0a5 + +AD9516_OUT8_DELAY_BYPASS = 0x0a6 + +AD9516_OUT8_DELAY_FULL_SCALE = 0x0a7 +AD9516_OUT8_RAMP_CURRENT = 1 << 0 # 3, 0x00 R/W +AD9516_OUT8_RAMP_CAPACITORS = 1 << 3 # 3, 0x00 R/W + +AD9516_OUT8_DELAY_FRACTION = 0x0a8 + +AD9516_OUT9_DELAY_BYPASS = 0x0a9 + +AD9516_OUT9_DELAY_FULL_SCALE = 0x0aa +AD9516_OUT9_RAMP_CURRENT = 1 << 0 # 3, 0x00 R/W +AD9516_OUT9_RAMP_CAPACITORS = 1 << 3 # 3, 0x00 R/W + +AD9516_OUT9_DELAY_FRACTION = 0x0ab + +AD9516_OUT0 = 0x0f0 +AD9516_OUT0_POWER_DOWN = 1 << 0 # 2, 0x00 R/W +AD9516_OUT0_LVPECL_DIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT0_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT1 = 0x0f1 +AD9516_OUT1_POWER_DOWN = 1 << 0 # 2, 0x02 R/W +AD9516_OUT1_LVPECLDIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT1_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT2 = 0x0f2 +AD9516_OUT2_POWER_DOWN = 1 << 0 # 2, 0x00 R/W +AD9516_OUT2_LVPECL_DIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT2_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT3 = 0x0f3 +AD9516_OUT3_POWER_DOWN = 1 << 0 # 2, 0x02 R/W +AD9516_OUT3_LVPECL_DIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT3_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT4 = 0x0f4 +AD9516_OUT4_POWER_DOWN = 1 << 0 # 2, 0x02 R/W +AD9516_OUT4_LVPECL_DIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT4_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT5 = 0x0f5 +AD9516_OUT5_POWER_DOWN = 1 << 0 # 2, 0x02 R/W +AD9516_OUT5_LVPECL_DIFFERENTIAL_VOLTAGE = 1 << 2 # 2, 0x02 R/W +AD9516_OUT5_INVERT = 1 << 4 # 1, 0x00 R/W + +AD9516_OUT6 = 0x140 +AD9516_OUT6_POWER_DOWN = 1 << 0 # 1, 0x00 R/W +AD9516_OUT6_LVDS_OUTPUT_CURRENT = 1 << 1 # 2, 0x01 R/W +AD9516_OUT6_SELECT_LVDS_CMOS = 1 << 3 # 1, 0x00 R/W +AD9516_OUT6_CMOS_B = 1 << 4 # 1, 0x00 R/W +AD9516_OUT6_LVDS_CMOS_OUTPUT_POLARITY = 1 << 5 # 1, 0x00 R/W +AD9516_OUT6_CMOS_OUTPUT_POLARITY = 1 << 6 # 2, 0x01 R/W + +AD9516_OUT7 = 0x141 +AD9516_OUT7_POWER_DOWN = 1 << 0 # 1, 0x01 R/W +AD9516_OUT7_LVDS_OUTPUT_CURRENT = 1 << 1 # 2, 0x01 R/W +AD9516_OUT7_SELECT_LVDS_CMOS = 1 << 3 # 1, 0x00 R/W +AD9516_OUT7_CMOS_B = 1 << 4 # 1, 0x00 R/W +AD9516_OUT7_LVDS_CMOS_OUTPUT_POLARITY = 1 << 5 # 1, 0x00 R/W +AD9516_OUT7_CMOS_OUTPUT_POLARITY = 1 << 6 # 2, 0x01 R/W + +AD9516_OUT8 = 0x142 +AD9516_OUT8_POWER_DOWN = 1 << 0 # 1, 0x00 R/W +AD9516_OUT8_LVDS_OUTPUT_CURRENT = 1 << 1 # 2, 0x01 R/W +AD9516_OUT8_SELECT_LVDS_CMOS = 1 << 3 # 1, 0x00 R/W +AD9516_OUT8_CMOS_B = 1 << 4 # 1, 0x00 R/W +AD9516_OUT8_LVDS_CMOS_OUTPUT_POLARITY = 1 << 5 # 1, 0x00 R/W +AD9516_OUT8_CMOS_OUTPUT_POLARITY = 1 << 6 # 2, 0x01 R/W + +AD9516_OUT9 = 0x143 +AD9516_OUT9_POWER_DOWN = 1 << 0 # 1, 0x01 R/W +AD9516_OUT9_LVDS_OUTPUT_CURRENT = 1 << 1 # 2, 0x01 R/W +AD9516_OUT9_SELECT_LVDS_CMOS = 1 << 3 # 1, 0x00 R/W +AD9516_OUT9_CMOS_B = 1 << 4 # 1, 0x00 R/W +AD9516_OUT9_LVDS_CMOS_OUTPUT_POLARITY = 1 << 5 # 1, 0x00 R/W +AD9516_OUT9_CMOS_OUTPUT_POLARITY = 1 << 6 # 2, 0x01 R/W + +AD9516_DIVIDER_0_0 = 0x190 +AD9516_DIVIDER_0_HIGH_CYCLES = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_0_LOW_CYCLES = 1 << 4 # 4, 0x00 R/W + +AD9516_DIVIDER_0_1 = 0x191 +AD9516_DIVIDER_0_PHASE_OFFSET = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_0_START_HIGH = 1 << 4 # 1, 0x00 R/W +AD9516_DIVIDER_0_FORCE_HIGH = 1 << 5 # 1, 0x00 R/W +AD9516_DIVIDER_0_NOSYNC = 1 << 6 # 1, 0x00 R/W +AD9516_DIVIDER_0_BYPASS = 1 << 7 # 1, 0x01 R/W + +AD9516_DIVIDER_0_2 = 0x192 +AD9516_DIVIDER_0_DCCOFF = 1 << 0 # 1, 0x00 R/W +AD9516_DIVIDER_0_DIRECT_TO_OUTPUT = 1 << 1 # 1, 0x00 R/W + +AD9516_DIVIDER_1_0 = 0x193 +AD9516_DIVIDER_1_HIGH_CYCLES = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_1_LOW_CYCLES = 1 << 4 # 4, 0x00 R/W + +AD9516_DIVIDER_1_1 = 0x194 +AD9516_DIVIDER_1_PHASE_OFFSET = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_1_START_HIGH = 1 << 4 # 1, 0x00 R/W +AD9516_DIVIDER_1_FORCE_HIGH = 1 << 5 # 1, 0x00 R/W +AD9516_DIVIDER_1_NOSYNC = 1 << 6 # 1, 0x00 R/W +AD9516_DIVIDER_1_BYPASS = 1 << 7 # 1, 0x00 R/W + +AD9516_DIVIDER_1_2 = 0x195 +AD9516_DIVIDER_1_DCCOFF = 1 << 0 # 1, 0x00 R/W +AD9516_DIVIDER_1_DIRECT_TO_OUTPUT = 1 << 1 # 1, 0x00 R/W + +AD9516_DIVIDER_2_0 = 0x196 +AD9516_DIVIDER_2_HIGH_CYCLES = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_2_LOW_CYCLES = 1 << 4 # 4, 0x00 R/W + +AD9516_DIVIDER_2_1 = 0x197 +AD9516_DIVIDER_2_PHASE_OFFSET = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_2_START_HIGH = 1 << 4 # 1, 0x00 R/W +AD9516_DIVIDER_2_FORCE_HIGH = 1 << 5 # 1, 0x00 R/W +AD9516_DIVIDER_2_NOSYNC = 1 << 6 # 1, 0x00 R/W +AD9516_DIVIDER_2_BYPASS = 1 << 7 # 1, 0x00 R/W + +AD9516_DIVIDER_2_2 = 0x198 +AD9516_DIVIDER_2_DCCOFF = 1 << 0 # 1, 0x00 R/W +AD9516_DIVIDER_2_DIRECT_TO_OUTPUT = 1 << 1 # 1, 0x00 R/W + +AD9516_DIVIDER_3_0 = 0x199 +AD9516_DIVIDER_3_HIGH_CYCLES_1 = 1 << 0 # 4, 0x02 R/W +AD9516_DIVIDER_3_LOW_CYCLES_1 = 1 << 4 # 4, 0x02 R/W + +AD9516_DIVIDER_3_1 = 0x19a +AD9516_DIVIDER_3_PHASE_OFFSET_1 = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_3_PHASE_OFFSET_2 = 1 << 4 # 4, 0x00 R/W + +AD9516_DIVIDER_3_2 = 0x19b +AD9516_DIVIDER_3_HIGH_CYCLES_2 = 1 << 0 # 4, 0x01 R/W +AD9516_DIVIDER_3_LOW_CYCLES_2 = 1 << 4 # 4, 0x01 R/W + +AD9516_DIVIDER_3_3 = 0x19c +AD9516_DIVIDER_3_START_HIGH_1 = 1 << 0 # 1, 0x00 R/W +AD9516_DIVIDER_3_START_HIGH_2 = 1 << 1 # 1, 0x00 R/W +AD9516_DIVIDER_3_FORCE_HIGH = 1 << 2 # 1, 0x00 R/W +AD9516_DIVIDER_3_NOSYNC = 1 << 3 # 1, 0x00 R/W +AD9516_DIVIDER_3_BYPASS_1 = 1 << 4 # 1, 0x00 R/W +AD9516_DIVIDER_3_BYPASS_2 = 1 << 5 # 1, 0x00 R/W + +AD9516_DIVIDER_3_4 = 0x19d +AD9516_DIVIDER_3_DCCOFF = 1 << 0 # 1, 0x00 R/W + +AD9516_DIVIDER_4_0 = 0x19e +AD9516_DIVIDER_4_HIGH_CYCLES_1 = 1 << 0 # 4, 0x02 R/W +AD9516_DIVIDER_4_LOW_CYCLES_1 = 1 << 4 # 4, 0x02 R/W + +AD9516_DIVIDER_4_1 = 0x19f +AD9516_DIVIDER_4_PHASE_OFFSET_1 = 1 << 0 # 4, 0x00 R/W +AD9516_DIVIDER_4_PHASE_OFFSET_2 = 1 << 4 # 4, 0x00 R/W + +AD9516_DIVIDER_4_2 = 0x1a0 +AD9516_DIVIDER_4_HIGH_CYCLES_2 = 1 << 0 # 4, 0x01 R/W +AD9516_DIVIDER_4_LOW_CYCLES_2 = 1 << 4 # 4, 0x01 R/W + +AD9516_DIVIDER_4_3 = 0x1a1 +AD9516_DIVIDER_4_START_HIGH_1 = 1 << 0 # 1, 0x00 R/W +AD9516_DIVIDER_4_START_HIGH_2 = 1 << 1 # 1, 0x00 R/W +AD9516_DIVIDER_4_FORCE_HIGH = 1 << 2 # 1, 0x00 R/W +AD9516_DIVIDER_4_NOSYNC = 1 << 3 # 1, 0x00 R/W +AD9516_DIVIDER_4_BYPASS_1 = 1 << 4 # 1, 0x00 R/W +AD9516_DIVIDER_4_BYPASS_2 = 1 << 5 # 1, 0x00 R/W + +AD9516_DIVIDER_4_4 = 0x1a2 +AD9516_DIVIDER_4_DCCOFF = 1 << 0 # 1, 0x00 R/W + +AD9516_VCO_DIVIDER = 0x1e0 + +AD9516_INPUT_CLKS = 0x1e1 +AD9516_BYPASS_VCO_DIVIDER = 1 << 0 # 1, 0x00 R/W +AD9516_SELECT_VCO_OR_CLK = 1 << 1 # 1, 0x00 R/W +AD9516_POWER_DOWN_VCO_AND_CLK = 1 << 2 # 1, 0x00 R/W +AD9516_POWER_DOWN_VCO_CLOCK_INTERFACE = 1 << 3 # 1, 0x00 R/W +AD9516_POWER_DOWN_CLOCK_INPUT_SECTION = 1 << 4 # 1, 0x00 R/W + +AD9516_POWER_DOWN_AND_SYNC = 0x230 +AD9516_SOFT_SYNC = 1 << 0 # 1, 0x00 R/W +AD9516_POWER_DOWN_DISTRIBUTION_REFERENCE = 1 << 1 # 1, 0x00 R/W +AD9516_POWER_DOWN_SYNC = 1 << 2 # 1, 0x00 R/W + +AD9516_UPDATE_ALL_REGISTERS = 0x232 diff --git a/artiq/coredevice/rtio.py b/artiq/coredevice/rtio.py index 3dec674df..471a48c31 100644 --- a/artiq/coredevice/rtio.py +++ b/artiq/coredevice/rtio.py @@ -3,12 +3,13 @@ from artiq.language.types import TInt64, TInt32, TNone, TList @syscall(flags={"nowrite"}) -def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32) -> TNone: +def rtio_output(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TInt32 + ) -> TNone: raise NotImplementedError("syscall not simulated") @syscall(flags={"nowrite"}) -def rtio_output_list(time_mu: TInt64, channel: TInt32, addr: TInt32, +def rtio_output_wide(time_mu: TInt64, channel: TInt32, addr: TInt32, data: TList(TInt32)) -> TNone: raise NotImplementedError("syscall not simulated") diff --git a/artiq/coredevice/sawg.py b/artiq/coredevice/sawg.py new file mode 100644 index 000000000..1010e48db --- /dev/null +++ b/artiq/coredevice/sawg.py @@ -0,0 +1,59 @@ +from artiq.coredevice.spline import Spline + + +class SAWG: + """Smart arbitrary waveform generator channel. + The channel is parametrized as: :: + + oscillators = exp(2j*pi*(frequency0*t + phase0))*( + amplitude1*exp(2j*pi*(frequency1*t + phase1)) + + amplitude2*exp(2j*pi*(frequency2*t + phase2))) + + output = (offset + + i_enable*Re(oscillators) + + q_enable*Im(buddy_oscillators)) + + The nine spline interpolators are accessible as attributes: + + * :attr:`offset`, :attr:`amplitude1`, :attr:`amplitude2`: in units + of full scale + * :attr:`phase0`, :attr:`phase1`, :attr:`phase2`: in units of turns + * :attr:`frequency0`, :attr:`frequency1`, :attr:`frequency2`: in units + of Hz + + :param channel_base: RTIO channel number of the first channel (amplitude). + Frequency and Phase are then assumed to be successive channels. + :param parallelism: Number of output samples per coarse RTIO clock cycle. + :param core_device: Name of the core device that this SAWG is on. + """ + kernel_invariants = {"channel_base", "core", + "amplitude1", "frequency1", "phase1", + "amplitude2", "frequency2", "phase2", + "frequency0", "phase0", "offset"} + + def __init__(self, dmgr, channel_base, parallelism, core_device="core"): + self.core = dmgr.get(core_device) + self.channel_base = channel_base + width = 16 + time_width = 16 + cordic_gain = 1.646760258057163 # Cordic(width=16, guard=None).gain + # cfg: channel_base + self.offset = Spline(width, time_width, channel_base + 1, + self.core, 2.) + self.amplitude1 = Spline(width, time_width, channel_base + 2, + self.core, 2*cordic_gain**2) + self.frequency1 = Spline(3*width, time_width, channel_base + 3, + self.core, 1/self.core.coarse_ref_period) + self.phase1 = Spline(width, time_width, channel_base + 4, + self.core, 1.) + self.amplitude2 = Spline(width, time_width, channel_base + 5, + self.core, 2*cordic_gain**2) + self.frequency2 = Spline(3*width, time_width, channel_base + 6, + self.core, 1/self.core.coarse_ref_period) + self.phase2 = Spline(width, time_width, channel_base + 7, + self.core, 1.) + self.frequency0 = Spline(2*width, time_width, channel_base + 8, + self.core, + parallelism/self.core.coarse_ref_period) + self.phase0 = Spline(width, time_width, channel_base + 9, + self.core, 1.) diff --git a/artiq/coredevice/spline.py b/artiq/coredevice/spline.py new file mode 100644 index 000000000..2f75879d6 --- /dev/null +++ b/artiq/coredevice/spline.py @@ -0,0 +1,222 @@ +from numpy import int32, int64 +from artiq.language.core import kernel, now_mu, portable, delay +from artiq.coredevice.rtio import rtio_output, rtio_output_wide +from artiq.language.types import TInt32, TInt64, TFloat + + +class Spline: + r"""Spline interpolating RTIO channel. + + One knot of a polynomial basis spline (B-spline) :math:`u(t)` + is defined by the coefficients :math:`u_n` up to order :math:`n = k`. + If the knot is evaluated starting at time :math:`t_0`, the output + :math:`u(t)` for :math:`t > t_0, t_0` is: + + .. math:: + u(t) &= \sum_{n=0}^k \frac{u_n}{n!} (t - t_0)^n \\ + &= u_0 + u_1 (t - t_0) + \frac{u_2}{2} (t - t_0)^2 + \dots + + :param width: Width in bits of the quantity that this spline controls + :param time_width: Width in bits of the time counter of this spline + :param channel: RTIO channel number + :param core_device: Core device that this spline is attached to + :param scale: Scale for conversion between machine units and physical + units; to be given as the "full scale physical value". + """ + + kernel_invariants = {"channel", "core", "scale", "width", + "time_width", "time_scale"} + + def __init__(self, width, time_width, channel, core_device, scale=1.): + self.core = core_device + self.channel = channel + self.width = width + self.scale = float((int64(1) << width) / scale) + self.time_width = time_width + self.time_scale = float((1 << time_width) * + core_device.coarse_ref_period) + + @portable(flags={"fast-math"}) + def to_mu(self, value: TFloat) -> TInt32: + """Convert floating point `value` from physical units to 32 bit + integer machine units.""" + return int32(round(value*self.scale)) + + @portable(flags={"fast-math"}) + def from_mu(self, value: TInt32) -> TFloat: + """Convert 32 bit integer `value` from machine units to floating point + physical units.""" + return value/self.scale + + @portable(flags={"fast-math"}) + def to_mu64(self, value: TFloat) -> TInt64: + """Convert floating point `value` from physical units to 64 bit + integer machine units.""" + return int64(round(value*self.scale)) + + @kernel + def set_mu(self, value: TInt32): + """Set spline value (machine units). + + :param value: Spline value in integer machine units. + """ + rtio_output(now_mu(), self.channel, 0, value) + + @kernel(flags={"fast-math"}) + def set(self, value: TFloat): + """Set spline value. + + :param value: Spline value relative to full-scale. + """ + if self.width > 32: + l = [int32(0)] * 2 + self.pack_coeff_mu([self.to_mu64(value)], l) + rtio_output_wide(now_mu(), self.channel, 0, l) + else: + rtio_output(now_mu(), self.channel, 0, self.to_mu(value)) + + @kernel + def set_coeff_mu(self, value): # TList(TInt32) + """Set spline raw values. + + :param value: Spline packed raw values. + """ + rtio_output_wide(now_mu(), self.channel, 0, value) + + @portable(flags={"fast-math"}) + def pack_coeff_mu(self, coeff, packed): # TList(TInt64), TList(TInt32) + """Pack coefficients into RTIO data + + :param coeff: TList(TInt64) list of machine units spline coefficients. + Lowest (zeroth) order first. The coefficient list is zero-extended + by the RTIO gateware. + :param packed: TList(TInt32) list for packed RTIO data. Must be + pre-allocated. Length in bits is + `n*width + (n - 1)*n//2*time_width` + """ + pos = 0 + for i in range(len(coeff)): + wi = self.width + i*self.time_width + ci = coeff[i] + while wi != 0: + j = pos//32 + used = pos - 32*j + avail = 32 - used + if avail > wi: + avail = wi + cij = int32(ci) + if avail != 32: + cij &= (1 << avail) - 1 + packed[j] |= cij << used + ci >>= avail + wi -= avail + pos += avail + + @portable(flags={"fast-math"}) + def coeff_to_mu(self, coeff, coeff64): # TList(TFloat), TList(TInt64) + """Convert a floating point list of coefficients into a 64 bit + integer (preallocated). + + :param coeff: TList(TFloat) list of coefficients in physical units. + :param coeff64: TList(TInt64) preallocated list of coefficients in + machine units. + """ + for i in range(len(coeff)): + vi = coeff[i] * self.scale + for j in range(i): + vi *= self.time_scale + ci = int64(round(vi)) + coeff64[i] = ci + # artiq.wavesynth.coefficients.discrete_compensate: + if i == 2: + coeff64[1] += ci >> self.time_width + 1 + elif i == 3: + coeff64[2] += ci >> self.time_width + coeff64[1] += ci // 6 >> 2*self.time_width + + def coeff_as_packed_mu(self, coeff64): + """Pack 64 bit integer machine units coefficients into 32 bit integer + RTIO data list. + + This is a host-only method that can be used to generate packed + spline knot data to be frozen into kernels at compile time. + """ + n = len(coeff64) + width = n*self.width + (n - 1)*n//2*self.time_width + packed = [int32(0)] * ((width + 31)//32) + self.pack_coeff_mu(coeff64, packed) + return packed + + def coeff_as_packed(self, coeff): + """Convert floating point spline coefficients into 32 bit integer + packed data. + + This is a host-only method that can be used to generate packed + spline knot data to be frozen into kernels at compile time. + """ + coeff64 = [int64(0)] * len(coeff) + self.coeff_to_mu(coeff, coeff64) + return self.coeff_as_packed_mu(coeff64) + + @kernel(flags={"fast-math"}) + def set_coeff(self, coeff): # TList(TFloat) + """Set spline coefficients. + + Missing coefficients (high order) are zero-extended byt the RTIO + gateware. + + If more coefficients are supplied than the gateware supports the extra + coefficients are ignored. + + :param value: List of floating point spline knot coefficients, + lowest order (constant) coefficient first. Units are the + unit of this spline's value times increasing powers of 1/s. + """ + n = len(coeff) + coeff64 = [int64(0)] * n + self.coeff_to_mu(coeff, coeff64) + width = n*self.width + (n - 1)*n//2*self.time_width + packed = [int32(0)] * ((width + 31)//32) + self.pack_coeff_mu(coeff64, packed) + self.set_coeff_mu(packed) + + @kernel(flags={"fast-math"}) + def smooth(self, start: TFloat, stop: TFloat, duration: TFloat, + order: TInt32): + """Initiate an interpolated value change. + + For zeroth order (step) interpolation, the step is at + `start + duration/2`. + + First order interpolation corresponds to a linear value ramp from + `start` to `stop` over `duration`. + + The third order interpolation is constrained to have zero first + order derivative at both `start` and `stop`. + + For first order and third order interpolation (linear and cubic) + the interpolator needs to be stopped (or fed a new spline knot) + explicitly at the stop time. + + This method advances the timeline by `duration`. + + :param start: Initial value of the change. In physical units. + :param stop: Final value of the change. In physical units. + :param duration: Duration of the interpolation. In physical units. + :param order: Order of the interpolation. Only 0, 1, + and 3 are valid: step, linear, cubic. + """ + if order == 0: + delay(duration/2.) + self.set_coeff([stop]) + delay(duration/2.) + elif order == 1: + self.set_coeff([start, (stop - start)/duration]) + delay(duration) + elif order == 3: + v2 = 6.*(stop - start)/(duration*duration) + self.set_coeff([start, 0., v2, -2.*v2/duration]) + delay(duration) + else: + raise ValueError("Invalid interpolation order. " + "Supported orders are: 0, 1, 3.") diff --git a/artiq/examples/phaser/device_db.pyon b/artiq/examples/phaser/device_db.pyon new file mode 100644 index 000000000..1bd1beb74 --- /dev/null +++ b/artiq/examples/phaser/device_db.pyon @@ -0,0 +1,77 @@ +# The RTIO channel numbers here are for Phaser on KC705. + +{ + "comm": { + "type": "local", + "module": "artiq.coredevice.comm_tcp", + "class": "Comm", + "arguments": {"host": "kc705aux.lab.m-labs.hk"} + }, + "core": { + "type": "local", + "module": "artiq.coredevice.core", + "class": "Core", + "arguments": { + "ref_period": 5e-9/6, + "external_clock": True + } + }, + "core_cache": { + "type": "local", + "module": "artiq.coredevice.cache", + "class": "CoreCache" + }, + "ad9154": { + "type": "local", + "module": "artiq.coredevice.ad9154", + "class": "AD9154" + }, + "ttl_sma": { + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", + "arguments": {"channel": 0} + }, + "led": { + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLOut", + "arguments": {"channel": 1} + }, + "sysref": { + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", + "arguments": {"channel": 2} + }, + "sync": { + "type": "local", + "module": "artiq.coredevice.ttl", + "class": "TTLInOut", + "arguments": {"channel": 3} + }, + "sawg0": { + "type": "local", + "module": "artiq.coredevice.sawg", + "class": "SAWG", + "arguments": {"channel_base": 4, "parallelism": 2} + }, + "sawg1": { + "type": "local", + "module": "artiq.coredevice.sawg", + "class": "SAWG", + "arguments": {"channel_base": 14, "parallelism": 2} + }, + "sawg2": { + "type": "local", + "module": "artiq.coredevice.sawg", + "class": "SAWG", + "arguments": {"channel_base": 24, "parallelism": 2} + }, + "sawg3": { + "type": "local", + "module": "artiq.coredevice.sawg", + "class": "SAWG", + "arguments": {"channel_base": 34, "parallelism": 2} + } +} diff --git a/artiq/examples/phaser/repository/dac_setup.py b/artiq/examples/phaser/repository/dac_setup.py new file mode 100644 index 000000000..2364ff183 --- /dev/null +++ b/artiq/examples/phaser/repository/dac_setup.py @@ -0,0 +1,362 @@ +from jesd204b.common import (JESD204BPhysicalSettings, + JESD204BTransportSettings, + JESD204BSettings) +from artiq.experiment import * +from artiq.coredevice.ad9154_reg import * + +# ad9154 mode 2: +ps = JESD204BPhysicalSettings( + l=4, # lanes + m=4, # converters + n=16, # bits/converter + np=16, # bits/sample +) +ts = JESD204BTransportSettings( + f=2, # octets/(lane and frame) + s=1, # samples/(converter and frame) + k=16, # frames/multiframe + cs=1, # +) +jesd_settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5) +jesd_checksum = jesd_settings.get_configuration_checksum() +# external clk=300MHz +# pclock=150MHz +# deviceclock_fpga=150MHz +# deviceclock_dac=300MHz + + +class DACSetup(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("led") + self.setattr_device("ad9154") + self.setattr_device("sync") + + @kernel + def run(self): + # TODO; remove when + # https://github.com/m-labs/jesd204b/issues/6 + # is resolved + for i in range(99): + try: + self.cfg() + return + except: + pass + self.cfg() + + @kernel + def cfg(self): + self.core.reset() + self.ad9154.jesd_enable(0) + self.ad9154.jesd_prbs(0) + self.ad9154.jesd_stpl(0) + self.busywait_us(10000) + self.ad9154.jesd_enable(1) + self.ad9154.init() + self.dac_setup() + self.ad9154.jesd_enable(0) + self.busywait_us(10000) + self.ad9154.jesd_enable(1) + self.monitor() + while not self.ad9154.jesd_ready(): + pass + self.busywait_us(10000) + if self.ad9154.dac_read(AD9154_CODEGRPSYNCFLG) != 0x0f: + raise ValueError("bad CODEGRPSYNCFLG") + self.core.break_realtime() + if not self.sync.sample_get_nonrt(): + raise ValueError("bad SYNC") + if self.ad9154.dac_read(AD9154_FRAMESYNCFLG) != 0x0f: + raise ValueError("bad FRAMESYNCFLG") + if self.ad9154.dac_read(AD9154_GOODCHKSUMFLG) != 0x0f: + raise ValueError("bad GOODCHECKSUMFLG") + if self.ad9154.dac_read(AD9154_INITLANESYNCFLG) != 0x0f: + raise ValueError("bad INITLANESYNCFLG") + + @kernel + def busywait_us(self, t): + t = self.core.get_rtio_counter_mu() + self.core.seconds_to_mu(t*us) + while self.core.get_rtio_counter_mu() < t: + pass + + @kernel + def dac_setup(self): + # reset + self.ad9154.dac_write(AD9154_SPI_INTFCONFA, + AD9154_SOFTRESET_M_SET(1) | AD9154_SOFTRESET_SET(1) | + AD9154_LSBFIRST_M_SET(0) | AD9154_LSBFIRST_SET(0) | + AD9154_ADDRINC_M_SET(0) | AD9154_ADDRINC_SET(0) | + AD9154_SDOACTIVE_M_SET(1) | AD9154_SDOACTIVE_SET(1)) + self.busywait_us(100) + self.ad9154.dac_write(AD9154_SPI_INTFCONFA, + AD9154_SOFTRESET_M_SET(0) | AD9154_SOFTRESET_SET(0) | + AD9154_LSBFIRST_M_SET(0) | AD9154_LSBFIRST_SET(0) | + AD9154_ADDRINC_M_SET(0) | AD9154_ADDRINC_SET(0) | + AD9154_SDOACTIVE_M_SET(1) | AD9154_SDOACTIVE_SET(1)) + self.busywait_us(100) + if ((self.ad9154.dac_read(AD9154_PRODIDH) << 8) | + self.ad9154.dac_read(AD9154_PRODIDL) != 0x9154): + raise ValueError("AD9154 not found") + + self.ad9154.dac_write(AD9154_PWRCNTRL0, + AD9154_PD_DAC0_SET(0) | AD9154_PD_DAC1_SET(0) | + AD9154_PD_DAC2_SET(0) | AD9154_PD_DAC3_SET(0) | + AD9154_PD_BG_SET(0)) + self.busywait_us(100) + self.ad9154.dac_write(AD9154_TXENMASK1, AD9154_DACA_MASK_SET(0) | + AD9154_DACB_MASK_SET(0)) # TX not controlled by TXEN pins + self.ad9154.dac_write(AD9154_CLKCFG0, + AD9154_REF_CLKDIV_EN_SET(0) | AD9154_RF_SYNC_EN_SET(1) | + AD9154_DUTY_EN_SET(1) | AD9154_PD_CLK_REC_SET(0) | + AD9154_PD_SERDES_PCLK_SET(0) | AD9154_PD_CLK_DIG_SET(0) | + AD9154_PD_CLK23_SET(0) | AD9154_PD_CLK01_SET(0)) + self.ad9154.dac_write(AD9154_DACPLLCNTRL, + AD9154_ENABLE_DACPLL_SET(0) | AD9154_RECAL_DACPLL_SET(0)) + self.ad9154.dac_write(AD9154_SYSREF_ACTRL0, # jesd204b subclass 1 + AD9154_HYS_CNTRL1_SET(0) | AD9154_SYSREF_RISE_SET(0) | + AD9154_HYS_ON_SET(0) | AD9154_PD_SYSREF_BUFFER_SET(0)) + + self.ad9154.dac_write(AD9154_DEVICE_CONFIG_REG_0, 0x8b) # magic + self.ad9154.dac_write(AD9154_DEVICE_CONFIG_REG_1, 0x01) # magic + self.ad9154.dac_write(AD9154_DEVICE_CONFIG_REG_2, 0x01) # magic + + self.ad9154.dac_write(AD9154_SPI_PAGEINDX, 0x3) # A and B dual + + self.ad9154.dac_write(AD9154_INTERP_MODE, 0) # 1x + self.ad9154.dac_write(AD9154_MIX_MODE, 0) + self.ad9154.dac_write(AD9154_DATA_FORMAT, AD9154_BINARY_FORMAT_SET(0)) # s16 + self.ad9154.dac_write(AD9154_DATAPATH_CTRL, + AD9154_I_TO_Q_SET(0) | AD9154_SEL_SIDEBAND_SET(0) | + AD9154_MODULATION_TYPE_SET(0) | AD9154_PHASE_ADJ_ENABLE_SET(0) | + AD9154_DIG_GAIN_ENABLE_SET(1) | AD9154_INVSINC_ENABLE_SET(0)) + self.ad9154.dac_write(AD9154_IDAC_DIG_GAIN0, 0x00) + self.ad9154.dac_write(AD9154_IDAC_DIG_GAIN1, 0x8) + self.ad9154.dac_write(AD9154_QDAC_DIG_GAIN0, 0x00) + self.ad9154.dac_write(AD9154_QDAC_DIG_GAIN1, 0x8) + self.ad9154.dac_write(AD9154_DC_OFFSET_CTRL, 0) + self.ad9154.dac_write(AD9154_IPATH_DC_OFFSET_1PART0, 0x00) + self.ad9154.dac_write(AD9154_IPATH_DC_OFFSET_1PART1, 0x00) + self.ad9154.dac_write(AD9154_IPATH_DC_OFFSET_2PART, 0x00) + self.ad9154.dac_write(AD9154_QPATH_DC_OFFSET_1PART0, 0x00) + self.ad9154.dac_write(AD9154_QPATH_DC_OFFSET_1PART1, 0x00) + self.ad9154.dac_write(AD9154_QPATH_DC_OFFSET_2PART, 0x00) + self.ad9154.dac_write(AD9154_PHASE_ADJ0, 0) + self.ad9154.dac_write(AD9154_PHASE_ADJ1, 0) + self.ad9154.dac_write(AD9154_GROUP_DLY, AD9154_COARSE_GROUP_DELAY_SET(0x8) | + AD9154_GROUP_DELAY_RESERVED_SET(0x8)) + self.ad9154.dac_write(AD9154_GROUPDELAY_COMP_BYP, + AD9154_GROUPCOMP_BYPQ_SET(1) | + AD9154_GROUPCOMP_BYPI_SET(1)) + self.ad9154.dac_write(AD9154_GROUPDELAY_COMP_I, 0) + self.ad9154.dac_write(AD9154_GROUPDELAY_COMP_Q, 0) + self.ad9154.dac_write(AD9154_PDP_AVG_TIME, AD9154_PDP_ENABLE_SET(0)) + + self.ad9154.dac_write(AD9154_MASTER_PD, 0) + self.ad9154.dac_write(AD9154_PHY_PD, 0x0f) # power down lanes 0-3 + self.ad9154.dac_write(AD9154_GENERIC_PD, + AD9154_PD_SYNCOUT0B_SET(0) | + AD9154_PD_SYNCOUT1B_SET(1)) + self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_0, + AD9154_LINK_EN_SET(0x0) | AD9154_LINK_PAGE_SET(0) | + AD9154_LINK_MODE_SET(0) | AD9154_CHECKSUM_MODE_SET(0)) + self.ad9154.dac_write(AD9154_ILS_DID, jesd_settings.did) + self.ad9154.dac_write(AD9154_ILS_BID, jesd_settings.bid) + self.ad9154.dac_write(AD9154_ILS_LID0, 0x00) # lane id + self.ad9154.dac_write(AD9154_ILS_SCR_L, + AD9154_L_1_SET(jesd_settings.phy.l - 1) | + AD9154_SCR_SET(1)) + self.ad9154.dac_write(AD9154_ILS_F, jesd_settings.transport.f - 1) + self.ad9154.dac_write(AD9154_ILS_K, jesd_settings.transport.k - 1) + self.ad9154.dac_write(AD9154_ILS_M, jesd_settings.phy.m - 1) + self.ad9154.dac_write(AD9154_ILS_CS_N, + AD9154_N_1_SET(jesd_settings.phy.n - 1) | + AD9154_CS_SET(0)) + self.ad9154.dac_write(AD9154_ILS_NP, + AD9154_NP_1_SET(jesd_settings.phy.np - 1) | + AD9154_SUBCLASSV_SET(jesd_settings.phy.subclassv)) + self.ad9154.dac_write(AD9154_ILS_S, + AD9154_S_1_SET(jesd_settings.transport.s - 1) | + AD9154_JESDV_SET(jesd_settings.phy.jesdv)) + self.ad9154.dac_write(AD9154_ILS_HD_CF, + AD9154_HD_SET(0) | AD9154_CF_SET(0)) + self.ad9154.dac_write(AD9154_ILS_CHECKSUM, jesd_checksum) + self.ad9154.dac_write(AD9154_LANEDESKEW, 0x0f) + for i in range(8): + self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_DIS_SET(0) | + AD9154_DISABLE_ERR_CNTR_DIS_SET(0) | + AD9154_RST_ERR_CNTR_DIS_SET(1) | AD9154_LANE_ADDR_DIS_SET(i)) + self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_DIS_SET(0) | + AD9154_DISABLE_ERR_CNTR_DIS_SET(0) | + AD9154_RST_ERR_CNTR_DIS_SET(0) | AD9154_LANE_ADDR_DIS_SET(i)) + self.ad9154.dac_write(AD9154_NIT_W, AD9154_RST_IRQ_NIT_SET(0) | + AD9154_DISABLE_ERR_CNTR_NIT_SET(0) | + AD9154_RST_ERR_CNTR_NIT_SET(1) | AD9154_LANE_ADDR_NIT_SET(i)) + self.ad9154.dac_write(AD9154_NIT_W, AD9154_RST_IRQ_NIT_SET(0) | + AD9154_DISABLE_ERR_CNTR_NIT_SET(0) | + AD9154_RST_ERR_CNTR_NIT_SET(0) | AD9154_LANE_ADDR_NIT_SET(i)) + self.ad9154.dac_write(AD9154_UNEXPECTEDCONTROL_W, AD9154_RST_IRQ_UCC_SET(0) | + AD9154_DISABLE_ERR_CNTR_UCC_SET(0) | + AD9154_RST_ERR_CNTR_UCC_SET(1) | AD9154_LANE_ADDR_UCC_SET(i)) + self.ad9154.dac_write(AD9154_BADDISPARITY, AD9154_RST_IRQ_UCC_SET(0) | + AD9154_DISABLE_ERR_CNTR_UCC_SET(0) | + AD9154_RST_ERR_CNTR_UCC_SET(0) | AD9154_LANE_ADDR_UCC_SET(i)) + self.ad9154.dac_write(AD9154_CTRLREG1, jesd_settings.transport.f) + self.ad9154.dac_write(AD9154_CTRLREG2, AD9154_ILAS_MODE_SET(0) | + AD9154_THRESHOLD_MASK_EN_SET(0)) + self.ad9154.dac_write(AD9154_KVAL, 1) # *4*K multiframes during ILAS + self.ad9154.dac_write(AD9154_LANEENABLE, 0x0f) # CGS _after_ this + + self.ad9154.dac_write(AD9154_TERM_BLK1_CTRLREG0, 1) + self.ad9154.dac_write(AD9154_TERM_BLK2_CTRLREG0, 1) + self.ad9154.dac_write(AD9154_SERDES_SPI_REG, 1) + self.ad9154.dac_write(AD9154_CDR_OPERATING_MODE_REG_0, + AD9154_CDR_OVERSAMP_SET(0) | AD9154_CDR_RESERVED_SET(0x2) | + AD9154_ENHALFRATE_SET(1)) + self.ad9154.dac_write(AD9154_CDR_RESET, 0) + self.ad9154.dac_write(AD9154_CDR_RESET, 1) + self.ad9154.dac_write(AD9154_REF_CLK_DIVIDER_LDO, + AD9154_SPI_CDR_OVERSAMP_SET(0x0) | + AD9154_SPI_LDO_BYPASS_FILT_SET(1) | + AD9154_SPI_LDO_REF_SEL_SET(0)) + self.ad9154.dac_write(AD9154_LDO_FILTER_1, 0x62) # magic + self.ad9154.dac_write(AD9154_LDO_FILTER_2, 0xc9) # magic + self.ad9154.dac_write(AD9154_LDO_FILTER_3, 0x0e) # magic + self.ad9154.dac_write(AD9154_CP_CURRENT_SPI, + AD9154_SPI_CP_CURRENT_SET(0x12) | + AD9154_SPI_SERDES_LOGEN_POWER_MODE_SET(0)) + self.ad9154.dac_write(AD9154_VCO_LDO, 0x7b) # magic + self.ad9154.dac_write(AD9154_PLL_RD_REG, + AD9154_SPI_SERDES_LOGEN_PD_CORE_SET(0) | + AD9154_SPI_SERDES_LDO_PD_SET(0) | AD9154_SPI_SYN_PD_SET(0) | + AD9154_SPI_VCO_PD_ALC_SET(0) | AD9154_SPI_VCO_PD_PTAT_SET(0) | + AD9154_SPI_VCO_PD_SET(0)) + self.ad9154.dac_write(AD9154_ALC_VARACTOR, + AD9154_SPI_VCO_VARACTOR_SET(0x9) | + AD9154_SPI_INIT_ALC_VALUE_SET(0x8)) + self.ad9154.dac_write(AD9154_VCO_OUTPUT, + AD9154_SPI_VCO_OUTPUT_LEVEL_SET(0xc) | + AD9154_SPI_VCO_OUTPUT_RESERVED_SET(0x4)) + self.ad9154.dac_write(AD9154_CP_CONFIG, + AD9154_SPI_CP_TEST_SET(0) | + AD9154_SPI_CP_CAL_EN_SET(1) | + AD9154_SPI_CP_FORCE_CALBITS_SET(0) | + AD9154_SPI_CP_OFFSET_OFF_SET(0) | + AD9154_SPI_CP_ENABLE_MACHINE_SET(1) | + AD9154_SPI_CP_DITHER_MODE_SET(0) | + AD9154_SPI_CP_HALF_VCO_CAL_CLK_SET(0)) + self.ad9154.dac_write(AD9154_VCO_BIAS_1, + AD9154_SPI_VCO_BIAS_REF_SET(0x3) | + AD9154_SPI_VCO_BIAS_TCF_SET(0x3)) + self.ad9154.dac_write(AD9154_VCO_BIAS_2, + AD9154_SPI_PRESCALE_BIAS_SET(0x1) | + AD9154_SPI_LAST_ALC_EN_SET(1) | + AD9154_SPI_PRESCALE_BYPASS_R_SET(0x1) | + AD9154_SPI_VCO_COMP_BYPASS_BIASR_SET(0) | + AD9154_SPI_VCO_BYPASS_DAC_R_SET(0)) + self.ad9154.dac_write(AD9154_VCO_PD_OVERRIDES, + AD9154_SPI_VCO_PD_OVERRIDE_VCO_BUF_SET(0) | + AD9154_SPI_VCO_PD_OVERRIDE_CAL_TCF_SET(1) | + AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_TCF_SET(0) | + AD9154_SPI_VCO_PD_OVERRIDE_VAR_REF_SET(0)) + self.ad9154.dac_write(AD9154_VCO_CAL, + AD9154_SPI_FB_CLOCK_ADV_SET(0x2) | + AD9154_SPI_VCO_CAL_COUNT_SET(0x3) | + AD9154_SPI_VCO_CAL_ALC_WAIT_SET(0) | + AD9154_SPI_VCO_CAL_EN_SET(1)) + self.ad9154.dac_write(AD9154_CP_LEVEL_DETECT, + AD9154_SPI_CP_LEVEL_THRESHOLD_HIGH_SET(0x2) | + AD9154_SPI_CP_LEVEL_THRESHOLD_LOW_SET(0x5) | + AD9154_SPI_CP_LEVEL_DET_PD_SET(0)) + self.ad9154.dac_write(AD9154_VCO_VARACTOR_CTRL_0, + AD9154_SPI_VCO_VARACTOR_OFFSET_SET(0xe) | + AD9154_SPI_VCO_VARACTOR_REF_TCF_SET(0x7)) + self.ad9154.dac_write(AD9154_VCO_VARACTOR_CTRL_1, + AD9154_SPI_VCO_VARACTOR_REF_SET(0x6)) + # ensure link is txing + #self.ad9154.dac_write(AD9154_SERDESPLL_ENABLE_CNTRL, + # AD9154_ENABLE_SERDESPLL_SET(1) | AD9154_RECAL_SERDESPLL_SET(1)) + self.ad9154.dac_write(AD9154_SERDESPLL_ENABLE_CNTRL, + AD9154_ENABLE_SERDESPLL_SET(1) | AD9154_RECAL_SERDESPLL_SET(0)) + while not AD9154_SERDES_PLL_LOCK_RB_GET(self.ad9154.dac_read(AD9154_PLL_STATUS)): + pass + + self.ad9154.dac_write(AD9154_EQ_BIAS_REG, AD9154_EQ_BIAS_RESERVED_SET(0x22) | + AD9154_EQ_POWER_MODE_SET(1)) + + self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_1, 1) # subclass 1 + self.ad9154.dac_write(AD9154_LMFC_DELAY_0, 0) + self.ad9154.dac_write(AD9154_LMFC_DELAY_1, 0) + self.ad9154.dac_write(AD9154_LMFC_VAR_0, 0x0a) # receive buffer delay + self.ad9154.dac_write(AD9154_LMFC_VAR_1, 0x0a) + self.ad9154.dac_write(AD9154_SYNC_ERRWINDOW, 0) # +- 1/2 DAC clock + self.ad9154.dac_write(AD9154_SYNC_CONTROL, + AD9154_SYNCMODE_SET(0x9) | AD9154_SYNCENABLE_SET(0) | + AD9154_SYNCARM_SET(0) | AD9154_SYNCCLRSTKY_SET(1) | + AD9154_SYNCCLRLAST_SET(1)) + self.ad9154.dac_write(AD9154_SYNC_CONTROL, + AD9154_SYNCMODE_SET(0x9) | AD9154_SYNCENABLE_SET(1) | + AD9154_SYNCARM_SET(0) | AD9154_SYNCCLRSTKY_SET(1) | + AD9154_SYNCCLRLAST_SET(1)) + self.ad9154.dac_write(AD9154_SYNC_CONTROL, + AD9154_SYNCMODE_SET(0x9) | AD9154_SYNCENABLE_SET(1) | + AD9154_SYNCARM_SET(1) | AD9154_SYNCCLRSTKY_SET(0) | + AD9154_SYNCCLRLAST_SET(0)) + self.busywait_us(1000) # ensure at leas one sysref edge + if not AD9154_SYNC_LOCK_GET(self.ad9154.dac_read(AD9154_SYNC_STATUS)): + raise ValueError("no sync lock") + self.ad9154.dac_write(AD9154_XBAR_LN_0_1, + AD9154_LOGICAL_LANE0_SRC_SET(7) | AD9154_LOGICAL_LANE1_SRC_SET(6)) + self.ad9154.dac_write(AD9154_XBAR_LN_2_3, + AD9154_LOGICAL_LANE2_SRC_SET(5) | AD9154_LOGICAL_LANE3_SRC_SET(4)) + self.ad9154.dac_write(AD9154_XBAR_LN_4_5, + AD9154_LOGICAL_LANE4_SRC_SET(0) | AD9154_LOGICAL_LANE5_SRC_SET(0)) + self.ad9154.dac_write(AD9154_XBAR_LN_6_7, + AD9154_LOGICAL_LANE6_SRC_SET(0) | AD9154_LOGICAL_LANE7_SRC_SET(0)) + self.ad9154.dac_write(AD9154_JESD_BIT_INVERSE_CTRL, 0x00) + self.ad9154.dac_write(AD9154_GENERAL_JRX_CTRL_0, + AD9154_LINK_EN_SET(0x1) | AD9154_LINK_PAGE_SET(0) | + AD9154_LINK_MODE_SET(0) | AD9154_CHECKSUM_MODE_SET(0)) + + @kernel + def monitor(self): + self.ad9154.dac_write(AD9154_IRQ_STATUS0, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS1, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS2, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS3, 0x00) + + self.ad9154.dac_write(AD9154_IRQEN_STATUSMODE0, + AD9154_IRQEN_SMODE_LANEFIFOERR_SET(1) | + AD9154_IRQEN_SMODE_SERPLLLOCK_SET(1) | + AD9154_IRQEN_SMODE_SERPLLLOST_SET(1) | + AD9154_IRQEN_SMODE_DACPLLLOCK_SET(1) | + AD9154_IRQEN_SMODE_DACPLLLOST_SET(1)) + + self.ad9154.dac_write(AD9154_IRQEN_STATUSMODE1, + AD9154_IRQEN_SMODE_PRBS0_SET(1) | + AD9154_IRQEN_SMODE_PRBS1_SET(1) | + AD9154_IRQEN_SMODE_PRBS2_SET(1) | + AD9154_IRQEN_SMODE_PRBS3_SET(1)) + + self.ad9154.dac_write(AD9154_IRQEN_STATUSMODE2, + AD9154_IRQEN_SMODE_SYNC_TRIP0_SET(1) | + AD9154_IRQEN_SMODE_SYNC_WLIM0_SET(1) | + AD9154_IRQEN_SMODE_SYNC_ROTATE0_SET(1) | + AD9154_IRQEN_SMODE_SYNC_LOCK0_SET(1) | + AD9154_IRQEN_SMODE_NCO_ALIGN0_SET(1) | + AD9154_IRQEN_SMODE_BLNKDONE0_SET(1) | + AD9154_IRQEN_SMODE_PDPERR0_SET(1)) + + self.ad9154.dac_write(AD9154_IRQEN_STATUSMODE3, + AD9154_IRQEN_SMODE_SYNC_TRIP1_SET(1) | + AD9154_IRQEN_SMODE_SYNC_WLIM1_SET(1) | + AD9154_IRQEN_SMODE_SYNC_ROTATE1_SET(1) | + AD9154_IRQEN_SMODE_SYNC_LOCK1_SET(1) | + AD9154_IRQEN_SMODE_NCO_ALIGN1_SET(1) | + AD9154_IRQEN_SMODE_BLNKDONE1_SET(1) | + AD9154_IRQEN_SMODE_PDPERR1_SET(1)) + + self.ad9154.dac_write(AD9154_IRQ_STATUS0, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS1, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS2, 0x00) + self.ad9154.dac_write(AD9154_IRQ_STATUS3, 0x00) diff --git a/artiq/examples/phaser/repository/demo.py b/artiq/examples/phaser/repository/demo.py new file mode 100644 index 000000000..221016904 --- /dev/null +++ b/artiq/examples/phaser/repository/demo.py @@ -0,0 +1,50 @@ +from artiq.experiment import * + + +class SAWGTest(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("led") + self.setattr_device("ttl_sma") + + self.setattr_device("sawg0") + self.setattr_device("sawg1") + self.setattr_device("sawg2") + self.setattr_device("sawg3") + + @kernel + def run(self): + self.core.break_realtime() + self.ttl_sma.output() + + while True: + self.sawg0.amplitude1.set(0.) + self.sawg0.frequency0.set(0*MHz) + self.sawg1.amplitude1.set(0.) + self.sawg1.frequency0.set(0*MHz) + delay(20*ms) + + self.sawg0.amplitude1.set(.4) + self.sawg0.frequency0.set(10*MHz) + self.sawg0.phase0.set(0.) + self.sawg1.amplitude1.set(.4) + self.sawg1.frequency0.set(10*MHz) + self.sawg1.phase0.set(0.) + self.ttl_sma.pulse(200*ns) + self.sawg1.amplitude1.set(.1) + delay(200*ns) + self.sawg1.amplitude1.set(-.4) + self.ttl_sma.pulse(200*ns) + self.sawg1.amplitude1.set(.4) + delay(200*ns) + self.sawg1.phase0.set(.25) + self.ttl_sma.pulse(200*ns) + self.sawg1.phase0.set(.5) + delay(200*ns) + self.sawg0.phase0.set(.5) + self.ttl_sma.pulse(200*ns) + self.sawg1.frequency0.set(30*MHz) + delay(200*ns) + self.sawg1.frequency0.set(10*MHz) + self.sawg1.phase0.set(0.) + self.ttl_sma.pulse(200*ns) diff --git a/artiq/examples/phaser/repository/demo_2tone.py b/artiq/examples/phaser/repository/demo_2tone.py new file mode 100644 index 000000000..5bcfe9962 --- /dev/null +++ b/artiq/examples/phaser/repository/demo_2tone.py @@ -0,0 +1,46 @@ +from artiq.experiment import * + + +class SAWGTest(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("led") + self.setattr_device("ttl_sma") + + self.setattr_device("sawg0") + self.setattr_device("sawg1") + self.setattr_device("sawg2") + self.setattr_device("sawg3") + + @kernel + def run(self): + self.core.break_realtime() + self.ttl_sma.output() + + while True: + t_up = t_hold = t_down = 800*ns + a1 = .3 + a2 = .4 + order = 3 + + delay(20*ms) + self.sawg0.frequency0.set(10*MHz) + self.sawg0.phase0.set(0.) + self.sawg0.frequency1.set(1*MHz) + self.sawg0.phase1.set(0.) + self.sawg0.frequency2.set(9*MHz) + self.sawg0.phase2.set(0.) + with parallel: + self.sawg0.amplitude1.smooth(.0, a1, t_up, order) + self.sawg0.amplitude2.smooth(.0, a2, t_up, order) + self.sawg0.amplitude1.set(a1) + self.sawg0.amplitude2.set(a2) + delay(t_hold) + with parallel: + self.sawg0.amplitude1.smooth(a1, .0, t_down, order) + self.sawg0.amplitude2.smooth(a2, .0, t_down, order) + self.sawg0.amplitude1.set(.0) + self.sawg0.amplitude2.set(.0) + + self.sawg1.amplitude1.set(.0) + self.sawg1.amplitude2.set(.0) diff --git a/artiq/examples/phaser/repository/test_ad9154_prbs.py b/artiq/examples/phaser/repository/test_ad9154_prbs.py new file mode 100644 index 000000000..ad7562c06 --- /dev/null +++ b/artiq/examples/phaser/repository/test_ad9154_prbs.py @@ -0,0 +1,60 @@ +from artiq.coredevice.ad9154_reg import * +from artiq.experiment import * + + +class Test(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("ad9154") + + @kernel + def run(self): + for e in range(2): + for i in range(3): # prbs7, prbs15, prbs31 + self.prbs(i, 10, e) + + @kernel + def busywait_us(self, t): + t = self.core.get_rtio_counter_mu() + self.core.seconds_to_mu(t*us) + while self.core.get_rtio_counter_mu() < t: + pass + + def p(self, f, *a): + print(f.format(*a)) + + @kernel + def prbs(self, p, t, inject_errors): + self.p("---\nprbs sequence {}, threshold {}, inject_errors {}:", + p, t, inject_errors) + self.ad9154.jesd_prbs((1 << p) | (inject_errors << 3)) + + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, + AD9154_PHY_PRBS_PAT_SEL_SET(p)) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_EN, 0xff) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, + AD9154_PHY_PRBS_PAT_SEL_SET(p) | AD9154_PHY_TEST_RESET_SET(1)) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, + AD9154_PHY_PRBS_PAT_SEL_SET(p)) + + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_THRESHOLD_LOBITS, t) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_THRESHOLD_MIDBITS, t >> 8) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_THRESHOLD_MIDBITS, t >> 16) + + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, AD9154_PHY_PRBS_PAT_SEL_SET(p)) + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, + AD9154_PHY_PRBS_PAT_SEL_SET(p) | AD9154_PHY_TEST_START_SET(1)) + + self.busywait_us(1000000) + + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, AD9154_PHY_PRBS_PAT_SEL_SET(p)) + + self.p("prbs status: {:#04x}", self.ad9154.dac_read(AD9154_PHY_PRBS_TEST_STATUS)) + + for i in range(8): + self.ad9154.dac_write(AD9154_PHY_PRBS_TEST_CTRL, AD9154_PHY_SRC_ERR_CNT_SET(i)) + self.p("prbs errors[{}]: {:#08x}", i, + self.ad9154.dac_read(AD9154_PHY_PRBS_TEST_ERRCNT_LOBITS) | + (self.ad9154.dac_read(AD9154_PHY_PRBS_TEST_ERRCNT_MIDBITS) << 8) | + (self.ad9154.dac_read(AD9154_PHY_PRBS_TEST_ERRCNT_HIBITS) << 16)) + + self.ad9154.jesd_prbs(0) diff --git a/artiq/examples/phaser/repository/test_ad9154_status.py b/artiq/examples/phaser/repository/test_ad9154_status.py new file mode 100644 index 000000000..0f047a8c7 --- /dev/null +++ b/artiq/examples/phaser/repository/test_ad9154_status.py @@ -0,0 +1,138 @@ +from artiq.coredevice.ad9154_reg import * +from artiq.experiment import * + + +class Test(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("ad9154") + + @kernel + def run(self): + self.print_status() + self.print_temp() + + def p(self, f, *a): + print(f % a) + + @kernel + def print_temp(self): + self.ad9154.dac_write(AD9154_DIE_TEMP_CTRL0, AD9154_AUXADC_RESERVED_SET(0x10) | + AD9154_AUXADC_ENABLE_SET(1)) + self.ad9154.dac_write(AD9154_DIE_TEMP_UPDATE, 1) + self.p("temp_code %d", self.ad9154.dac_read(AD9154_DIE_TEMP0) | + (self.ad9154.dac_read(AD9154_DIE_TEMP1) << 8)) + self.ad9154.dac_write(AD9154_DIE_TEMP_CTRL0, AD9154_AUXADC_RESERVED_SET(0x10) | + AD9154_AUXADC_ENABLE_SET(0)) + + @kernel + def print_status(self): + x = self.ad9154.dac_read(AD9154_IRQ_STATUS0) + self.p("LANEFIFOERR: %d, SERPLLLOCK: %d, SERPLLLOST: %d, " + "DACPLLLOCK: %d, DACPLLLOST: %d", + AD9154_LANEFIFOERR_GET(x), AD9154_SERPLLLOCK_GET(x), + AD9154_SERPLLLOST_GET(x), AD9154_DACPLLLOCK_GET(x), + AD9154_DACPLLLOST_GET(x)) + x = self.ad9154.dac_read(AD9154_IRQ_STATUS1) + self.p("PRBS0: %d, PRBS1: %d, PRBS2: %d, PRBS3: %d", + AD9154_PRBS0_GET(x), AD9154_PRBS1_GET(x), + AD9154_PRBS2_GET(x), AD9154_PRBS3_GET(x)) + x = self.ad9154.dac_read(AD9154_IRQ_STATUS2) + self.p("SYNC_TRIP0: %d, SYNC_WLIM0: %d, SYNC_ROTATE0: %d, " + "SYNC_LOCK0: %d, NCO_ALIGN0: %d, BLNKDONE0: %d, " + "PDPERR0: %d", + AD9154_SYNC_TRIP0_GET(x), AD9154_SYNC_WLIM0_GET(x), + AD9154_SYNC_ROTATE0_GET(x), AD9154_SYNC_LOCK0_GET(x), + AD9154_NCO_ALIGN0_GET(x), AD9154_BLNKDONE0_GET(x), + AD9154_PDPERR0_GET(x)) + x = self.ad9154.dac_read(AD9154_IRQ_STATUS3) + self.p("SYNC_TRIP1: %d, SYNC_WLIM1: %d, SYNC_ROTATE1: %d, " + "SYNC_LOCK1: %d, NCO_ALIGN1: %d, BLNKDONE1: %d, " + "PDPERR1: %d", + AD9154_SYNC_TRIP1_GET(x), AD9154_SYNC_WLIM1_GET(x), + AD9154_SYNC_ROTATE1_GET(x), AD9154_SYNC_LOCK1_GET(x), + AD9154_NCO_ALIGN1_GET(x), AD9154_BLNKDONE1_GET(x), + AD9154_PDPERR1_GET(x)) + x = self.ad9154.dac_read(AD9154_JESD_CHECKS) + self.p("ERR_INTSUPP: %d, ERR_SUBCLASS: %d, ERR_KUNSUPP: %d, " + "ERR_JESDBAD: %d, ERR_WINLIMIT: %d, ERR_DLYOVER: %d", + AD9154_ERR_INTSUPP_GET(x), AD9154_ERR_SUBCLASS_GET(x), + AD9154_ERR_KUNSUPP_GET(x), AD9154_ERR_JESDBAD_GET(x), + AD9154_ERR_WINLIMIT_GET(x), AD9154_ERR_DLYOVER_GET(x)) + + x = self.ad9154.dac_read(AD9154_DACPLLSTATUS) + self.p("DACPLL_LOCK: %d, VCO_CAL_PROGRESS: %d, CP_CAL_VALID: %d, " + "CP_OVERRANGE_L: %d, CP_OVERRANGE_H: %d", + AD9154_DACPLL_LOCK_GET(x), AD9154_VCO_CAL_PROGRESS_GET(x), + AD9154_CP_CAL_VALID_GET(x), AD9154_CP_OVERRANGE_L_GET(x), + AD9154_CP_OVERRANGE_H_GET(x)) + + x = self.ad9154.dac_read(AD9154_PLL_STATUS) + self.p("PLL_LOCK_RB: %d, CURRENTS_READY_RB: %d, " + "VCO_CAL_IN_PROGRESS_RB: %d, PLL_CAL_VALID_RB: %d, " + "PLL_OVERRANGE_L_RB: %d, PLL_OVERRANGE_H_RB: %d", + AD9154_SERDES_PLL_LOCK_RB_GET(x), + AD9154_SERDES_CURRENTS_READY_RB_GET(x), + AD9154_SERDES_VCO_CAL_IN_PROGRESS_RB_GET(x), + AD9154_SERDES_PLL_CAL_VALID_RB_GET(x), + AD9154_SERDES_PLL_OVERRANGE_L_RB_GET(x), + AD9154_SERDES_PLL_OVERRANGE_H_RB_GET(x)) + + self.p("CODEGRPSYNC: 0x%02x", self.ad9154.dac_read(AD9154_CODEGRPSYNCFLG)) + self.p("FRAMESYNC: 0x%02x", self.ad9154.dac_read(AD9154_FRAMESYNCFLG)) + self.p("GOODCHECKSUM: 0x%02x", self.ad9154.dac_read(AD9154_GOODCHKSUMFLG)) + self.p("INITIALLANESYNC: 0x%02x", self.ad9154.dac_read(AD9154_INITLANESYNCFLG)) + + x = self.ad9154.dac_read(AD9154_SYNC_CURRERR_H) + self.p("SYNC_CURRERR: 0x%04x", self.ad9154.dac_read(AD9154_SYNC_CURRERR_L) | + (AD9154_CURRERROR_H_GET(x) << 8)) + self.p("SYNC_CURROVER: %d, SYNC_CURRUNDER: %d", + AD9154_CURROVER_GET(x), AD9154_CURRUNDER_GET(x)) + x = self.ad9154.dac_read(AD9154_SYNC_LASTERR_H) + self.p("SYNC_LASTERR: 0x%04x", self.ad9154.dac_read(AD9154_SYNC_LASTERR_L) | + (AD9154_LASTERROR_H_GET(x) << 8)) + self.p("SYNC_LASTOVER: %d, SYNC_LASTUNDER: %d", + AD9154_LASTOVER_GET(x), AD9154_LASTUNDER_GET(x)) + x = self.ad9154.dac_read(AD9154_SYNC_STATUS) + self.p("SYNC_TRIP: %d, SYNC_WLIM: %d, SYNC_ROTATE: %d, " + "SYNC_LOCK: %d, SYNC_BUSY: %d", + AD9154_SYNC_TRIP_GET(x), AD9154_SYNC_WLIM_GET(x), + AD9154_SYNC_ROTATE_GET(x), AD9154_SYNC_LOCK_GET(x), + AD9154_SYNC_BUSY_GET(x)) + + self.p("LANE_FIFO_FULL: 0x%02x", self.ad9154.dac_read(AD9154_FIFO_STATUS_REG_0)) + self.p("LANE_FIFO_EMPTY: 0x%02x", self.ad9154.dac_read(AD9154_FIFO_STATUS_REG_1)) + self.p("DID_REG: 0x%02x", self.ad9154.dac_read(AD9154_DID_REG)) + self.p("BID_REG: 0x%02x", self.ad9154.dac_read(AD9154_BID_REG)) + self.p("SCR_L_REG: 0x%02x", self.ad9154.dac_read(AD9154_SCR_L_REG)) + self.p("F_REG: 0x%02x", self.ad9154.dac_read(AD9154_F_REG)) + self.p("K_REG: 0x%02x", self.ad9154.dac_read(AD9154_K_REG)) + self.p("M_REG: 0x%02x", self.ad9154.dac_read(AD9154_M_REG)) + self.p("CS_N_REG: 0x%02x", self.ad9154.dac_read(AD9154_CS_N_REG)) + self.p("NP_REG: 0x%02x", self.ad9154.dac_read(AD9154_NP_REG)) + self.p("S_REG: 0x%02x", self.ad9154.dac_read(AD9154_S_REG)) + self.p("HD_CF_REG: 0x%02x", self.ad9154.dac_read(AD9154_HD_CF_REG)) + self.p("RES1_REG: 0x%02x", self.ad9154.dac_read(AD9154_RES1_REG)) + self.p("RES2_REG: 0x%02x", self.ad9154.dac_read(AD9154_RES2_REG)) + self.p("LIDx_REG: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + self.ad9154.dac_read(AD9154_LID0_REG), self.ad9154.dac_read(AD9154_LID1_REG), + self.ad9154.dac_read(AD9154_LID2_REG), self.ad9154.dac_read(AD9154_LID3_REG), + self.ad9154.dac_read(AD9154_LID4_REG), self.ad9154.dac_read(AD9154_LID5_REG), + self.ad9154.dac_read(AD9154_LID6_REG), self.ad9154.dac_read(AD9154_LID7_REG)) + self.p("CHECKSUMx_REG: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + self.ad9154.dac_read(AD9154_CHECKSUM0_REG), self.ad9154.dac_read(AD9154_CHECKSUM1_REG), + self.ad9154.dac_read(AD9154_CHECKSUM2_REG), self.ad9154.dac_read(AD9154_CHECKSUM3_REG), + self.ad9154.dac_read(AD9154_CHECKSUM4_REG), self.ad9154.dac_read(AD9154_CHECKSUM5_REG), + self.ad9154.dac_read(AD9154_CHECKSUM6_REG), self.ad9154.dac_read(AD9154_CHECKSUM7_REG)) + self.p("COMPSUMx_REG: 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x", + self.ad9154.dac_read(AD9154_COMPSUM0_REG), self.ad9154.dac_read(AD9154_COMPSUM1_REG), + self.ad9154.dac_read(AD9154_COMPSUM2_REG), self.ad9154.dac_read(AD9154_COMPSUM3_REG), + self.ad9154.dac_read(AD9154_COMPSUM4_REG), self.ad9154.dac_read(AD9154_COMPSUM5_REG), + self.ad9154.dac_read(AD9154_COMPSUM6_REG), self.ad9154.dac_read(AD9154_COMPSUM7_REG)) + self.p("BADDISPARITY: 0x%02x", self.ad9154.dac_read(AD9154_BADDISPARITY)) + self.p("NITDISPARITY: 0x%02x", self.ad9154.dac_read(AD9154_NIT_W)) + self.p("UNEXPECTEDCONTROL: 0x%02x", self.ad9154.dac_read(AD9154_UNEXPECTEDCONTROL_W)) + self.p("DYN_LINK_LATENCY_0: 0x%02x", + self.ad9154.dac_read(AD9154_DYN_LINK_LATENCY_0)) + self.p("DYN_LINK_LATENCY_1: 0x%02x", + self.ad9154.dac_read(AD9154_DYN_LINK_LATENCY_1)) diff --git a/artiq/examples/phaser/repository/test_ad9154_stpl.py b/artiq/examples/phaser/repository/test_ad9154_stpl.py new file mode 100644 index 000000000..d19e90d3b --- /dev/null +++ b/artiq/examples/phaser/repository/test_ad9154_stpl.py @@ -0,0 +1,50 @@ +from jesd204b.transport import seed_to_data + +from artiq.coredevice.ad9154_reg import * +from artiq.experiment import * + + +class Test(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("ad9154") + + def run(self): + self.ad9154.jesd_stpl(1) + # short transport layer test + for i in range(4): + data = seed_to_data(i << 8, True) + fail = self.stpl(i, data) + print("channel", i, "FAIL" if fail else "PASS") + self.ad9154.jesd_stpl(0) + + @kernel + def stpl(self, i, data): + # select dac + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_0, + AD9154_SHORT_TPL_TEST_EN_SET(0) | + AD9154_SHORT_TPL_TEST_RESET_SET(0) | + AD9154_SHORT_TPL_DAC_SEL_SET(i) | + AD9154_SHORT_TPL_SP_SEL_SET(0)) + # set expected value + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_1, data & 0xff) + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_2, (data & 0xff00) >> 8) + # enable stpl + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_0, + AD9154_SHORT_TPL_TEST_EN_SET(1) | + AD9154_SHORT_TPL_TEST_RESET_SET(0) | + AD9154_SHORT_TPL_DAC_SEL_SET(i) | + AD9154_SHORT_TPL_SP_SEL_SET(0)) + # reset stpl + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_0, + AD9154_SHORT_TPL_TEST_EN_SET(1) | + AD9154_SHORT_TPL_TEST_RESET_SET(1) | + AD9154_SHORT_TPL_DAC_SEL_SET(i) | + AD9154_SHORT_TPL_SP_SEL_SET(0)) + # release reset stpl + self.ad9154.dac_write(AD9154_SHORT_TPL_TEST_0, + AD9154_SHORT_TPL_TEST_EN_SET(1) | + AD9154_SHORT_TPL_TEST_RESET_SET(0) | + AD9154_SHORT_TPL_DAC_SEL_SET(i) | + AD9154_SHORT_TPL_SP_SEL_SET(0)) + return self.ad9154.dac_read(AD9154_SHORT_TPL_TEST_3) diff --git a/artiq/examples/phaser/startup_kernel.py b/artiq/examples/phaser/startup_kernel.py new file mode 100644 index 000000000..3fb678ab4 --- /dev/null +++ b/artiq/examples/phaser/startup_kernel.py @@ -0,0 +1,73 @@ +from artiq.experiment import * +from artiq.coredevice.ad9516_reg import * + + +class StartupKernel(EnvExperiment): + def build(self): + self.setattr_device("core") + self.setattr_device("led") + self.setattr_device("ad9154") + + @kernel + def run(self): + self.core.reset() + self.ad9154.jesd_enable(0) + self.ad9154.init() + self.clock_setup() + + @kernel + def clock_setup(self): + # reset + self.ad9154.clock_write(AD9516_SERIAL_PORT_CONFIGURATION, + AD9516_SOFT_RESET | AD9516_SOFT_RESET_MIRRORED | + AD9516_LONG_INSTRUCTION | AD9516_LONG_INSTRUCTION_MIRRORED | + AD9516_SDO_ACTIVE | AD9516_SDO_ACTIVE_MIRRORED) + self.ad9154.clock_write(AD9516_SERIAL_PORT_CONFIGURATION, + AD9516_LONG_INSTRUCTION | AD9516_LONG_INSTRUCTION_MIRRORED | + AD9516_SDO_ACTIVE | AD9516_SDO_ACTIVE_MIRRORED) + if self.ad9154.clock_read(AD9516_PART_ID) != 0x41: + raise ValueError("AD9516 not found") + + # use clk input, dclk=clk/2 + self.ad9154.clock_write(AD9516_PFD_AND_CHARGE_PUMP, 1*AD9516_PLL_POWER_DOWN | + 0*AD9516_CHARGE_PUMP_MODE) + self.ad9154.clock_write(AD9516_VCO_DIVIDER, 0) + self.ad9154.clock_write(AD9516_INPUT_CLKS, 0*AD9516_SELECT_VCO_OR_CLK | + 0*AD9516_BYPASS_VCO_DIVIDER) + + self.ad9154.clock_write(AD9516_OUT0, 2*AD9516_OUT0_POWER_DOWN) + self.ad9154.clock_write(AD9516_OUT2, 2*AD9516_OUT2_POWER_DOWN) + self.ad9154.clock_write(AD9516_OUT3, 2*AD9516_OUT3_POWER_DOWN) + self.ad9154.clock_write(AD9516_OUT4, 2*AD9516_OUT4_POWER_DOWN) + self.ad9154.clock_write(AD9516_OUT5, 2*AD9516_OUT5_POWER_DOWN) + self.ad9154.clock_write(AD9516_OUT8, 1*AD9516_OUT8_POWER_DOWN) + + # DAC deviceclk, clk/1 + self.ad9154.clock_write(AD9516_DIVIDER_0_2, AD9516_DIVIDER_0_DIRECT_TO_OUTPUT) + self.ad9154.clock_write(AD9516_OUT1, 0*AD9516_OUT1_POWER_DOWN | + 2*AD9516_OUT1_LVPECLDIFFERENTIAL_VOLTAGE) + + # FPGA deviceclk, dclk/1 + self.ad9154.clock_write(AD9516_DIVIDER_4_3, 0*AD9516_DIVIDER_4_NOSYNC | + 1*AD9516_DIVIDER_4_BYPASS_1 | 1*AD9516_DIVIDER_4_BYPASS_2) + self.ad9154.clock_write(AD9516_DIVIDER_4_4, 0*AD9516_DIVIDER_4_DCCOFF) + self.ad9154.clock_write(AD9516_OUT9, 1*AD9516_OUT9_LVDS_OUTPUT_CURRENT | + 2*AD9516_OUT9_LVDS_CMOS_OUTPUT_POLARITY | + 0*AD9516_OUT9_SELECT_LVDS_CMOS) + + # sysref f_data*S/(K*F), dclk/16 + self.ad9154.clock_write(AD9516_DIVIDER_3_0, (16//2-1)*AD9516_DIVIDER_3_HIGH_CYCLES_1 | + (16//2-1)*AD9516_DIVIDER_3_LOW_CYCLES_1) + self.ad9154.clock_write(AD9516_DIVIDER_3_1, 0*AD9516_DIVIDER_3_PHASE_OFFSET_1 | + 0*AD9516_DIVIDER_3_PHASE_OFFSET_2) + self.ad9154.clock_write(AD9516_DIVIDER_3_3, 0*AD9516_DIVIDER_3_NOSYNC | + 0*AD9516_DIVIDER_3_BYPASS_1 | 1*AD9516_DIVIDER_3_BYPASS_2) + self.ad9154.clock_write(AD9516_DIVIDER_3_4, 0*AD9516_DIVIDER_3_DCCOFF) + self.ad9154.clock_write(AD9516_OUT6, 1*AD9516_OUT6_LVDS_OUTPUT_CURRENT | + 2*AD9516_OUT6_LVDS_CMOS_OUTPUT_POLARITY | + 0*AD9516_OUT6_SELECT_LVDS_CMOS) + self.ad9154.clock_write(AD9516_OUT7, 1*AD9516_OUT7_LVDS_OUTPUT_CURRENT | + 2*AD9516_OUT7_LVDS_CMOS_OUTPUT_POLARITY | + 0*AD9516_OUT7_SELECT_LVDS_CMOS) + + self.ad9154.clock_write(AD9516_UPDATE_ALL_REGISTERS, 1) diff --git a/artiq/gateware/ad9154_fmc_ebz.py b/artiq/gateware/ad9154_fmc_ebz.py new file mode 100644 index 000000000..6f7f32459 --- /dev/null +++ b/artiq/gateware/ad9154_fmc_ebz.py @@ -0,0 +1,74 @@ +from migen.build.generic_platform import * + + +ad9154_fmc_ebz = [ + ("ad9154_spi", 0, + # AD9154 should give control of SPI to FMC when USB cable is unplugged, + # It's the case, but the PIC18F24J50 is introducing noise on SPI SCK + # (???) To workaround that, add 2 jumpers: + # - on XP1, between pin 5 and 6 (will keep the PIC in reset) + # - on JP3 (will force output enable on FXLA108) + Subsignal("clk", Pins("HPC:LA03_P")), + Subsignal("cs_n", Pins("HPC:LA04_N", "HPC:LA05_P")), + Subsignal("mosi", Pins("HPC:LA03_N")), + Subsignal("miso", Pins("HPC:LA04_P")), + Subsignal("en", Pins("HPC:LA05_N")), + IOStandard("LVCMOS25"), + ), + ("ad9154_txen", 0, Pins("HPC:LA07_P"), IOStandard("LVCMOS25")), + ("ad9154_txen", 1, Pins("HPC:LA07_N"), IOStandard("LVCMOS25")), + ("ad9154_refclk", 0, + Subsignal("p", Pins("HPC:GBTCLK0_M2C_P")), + Subsignal("n", Pins("HPC:GBTCLK0_M2C_N")), + ), + ("ad9154_sysref", 0, + Subsignal("p", Pins("HPC:LA00_CC_P")), + Subsignal("n", Pins("HPC:LA00_CC_N")), + IOStandard("LVDS_25"), + Misc("DIFF_TERM=TRUE"), + ), + ("ad9154_sync", 0, + Subsignal("p", Pins("HPC:LA01_CC_P")), + Subsignal("n", Pins("HPC:LA01_CC_N")), + IOStandard("LVDS_25"), + Misc("DIFF_TERM=TRUE"), + ), + ("ad9154_sync", 1, + Subsignal("p", Pins("HPC:LA02_P")), + Subsignal("n", Pins("HPC:LA02_N")), + IOStandard("LVDS_25"), + Misc("DIFF_TERM=TRUE"), + ), + ("ad9154_jesd", 0, # AD9154's SERDIN7 + Subsignal("txp", Pins("HPC:DP0_C2M_P")), + Subsignal("txn", Pins("HPC:DP0_C2M_N")) + ), + ("ad9154_jesd", 1, # AD9154's SERDIN6 + Subsignal("txp", Pins("HPC:DP1_C2M_P")), + Subsignal("txn", Pins("HPC:DP1_C2M_N")) + ), + ("ad9154_jesd", 2, # AD9154's SERDIN5 + Subsignal("txp", Pins("HPC:DP2_C2M_P")), + Subsignal("txn", Pins("HPC:DP2_C2M_N")) + ), + ("ad9154_jesd", 3, # AD9154's SERDIN4 + Subsignal("txp", Pins("HPC:DP3_C2M_P")), + Subsignal("txn", Pins("HPC:DP3_C2M_N")) + ), + ("ad9154_jesd", 4, # AD9154's SERDIN2 + Subsignal("txp", Pins("HPC:DP4_C2M_P")), + Subsignal("txn", Pins("HPC:DP4_C2M_N")) + ), + ("ad9154_jesd", 5, # AD9154's SERDIN0 + Subsignal("txp", Pins("HPC:DP5_C2M_P")), + Subsignal("txn", Pins("HPC:DP5_C2M_N")) + ), + ("ad9154_jesd", 6, # AD9154's SERDIN1 + Subsignal("txp", Pins("HPC:DP6_C2M_P")), + Subsignal("txn", Pins("HPC:DP6_C2M_N")) + ), + ("ad9154_jesd", 7, # AD9154's SERDIN3 + Subsignal("txp", Pins("HPC:DP7_C2M_P")), + Subsignal("txn", Pins("HPC:DP7_C2M_N")) + ), +] diff --git a/artiq/gateware/dsp/__init__.py b/artiq/gateware/dsp/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/artiq/gateware/dsp/accu.py b/artiq/gateware/dsp/accu.py new file mode 100644 index 000000000..6e8776476 --- /dev/null +++ b/artiq/gateware/dsp/accu.py @@ -0,0 +1,112 @@ +from migen import * +from misoc.interconnect.stream import Endpoint + + +class Accu(Module): + def __init__(self, width, meta=[]): + self.i = Endpoint([("p", width), ("f", width), ("clr", 1)]) + self.o = Endpoint([("z", width)]) + self.latency = 1 + + ### + + f = Signal.like(self.i.f) + p = Signal.like(self.i.p) + self.comb += self.i.ack.eq(~self.o.stb | self.o.ack) + self.sync += [ + If(self.o.ack, + self.o.stb.eq(0), + ), + If(self.i.ack, + self.o.stb.eq(1), + If(self.i.stb, + self.o.z.eq(self.i.p + Mux(self.i.clr, 0, self.o.z + p)), + f.eq(self.i.f), + p.eq(self.i.f - self.i.p), + ).Else( + self.o.z.eq(self.o.z + f), + ) + ) + ] + + +class MCM(Module): + def __init__(self, width, constants): + n = len(constants) + self.i = i = Signal(width) + self.o = o = [Signal.like(self.i) for i in range(n)] + + ### + + # TODO: improve MCM + assert range(n) == constants + assert n <= 9 + + if n > 0: + self.comb += o[0].eq(0) + if n > 1: + self.comb += o[1].eq(i) + if n > 2: + self.comb += o[2].eq(i << 1) + if n > 3: + self.comb += o[3].eq(i + (i << 1)) + if n > 4: + self.comb += o[4].eq(i << 2) + if n > 5: + self.comb += o[5].eq(i + (i << 2)) + if n > 6: + self.comb += o[6].eq(o[3] << 1) + if n > 7: + self.comb += o[7].eq((i << 3) - i) + if n > 8: + self.comb += o[8].eq(i << 3) + + +class PhasedAccu(Module): + def __init__(self, width, parallelism=8): + self.i = Endpoint([("p", width), ("f", width), ("clr", 1)]) + self.o = Endpoint([("z{}".format(i), width) for i in + range(parallelism)]) + self.parallelism = parallelism + self.latency = 2 + + ### + + a = MCM(width, range(parallelism + 1)) + self.submodules += a + z = [Signal(width) for i in range(parallelism)] + o = self.o.payload.flatten() + load = Signal() + clr = Signal() + p = Signal.like(self.i.p) + f = Signal.like(self.i.f) + fp = Signal.like(self.i.f) + self.comb += [ + self.i.ack.eq(self.o.ack), + a.i.eq(self.i.f), + ] + + self.sync += [ + If(self.o.ack, + self.o.stb.eq(0), + ), + If(~self.o.stb | self.o.ack, + self.o.stb.eq(1), + If(load, + load.eq(0), + [oi.eq(Mux(clr, 0, o[0] + fp) + zi) + for oi, zi in zip(o, z)], + fp.eq(f), + ).Else( + [oi.eq(oi + fp) for oi in o], + ), + ), + If(self.i.stb & self.i.ack, + [zi.eq(self.i.p - Mux(self.i.clr, 0, p) + aoi) + for zi, aoi in zip(z, a.o)], + clr.eq(self.i.clr), + p.eq(self.i.p), + f.eq(a.o[parallelism]), + load.eq(1), + ), + ] diff --git a/artiq/gateware/dsp/fir.py b/artiq/gateware/dsp/fir.py new file mode 100644 index 000000000..6f1535528 --- /dev/null +++ b/artiq/gateware/dsp/fir.py @@ -0,0 +1,157 @@ +from operator import add +from functools import reduce +import numpy as np +from migen import * + + +def halfgen4(width, n): + """ + http://recycle.lbl.gov/~ldoolitt/halfband + + params: + * `up` is the passband/stopband width, as a fraction of + input sampling rate + * `n is the order of half-band filter to generate + returns: + * `a` is the full set of FIR coefficients, `4*n-1` long. + implement wisely. + """ + + npt = n*40 + wmax = 2*np.pi*width + wfit = (1 - np.linspace(0, 1, npt)[:, None]**2)*wmax + + target = .5*np.ones_like(wfit) + basis = np.cos(wfit*np.arange(1, 2*n, 2)) + l = np.linalg.pinv(basis)@target + + weight = np.ones_like(wfit) + for i in range(40): + err = np.fabs(basis@l - .5) + weight[err > .99*np.max(err)] *= 1 + 1.5/(i + 11) + l = np.linalg.pinv(basis*weight)@(target*weight) + a = np.c_[l, np.zeros_like(l)].ravel()[:-1] + a = np.r_[a[::-1], 1, a]/2 + return a + + +class FIR(Module): + """Full-rate finite impulse response filter. + + :param coefficients: integer taps. + :param width: bit width of input and output. + :param shift: scale factor (as power of two). + """ + def __init__(self, coefficients, width=16, shift=None): + self.width = width + self.i = Signal((width, True)) + self.o = Signal((width, True)) + n = len(coefficients) + self.latency = (n + 1)//2 + 2 + + ### + + # Delay line: increasing delay + x = [Signal((width, True)) for _ in range(n)] + self.sync += [xi.eq(xj) for xi, xj in zip(x, [self.i] + x)] + + if shift is None: + shift = width - 1 + + # Make products + o = [] + for i, c in enumerate(coefficients): + # simplify for halfband and symmetric filters + if c == 0 or c in coefficients[i + 1:]: + continue + m = Signal((width + shift, True)) + self.sync += m.eq(c*reduce(add, [ + xj for xj, cj in zip(x[::-1], coefficients) if cj == c + ])) + o.append(m) + + # Make sum + self.sync += self.o.eq(reduce(add, o) >> shift) + + +class ParallelFIR(Module): + """Full-rate parallelized finite impulse response filter. + + :param coefficients: integer taps. + :param parallelism: number of samples per cycle. + :param width: bit width of input and output. + :param shift: scale factor (as power of two). + """ + def __init__(self, coefficients, parallelism, width=16, shift=None): + self.width = width + self.parallelism = p = parallelism + n = len(coefficients) + # input and output: old to young, decreasing delay + self.i = [Signal((width, True)) for i in range(p)] + self.o = [Signal((width, True)) for i in range(p)] + self.latency = (n + 1)//2//parallelism + 3 # minus one sample + + ### + + # Delay line: young to old, increasing delay + x = [Signal((width, True)) for _ in range(n + p - 1)] + self.sync += [xi.eq(xj) for xi, xj in zip(x, self.i[::-1] + x)] + + if shift is None: + shift = width - 1 + + for j in range(p): + # Make products + o = [] + for i, c in enumerate(coefficients): + # simplify for halfband and symmetric filters + if c == 0 or c in coefficients[i + 1:]: + continue + m = Signal((width + shift, True)) + self.sync += m.eq(c*reduce(add, [ + xj for xj, cj in zip(x[-1 - j::-1], coefficients) if cj == c + ])) + o.append(m) + # Make sum + self.sync += self.o[j].eq(reduce(add, o) >> shift) + + +def halfgen4_cascade(rate, width, order=None): + """Generate coefficients for cascaded half-band filters. + + :param rate: upsampling rate. power of two + :param width: passband/stopband width in units of input sampling rate. + :param order: highest order, defaults to :param:`rate`""" + if order is None: + order = rate + coeff = [] + p = 1 + while p < rate: + p *= 2 + coeff.append(halfgen4(width*p/rate/2, order*p//rate)) + return coeff + + +class ParallelHBFUpsampler(Module): + """Parallel, power-of-two, half-band, cascading upsampler. + + Coefficients should be normalized to overall gain of 2 + (highest/center coefficient being 1).""" + def __init__(self, coefficients, width=16, **kwargs): + self.parallelism = 1 + self.latency = 0 + self.width = width + self.i = Signal((width, True)) + + ### + + i = [self.i] + for coeff in coefficients: + self.parallelism *= 2 + # assert coeff[len(coeff)//2 + 1] == 1 + hbf = ParallelFIR(coeff, self.parallelism, width, **kwargs) + self.submodules += hbf + self.comb += [a.eq(b) for a, b in zip(hbf.i[::2], i)] + i = hbf.o + self.latency += hbf.latency + self.o = i diff --git a/artiq/gateware/dsp/sawg.py b/artiq/gateware/dsp/sawg.py new file mode 100644 index 000000000..080d73fbb --- /dev/null +++ b/artiq/gateware/dsp/sawg.py @@ -0,0 +1,201 @@ +from collections import namedtuple + +from migen import * +from misoc.interconnect.stream import Endpoint +from misoc.cores.cordic import Cordic + +from .accu import PhasedAccu +from .tools import eqh, Delay, SatAddMixin +from .spline import Spline +from .fir import ParallelHBFUpsampler, halfgen4_cascade + + +_Widths = namedtuple("_Widths", "t a p f") +_Orders = namedtuple("_Orders", "a p f") + + +class ParallelDDS(Module): + def __init__(self, widths, parallelism=1, a_delay=0): + self.i = Endpoint([("x", widths.a), ("y", widths.a), + ("f", widths.f), ("p", widths.f), ("clr", 1)]) + self.parallelism = parallelism + self.widths = widths + + ### + + accu = PhasedAccu(widths.f, parallelism) + cordic = [Cordic(width=widths.a, widthz=widths.p, guard=None, + eval_mode="pipelined") for i in range(parallelism)] + self.xo = [c.xo for c in cordic] + self.yo = [c.yo for c in cordic] + a_delay += accu.latency + xy_delay = Delay(2*widths.a, max(0, a_delay)) + z_delay = Delay(parallelism*widths.p, max(0, -a_delay)) + self.submodules += accu, xy_delay, z_delay, cordic + self.latency = max(0, a_delay) + cordic[0].latency + self.gain = cordic[0].gain + + self.comb += [ + xy_delay.i.eq(Cat(self.i.x, self.i.y)), + z_delay.i.eq(Cat(zi[-widths.p:] + for zi in accu.o.payload.flatten())), + eqh(accu.i.p, self.i.p), + accu.i.f.eq(self.i.f), + accu.i.clr.eq(self.i.clr), + accu.i.stb.eq(self.i.stb), + self.i.ack.eq(accu.i.ack), + accu.o.ack.eq(1), + [Cat(c.xi, c.yi).eq(xy_delay.o) for c in cordic], + Cat(c.zi for c in cordic).eq(z_delay.o), + ] + + +class SplineParallelDUC(ParallelDDS): + def __init__(self, widths, orders, **kwargs): + p = Spline(order=orders.p, width=widths.p) + f = Spline(order=orders.f, width=widths.f) + self.f = f.tri(widths.t) + self.p = p.tri(widths.t) + self.submodules += p, f + self.ce = Signal(reset=1) + self.clr = Signal() + super().__init__(widths._replace(p=len(self.p.a0), f=len(self.f.a0)), + **kwargs) + self.latency += f.latency + + ### + + assert p.latency == f.latency + + self.comb += [ + p.o.ack.eq(self.ce), + f.o.ack.eq(self.ce), + eqh(self.i.f, f.o.a0), + eqh(self.i.p, p.o.a0), + self.i.stb.eq(p.o.stb | f.o.stb), + ] + + assert p.latency == 1 + self.sync += [ + self.i.clr.eq(0), + If(p.i.stb, + self.i.clr.eq(self.clr), + ), + ] + + +class SplineParallelDDS(SplineParallelDUC): + def __init__(self, widths, orders, **kwargs): + a = Spline(order=orders.a, width=widths.a) + self.a = a.tri(widths.t) + self.submodules += a + super().__init__(widths._replace(a=len(self.a.a0)), orders, **kwargs) + + ### + + self.comb += [ + a.o.ack.eq(self.ce), + eqh(self.i.x, a.o.a0), + self.i.y.eq(0), + ] + + +class Config(Module): + def __init__(self, width): + self.clr = Signal(4, reset=0b1111) + self.iq_en = Signal(2, reset=0b01) + self.limits = [[Signal((width, True), reset=-(1 << width - 1)), + Signal((width, True), reset=(1 << width - 1) - 1)] + for i in range(3)] + self.clipped = [Signal(2) for i in range(3)] # TODO + self.i = Endpoint([("addr", bits_for(4 + len(self.limits))), + ("data", 16)]) + self.ce = Signal() + + ### + + div = Signal(16, reset=0) + n = Signal.like(div) + pad = Signal() + + reg = Array([Cat(div, n), self.clr, self.iq_en, pad] + + [Cat(*l) for l in self.limits]) + + self.comb += [ + self.i.ack.eq(1), + self.ce.eq(n == 0), + ] + self.sync += [ + n.eq(n - 1), + If(self.ce, + n.eq(div), + ), + If(self.i.stb, + reg[self.i.addr].eq(self.i.data), + ), + ] + + +class Channel(Module, SatAddMixin): + def __init__(self, width=16, parallelism=4, widths=None, orders=None): + if orders is None: + orders = _Orders(a=4, f=2, p=1) + if widths is None: + widths = _Widths(t=width, a=orders.a*width, p=orders.p*width, + f=(orders.f + 2)*width) + + self.submodules.a1 = a1 = SplineParallelDDS(widths, orders) + self.submodules.a2 = a2 = SplineParallelDDS(widths, orders) + coeff = [[int(round((1 << 18)*ci)) for ci in c] + for c in halfgen4_cascade(parallelism, width=.4, order=8)] + hbf = [ParallelHBFUpsampler(coeff, width=width, shift=17) + for i in range(2)] + self.submodules.b = b = SplineParallelDUC( + widths._replace(a=len(a1.xo[0]), f=widths.f - width), orders, + parallelism=parallelism, a_delay=-a1.latency-hbf[0].latency) + cfg = Config(widths.a) + u = Spline(width=widths.a, order=orders.a) + du = Delay(width, a1.latency + hbf[0].latency + b.latency - u.latency) + self.submodules += cfg, u, du, hbf + self.u = u.tri(widths.t) + self.i = [cfg.i, self.u, a1.a, a1.f, a1.p, a2.a, a2.f, a2.p, b.f, b.p] + self.i_names = "cfg u a1 f1 p1 a2 f2 p2 f0 p0".split() + self.i_named = dict(zip(self.i_names, self.i)) + self.y_in = [Signal((width, True)) for i in range(parallelism)] + self.o = [Signal((width, True)) for i in range(parallelism)] + self.widths = widths + self.orders = orders + self.parallelism = parallelism + self.latency = a1.latency + hbf[0].latency + b.latency + 2 + self.cordic_gain = a1.gain*b.gain + + ### + + self.comb += [ + a1.ce.eq(cfg.ce), + a2.ce.eq(cfg.ce), + b.ce.eq(cfg.ce), + u.o.ack.eq(cfg.ce), + Cat(a1.clr, a2.clr, b.clr).eq(cfg.clr), + b.i.x.eq(hbf[0].o[0]), # FIXME: rip up + b.i.y.eq(hbf[1].o[0]), + ] + self.sync += [ + hbf[0].i.eq(self.sat_add(a1.xo[0], a2.xo[0], + limits=cfg.limits[0], + clipped=cfg.clipped[0])), + hbf[1].i.eq(self.sat_add(a1.yo[0], a2.yo[0], + limits=cfg.limits[1], + clipped=cfg.clipped[1])), + eqh(du.i, u.o.a0), + ] + # wire up outputs and q_{i,o} exchange + for o, x, y in zip(self.o, b.xo, self.y_in): + self.sync += [ + o.eq(self.sat_add( + du.o, Mux(cfg.iq_en[0], x, 0), Mux(cfg.iq_en[1], y, 0), + limits=cfg.limits[2], clipped=cfg.clipped[2])), + ] + + def connect_y(self, buddy): + self.comb += Cat(buddy.y_in).eq(Cat(self.b.yo)) diff --git a/artiq/gateware/dsp/spline.py b/artiq/gateware/dsp/spline.py new file mode 100644 index 000000000..0061653dc --- /dev/null +++ b/artiq/gateware/dsp/spline.py @@ -0,0 +1,46 @@ +from migen import * +from misoc.interconnect.stream import Endpoint + + +class Spline(Module): + def __init__(self, order, width, step=1, time_width=None): + if not (step == 1 or order <= 2): + raise ValueError("For non-linear splines, " + "`step` needs to be one.") + layout = [("a{}".format(i), (width, True)) for i in range(order)] + self.i = Endpoint(layout) + self.o = Endpoint(layout) + self.latency = 1 + + ### + + o = self.o.payload.flatten() + + self.comb += self.i.ack.eq(~self.o.stb | self.o.ack) + self.sync += [ + If(self.o.ack, + self.o.stb.eq(0), + ), + If(self.i.ack, + self.o.stb.eq(1), + [o[i].eq(o[i] + (o[i + 1] << log2_int(step))) + for i in range(order - 1)], + If(self.i.stb, + self.o.payload.eq(self.i.payload), + ), + ), + ] + + def tri(self, time_width): + layout = [(name, (length - i*time_width, signed)) + for i, (name, (length, signed), dir) in + enumerate(self.i.payload.layout[::-1])] + layout.reverse() + i = Endpoint(layout) + self.comb += [ + self.i.stb.eq(i.stb), + i.ack.eq(self.i.ack), + [i0[-len(i1):].eq(i1) for i0, i1 in + zip(self.i.payload.flatten(), i.payload.flatten())] + ] + return i diff --git a/artiq/gateware/dsp/tools.py b/artiq/gateware/dsp/tools.py new file mode 100644 index 000000000..b413fae3f --- /dev/null +++ b/artiq/gateware/dsp/tools.py @@ -0,0 +1,61 @@ +from operator import add +from functools import reduce + +from migen import * + + +class Delay(Module): + def __init__(self, i, delay, o=None): + if isinstance(i, (int, tuple)): + z = [Signal(i) for j in range(delay + 1)] + elif isinstance(i, list): + z = [Record(i) for j in range(delay + 1)] + elif isinstance(i, Record): + z = [Record(i.layout) for j in range(delay + 1)] + else: + z = [Signal.like(i) for j in range(delay + 1)] + self.i = z[0] + self.o = z[-1] + if not isinstance(i, (int, list, tuple)): + self.comb += self.i.eq(i) + if o is not None: + self.comb += o.eq(self.o) + self.latency = delay + self.sync += [z[j + 1].eq(z[j]) for j in range(delay)] + + +def eqh(a, b): + return a[-len(b):].eq(b[-len(a):]) + + +class SatAddMixin: + """Signed saturating addition mixin""" + def sat_add(self, *a, limits=None, clipped=None): + a = list(a) + # assert all(value_bits_sign(ai)[1] for ai in a) + length = max(len(ai) for ai in a) + carry = log2_int(len(a), need_pow2=False) + full = Signal((length + carry, True)) + limited = Signal((length, True)) + clip = Signal(2) + if clipped is not None: + clipped.eq(clip) + self.comb += [ + full.eq(reduce(add, a)), + ] + if limits is None: + self.comb += [ + If(full[-1-carry:] == Replicate(full[-1], carry + 1), + limited.eq(full), + clip.eq(0), + ).Else( + limited.eq(Cat(Replicate(~full[-1], length - 1), full[-1])), + clip.eq(Cat(full[-1], ~full[-1])), + ) + ] + else: + self.comb += [ + clip.eq(Cat(full < limits[0], full > limits[1])), + limited.eq(Array([full, limits[0], limits[1], 0])[clip]), + ] + return limited diff --git a/artiq/gateware/rtio/phy/sawg.py b/artiq/gateware/rtio/phy/sawg.py new file mode 100644 index 000000000..84094f5a2 --- /dev/null +++ b/artiq/gateware/rtio/phy/sawg.py @@ -0,0 +1,27 @@ +from collections import namedtuple + +from migen import * +from artiq.gateware.rtio import rtlink + +from artiq.gateware.dsp.sawg import Channel as _Channel + + +_Phy = namedtuple("Phy", "rtlink probes overrides") + +_ChannelPHY = ClockDomainsRenamer("rio_phy")(_Channel) + + +class Channel(_ChannelPHY): + def __init__(self, *args, **kwargs): + _ChannelPHY.__init__(self, *args, **kwargs) + self.phys = [] + for i in self.i: + rl = rtlink.Interface(rtlink.OInterface(len(i.payload))) + self.comb += [ + i.stb.eq(rl.o.stb), + rl.o.busy.eq(~i.ack), + i.payload.raw_bits().eq(rl.o.data), + ] + # TODO probes, overrides + self.phys.append(_Phy(rl, [], [])) + self.phys_named = dict(zip(self.i_names, self.phys)) diff --git a/artiq/gateware/rtio/phy/ttl_serdes_7series.py b/artiq/gateware/rtio/phy/ttl_serdes_7series.py index 018762984..e1d5278f5 100644 --- a/artiq/gateware/rtio/phy/ttl_serdes_7series.py +++ b/artiq/gateware/rtio/phy/ttl_serdes_7series.py @@ -31,6 +31,32 @@ class _OSERDESE2_8X(Module): o_O=pad, o_OB=pad_n) +class _ISERDESE2_8X(Module): + def __init__(self, pad, pad_n=None): + self.o = Signal(8) + self.i = Signal(8) + self.oe = Signal() + + # # # + + pad_i = Signal() + i = self.i + self.specials += Instance("ISERDESE2", p_DATA_RATE="DDR", + p_DATA_WIDTH=8, + p_INTERFACE_TYPE="NETWORKING", p_NUM_CE=1, + o_Q1=i[7], o_Q2=i[6], o_Q3=i[5], o_Q4=i[4], + o_Q5=i[3], o_Q6=i[2], o_Q7=i[1], o_Q8=i[0], + i_D=pad_i, + i_CLK=ClockSignal("rtiox4"), + i_CLKB=~ClockSignal("rtiox4"), + i_CE1=1, i_RST=0, + i_CLKDIV=ClockSignal("rio_phy")) + if pad_n is None: + self.comb += pad_i.eq(pad) + else: + self.specials += Instance("IBUFDS", o_O=pad_i, i_I=pad, i_IB=pad_n) + + class _IOSERDESE2_8X(Module): def __init__(self, pad, pad_n=None): self.o = Signal(8) @@ -80,3 +106,10 @@ class Inout_8X(ttl_serdes_generic.Inout): serdes = _IOSERDESE2_8X(pad, pad_n) self.submodules += serdes ttl_serdes_generic.Inout.__init__(self, serdes) + + +class Input_8X(ttl_serdes_generic.Inout): + def __init__(self, pad, pad_n=None): + serdes = _ISERDESE2_8X(pad, pad_n) + self.submodules += serdes + ttl_serdes_generic.Inout.__init__(self, serdes) diff --git a/artiq/gateware/rtio/phy/ttl_simple.py b/artiq/gateware/rtio/phy/ttl_simple.py index 2192758df..85c03af6d 100644 --- a/artiq/gateware/rtio/phy/ttl_simple.py +++ b/artiq/gateware/rtio/phy/ttl_simple.py @@ -27,6 +27,43 @@ class Output(Module): ] +class Input(Module): + def __init__(self, pad): + self.rtlink = rtlink.Interface( + rtlink.OInterface(2, 2), + rtlink.IInterface(1)) + self.overrides = [] + self.probes = [] + + # # # + + sensitivity = Signal(2) + + sample = Signal() + self.sync.rio += [ + sample.eq(0), + If(self.rtlink.o.stb & self.rtlink.o.address[1], + sensitivity.eq(self.rtlink.o.data), + If(self.rtlink.o.address[0], sample.eq(1)) + ) + ] + + i = Signal() + i_d = Signal() + self.specials += MultiReg(pad, i, "rio_phy") + self.sync.rio_phy += i_d.eq(i) + self.comb += [ + self.rtlink.i.stb.eq( + sample | + (sensitivity[0] & ( i & ~i_d)) | + (sensitivity[1] & (~i & i_d)) + ), + self.rtlink.i.data.eq(i) + ] + + self.probes += [i] + + class Inout(Module): def __init__(self, pad): self.rtlink = rtlink.Interface( diff --git a/artiq/gateware/targets/kc705.py b/artiq/gateware/targets/kc705.py index 61d8d8df2..c88017349 100755 --- a/artiq/gateware/targets/kc705.py +++ b/artiq/gateware/targets/kc705.py @@ -10,15 +10,14 @@ from migen.build.xilinx.vivado import XilinxVivadoToolchain from migen.build.xilinx.ise import XilinxISEToolchain from misoc.interconnect.csr import * -from misoc.interconnect import wishbone from misoc.cores import gpio -from misoc.integration.soc_core import mem_decoder from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict from misoc.integration.builder import builder_args, builder_argdict from artiq.gateware.soc import AMPSoC, build_artiq_soc from artiq.gateware import rtio, nist_clock, nist_qc2 -from artiq.gateware.rtio.phy import ttl_simple, ttl_serdes_7series, dds, spi +from artiq.gateware.rtio.phy import (ttl_simple, ttl_serdes_7series, + dds, spi) from artiq import __version__ as artiq_version diff --git a/artiq/gateware/targets/phaser.py b/artiq/gateware/targets/phaser.py new file mode 100755 index 000000000..df383b40d --- /dev/null +++ b/artiq/gateware/targets/phaser.py @@ -0,0 +1,266 @@ +#!/usr/bin/env python3.5 + +import argparse + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from migen.genlib.cdc import MultiReg +from migen.genlib.io import DifferentialInput + +from jesd204b.common import (JESD204BTransportSettings, + JESD204BPhysicalSettings, + JESD204BSettings) +from jesd204b.phy.gtx import GTXQuadPLL +from jesd204b.phy import JESD204BPhyTX +from jesd204b.core import JESD204BCoreTX +from jesd204b.core import JESD204BCoreTXControl + +from misoc.interconnect.csr import * +from misoc.cores import gpio +from misoc.cores import spi as spi_csr +from misoc.targets.kc705 import MiniSoC, soc_kc705_args, soc_kc705_argdict +from misoc.integration.builder import builder_args, builder_argdict + +from artiq.gateware.soc import AMPSoC, build_artiq_soc +from artiq.gateware import rtio +from artiq.gateware.ad9154_fmc_ebz import ad9154_fmc_ebz +from artiq.gateware.rtio.phy import (ttl_simple, ttl_serdes_7series, + sawg) +from artiq import __version__ as artiq_version + + +class _PhaserCRG(Module, AutoCSR): + def __init__(self, platform, refclk): + self._clock_sel = CSRStorage() + self._pll_reset = CSRStorage(reset=1) + self._pll_locked = CSRStatus() + self.clock_domains.cd_rtio = ClockDomain() + self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True) + + pll_locked = Signal() + rtio_clk = Signal() + rtiox4_clk = Signal() + self.specials += [ + Instance("PLLE2_ADV", + p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, + + p_REF_JITTER1=0.01, p_REF_JITTER2=0.01, + p_CLKIN1_PERIOD=20/3, p_CLKIN2_PERIOD=20/3, + i_CLKIN1=0, i_CLKIN2=refclk, + # Warning: CLKINSEL=0 means CLKIN2 is selected + i_CLKINSEL=~self._clock_sel.storage, + + # VCO @ 1.2GHz when using 150MHz input + p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1, + i_CLKFBIN=self.cd_rtio.clk, + i_RST=self._pll_reset.storage, + + o_CLKFBOUT=rtio_clk, + + p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0, + o_CLKOUT0=rtiox4_clk, + ), + Instance("BUFG", i_I=rtio_clk, o_O=self.cd_rtio.clk), + Instance("BUFG", i_I=rtiox4_clk, o_O=self.cd_rtiox4.clk), + AsyncResetSynchronizer(self.cd_rtio, ~pll_locked), + MultiReg(pll_locked | ~self._clock_sel.storage, + self._pll_locked.status) + ] + self.cd_rtio.clk.attr.add("keep") + platform.add_period_constraint(self.cd_rtio.clk, 20/3) + + +class AD9154JESD(Module, AutoCSR): + def __init__(self, platform): + ps = JESD204BPhysicalSettings(l=4, m=4, n=16, np=16) + ts = JESD204BTransportSettings(f=2, s=1, k=16, cs=1) + settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5) + linerate = 6e9 + refclk_freq = 150e6 + fabric_freq = 150*1000*1000 + + sync_pads = platform.request("ad9154_sync") + self.jsync = Signal() + self.specials += DifferentialInput( + sync_pads.p, sync_pads.n, self.jsync) + + refclk = Signal() + self.clock_domains.cd_jesd = ClockDomain() + refclk_pads = platform.request("ad9154_refclk") + + self.specials += [ + Instance("IBUFDS_GTE2", i_CEB=0, + i_I=refclk_pads.p, i_IB=refclk_pads.n, o_O=refclk), + Instance("BUFG", i_I=refclk, o_O=self.cd_jesd.clk), + AsyncResetSynchronizer(self.cd_jesd, ResetSignal("rio_phy")), + ] + self.cd_jesd.clk.attr.add("keep") + platform.add_period_constraint(self.cd_jesd.clk, 1e9/refclk_freq) + + qpll = GTXQuadPLL(refclk, refclk_freq, linerate) + self.submodules += qpll + self.phys = [] + for i in range(4): + phy = JESD204BPhyTX( + qpll, platform.request("ad9154_jesd", i), fabric_freq) + phy.gtx.cd_tx.clk.attr.add("keep") + platform.add_period_constraint(phy.gtx.cd_tx.clk, 40*1e9/linerate) + platform.add_false_path_constraints(self.cd_jesd.clk, + phy.gtx.cd_tx.clk) + self.phys.append(phy) + to_jesd = ClockDomainsRenamer("jesd") + self.submodules.core = to_jesd(JESD204BCoreTX(self.phys, settings, + converter_data_width=32)) + self.submodules.control = to_jesd(JESD204BCoreTXControl(self.core)) + + self.comb += [ + platform.request("ad9154_txen", 0).eq(1), + platform.request("ad9154_txen", 1).eq(1), + self.core.start.eq(self.jsync), + platform.request("user_led", 3).eq(self.jsync), + ] + + # blinking leds for transceiver reset status + for i in range(4): + counter = Signal(max=fabric_freq) + self.comb += platform.request("user_led", 4 + i).eq(counter[-1]) + sync = getattr(self.sync, "phy{}_tx".format(i)) + sync += [ + counter.eq(counter - 1), + If(counter == 0, + counter.eq(fabric_freq - 1) + ) + ] + + +class AD9154(Module, AutoCSR): + def __init__(self, platform): + ad9154_spi = platform.request("ad9154_spi") + self.comb += ad9154_spi.en.eq(1) + + self.submodules.spi = spi_csr.SPIMaster(ad9154_spi) + + self.submodules.jesd = AD9154JESD(platform) + + self.sawgs = [sawg.Channel(width=16, parallelism=2) for i in range(4)] + self.submodules += self.sawgs + + for conv, ch in zip(self.jesd.core.sink.flatten(), self.sawgs): + self.sync.jesd += conv.eq(Cat(ch.o)) + + +class Phaser(MiniSoC, AMPSoC): + mem_map = { + "timer_kernel": 0x10000000, # (shadow @0x90000000) + "rtio": 0x20000000, # (shadow @0xa0000000) + "i2c": 0x30000000, # (shadow @0xb0000000) + "mailbox": 0x70000000, # (shadow @0xf0000000) + "ad9154": 0x50000000, + } + mem_map.update(MiniSoC.mem_map) + + def __init__(self, cpu_type="or1k", **kwargs): + MiniSoC.__init__(self, + cpu_type=cpu_type, + sdram_controller_type="minicon", + l2_size=128*1024, + with_timer=False, + ident=artiq_version, + **kwargs) + AMPSoC.__init__(self) + self.platform.toolchain.bitstream_commands.extend([ + "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", + ]) + + platform = self.platform + platform.add_extension(ad9154_fmc_ebz) + + self.submodules.leds = gpio.GPIOOut(Cat( + platform.request("user_led", 0), + platform.request("user_led", 1))) + self.csr_devices.append("leds") + + i2c = platform.request("i2c") + self.submodules.i2c = gpio.GPIOTristate([i2c.scl, i2c.sda]) + self.register_kernel_cpu_csrdevice("i2c") + self.config["I2C_BUS_COUNT"] = 1 + + self.submodules.ad9154 = AD9154(platform) + self.register_kernel_cpu_csrdevice("ad9154") + self.config["AD9154_DAC_CS"] = 1 << 0 + self.config["AD9154_CLK_CS"] = 1 << 1 + + rtio_channels = [] + + phy = ttl_serdes_7series.Inout_8X( + platform.request("user_sma_gpio_n")) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=128)) + + phy = ttl_simple.Output(platform.request("user_led", 2)) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy)) + + sysref_pads = platform.request("ad9154_sysref") + phy = ttl_serdes_7series.Input_8X(sysref_pads.p, sysref_pads.n) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32, + ofifo_depth=2)) + + phy = ttl_simple.Input(self.ad9154.jesd.jsync) + self.submodules += phy + rtio_channels.append(rtio.Channel.from_phy(phy, ififo_depth=32, + ofifo_depth=2)) + + self.config["RTIO_REGULAR_TTL_COUNT"] = len(rtio_channels) + + self.config["RTIO_FIRST_SAWG_CHANNEL"] = len(rtio_channels) + rtio_channels.extend(rtio.Channel.from_phy(phy) + for sawg in self.ad9154.sawgs + for phy in sawg.phys) + + self.config["RTIO_LOG_CHANNEL"] = len(rtio_channels) + rtio_channels.append(rtio.LogChannel()) + + self.config["RTIO_FIRST_DDS_CHANNEL"] = len(rtio_channels) + self.config["RTIO_DDS_COUNT"] = 1 + self.config["DDS_CHANNELS_PER_BUS"] = 1 + self.config["DDS_AD9914"] = None + self.config["DDS_ONEHOT_SEL"] = None + self.config["DDS_RTIO_CLK_RATIO"] = 8 + + self.submodules.rtio_crg = _PhaserCRG( + platform, self.ad9154.jesd.cd_jesd.clk) + self.csr_devices.append("rtio_crg") + self.submodules.rtio = rtio.RTIO(rtio_channels) + self.register_kernel_cpu_csrdevice("rtio") + self.submodules.rtio_moninj = rtio.MonInj(rtio_channels) + self.csr_devices.append("rtio_moninj") + self.submodules.rtio_analyzer = rtio.Analyzer( + self.rtio, self.get_native_sdram_if()) + self.csr_devices.append("rtio_analyzer") + + self.config["RTIO_FINE_TS_WIDTH"] = self.rtio.fine_ts_width + platform.add_false_path_constraints( + self.crg.cd_sys.clk, self.rtio_crg.cd_rtio.clk) + platform.add_false_path_constraints( + self.crg.cd_sys.clk, self.ad9154.jesd.cd_jesd.clk) + for phy in self.ad9154.jesd.phys: + platform.add_false_path_constraints( + self.crg.cd_sys.clk, phy.gtx.cd_tx.clk) + + +def main(): + parser = argparse.ArgumentParser( + description="ARTIQ core device builder for " + "KC705+AD9154 hardware") + builder_args(parser) + soc_kc705_args(parser) + args = parser.parse_args() + + soc = Phaser(**soc_kc705_argdict(args)) + build_artiq_soc(soc, builder_argdict(args)) + + +if __name__ == "__main__": + main() diff --git a/artiq/runtime.rs/libksupport/ad9154.rs b/artiq/runtime.rs/libksupport/ad9154.rs new file mode 100644 index 000000000..ab7026258 --- /dev/null +++ b/artiq/runtime.rs/libksupport/ad9154.rs @@ -0,0 +1,75 @@ +use board::csr; + +pub extern fn init() { + unsafe { + csr::ad9154::spi_offline_write(1); + csr::ad9154::spi_cs_polarity_write(0); + csr::ad9154::spi_clk_polarity_write(0); + csr::ad9154::spi_clk_phase_write(0); + csr::ad9154::spi_lsb_first_write(0); + csr::ad9154::spi_half_duplex_write(0); + csr::ad9154::spi_clk_div_write_write(16); + csr::ad9154::spi_clk_div_read_write(16); + csr::ad9154::spi_xfer_len_write_write(24); + csr::ad9154::spi_xfer_len_read_write(0); + csr::ad9154::spi_cs_write(csr::CONFIG_AD9154_DAC_CS); + csr::ad9154::spi_offline_write(0); + } +} + +const AD9_READ: u16 = 1 << 15; + +pub extern fn dac_write(addr: u16, data: u8) { + unsafe { + csr::ad9154::spi_data_write_write( + ((addr as u32) << 16) | ((data as u32) << 8)); + while csr::ad9154::spi_pending_read() != 0 {} + while csr::ad9154::spi_active_read() != 0 {} + } +} + +pub extern fn dac_read(addr: u16) -> u8 { + unsafe { + dac_write(AD9_READ | addr, 0); + csr::ad9154::spi_data_read_read() as u8 + } +} + +pub extern fn clk_write(addr: u16, data: u8) { + unsafe { + csr::ad9154::spi_cs_write(csr::CONFIG_AD9154_CLK_CS); + dac_write(addr, data); + csr::ad9154::spi_cs_write(csr::CONFIG_AD9154_DAC_CS); + } +} + +pub extern fn clk_read(addr: u16) -> u8 { + unsafe { + clk_write(AD9_READ | addr, 0); + csr::ad9154::spi_data_read_read() as u8 + } +} + +pub extern fn jesd_enable(en: u32) { + unsafe { + csr::ad9154::jesd_control_enable_write(en); + } +} + +pub extern fn jesd_ready() { + unsafe { + csr::ad9154::jesd_control_ready_read(); + } +} + +pub extern fn jesd_prbs(p: u32) { + unsafe { + csr::ad9154::jesd_control_prbs_config_write(p); + } +} + +pub extern fn jesd_stpl(en: u32) { + unsafe { + csr::ad9154::jesd_control_stpl_enable_write(en); + } +} diff --git a/artiq/runtime.rs/libksupport/api.rs b/artiq/runtime.rs/libksupport/api.rs index 00c6ccec1..20d9c21ed 100644 --- a/artiq/runtime.rs/libksupport/api.rs +++ b/artiq/runtime.rs/libksupport/api.rs @@ -116,4 +116,23 @@ static mut API: &'static [(&'static str, *const ())] = &[ api!(i2c_write = ::i2c::write), #[cfg(has_i2c)] api!(i2c_read = ::i2c::read), + + #[cfg(has_ad9154)] + api!(ad9154_init = ::ad9154::init), + #[cfg(has_ad9154)] + api!(ad9154_write = ::ad9154::dac_write), + #[cfg(has_ad9154)] + api!(ad9154_read = ::ad9154::dac_read), + #[cfg(has_ad9154)] + api!(ad9516_write = ::ad9154::clk_write), + #[cfg(has_ad9154)] + api!(ad9516_read = ::ad9154::clk_read), + #[cfg(has_ad9154)] + api!(ad9154_jesd_enable = ::ad9154::jesd_enable), + #[cfg(has_ad9154)] + api!(ad9154_jesd_ready = ::ad9154::jesd_ready), + #[cfg(has_ad9154)] + api!(ad9154_jesd_prbs = ::ad9154::jesd_prbs), + #[cfg(has_ad9154)] + api!(ad9154_jesd_stpl = ::ad9154::jesd_stpl), ]; diff --git a/artiq/runtime.rs/libksupport/lib.rs b/artiq/runtime.rs/libksupport/lib.rs index fdacdb08a..1843e3c31 100644 --- a/artiq/runtime.rs/libksupport/lib.rs +++ b/artiq/runtime.rs/libksupport/lib.rs @@ -52,6 +52,8 @@ macro_rules! artiq_raise { mod rtio; #[cfg(has_i2c)] mod i2c; +#[cfg(has_ad9154)] +mod ad9154; use core::{mem, ptr, slice, str}; use std::io::Cursor; diff --git a/artiq/test/gateware/fir.py b/artiq/test/gateware/fir.py new file mode 100644 index 000000000..f26047d0b --- /dev/null +++ b/artiq/test/gateware/fir.py @@ -0,0 +1,103 @@ +import numpy as np +import matplotlib.pyplot as plt + +from migen import * +from migen.fhdl import verilog +from artiq.gateware.dsp import fir + + +class Transfer(Module): + def __init__(self, dut): + self.submodules.dut = dut + + def drive(self, x): + for xi in x: + yield self.dut.i.eq(int(xi)) + yield + + def record(self, y): + for i in range(self.dut.latency): + yield + for i in range(len(y)): + yield + y[i] = (yield self.dut.o) + + def run(self, samples, amplitude=1.): + w = 2**(self.dut.width - 1) - 1 + x = np.round(np.random.uniform( + -amplitude*w, amplitude*w, samples)) + y = np.empty_like(x) + run_simulation(self, [self.drive(x), self.record(y)], + vcd_name="fir.vcd") + x /= w + y /= w + return x, y + + def analyze(self, x, y): + fig, ax = plt.subplots(3) + ax[0].plot(x, "c-.", label="input") + ax[0].plot(y, "r-", label="output") + ax[0].legend(loc="right") + ax[0].set_xlabel("time (1/fs)") + ax[0].set_ylabel("signal") + n = len(x) + w = np.hanning(n) + x = (x.reshape(-1, n)*w).sum(0) + y = (y.reshape(-1, n)*w).sum(0) + t = (np.fft.rfft(y)/np.fft.rfft(x)) + f = np.fft.rfftfreq(n)*2 + fmin = f[1] + ax[1].plot(f, 20*np.log10(np.abs(t)), "r-") + ax[1].set_ylim(-70, 3) + ax[1].set_xlim(fmin, 1.) + # ax[1].set_xscale("log") + ax[1].set_xlabel("frequency (fs/2)") + ax[1].set_ylabel("magnitude (dB)") + ax[1].grid(True) + ax[2].plot(f, np.rad2deg(np.angle(t)), "r-") + ax[2].set_xlim(fmin, 1.) + # ax[2].set_xscale("log") + ax[2].set_xlabel("frequency (fs/2)") + ax[2].set_ylabel("phase (deg)") + ax[2].grid(True) + return fig + + +class ParallelTransfer(Transfer): + def drive(self, x): + for xi in x.reshape(-1, self.dut.parallelism): + yield [ij.eq(int(xj)) for ij, xj in zip(self.dut.i, xi)] + yield + + def record(self, y): + for i in range(self.dut.latency): + yield + for yi in y.reshape(-1, self.dut.parallelism): + yield + yi[:] = (yield from [(yield o) for o in self.dut.o]) + + +def _main(): + coeff = fir.halfgen4(.4/2, 8) + coeff_int = [int(round(c * (1 << 16 - 1))) for c in coeff] + if False: + coeff = [[int(round((1 << 26) * ci)) for ci in c] + for c in fir.halfgen4_cascade(8, width=.4, order=8)] + dut = fir.ParallelHBFUpsampler(coeff, width=16, shift=25) + print(verilog.convert(dut, ios=set([dut.i] + dut.o))) + elif True: + dut = fir.ParallelFIR(coeff_int, parallelism=4, width=16) + # print(verilog.convert(dut, ios=set(dut.i + dut.o))) + tb = ParallelTransfer(dut) + else: + dut = fir.FIR(coeff_int, width=16) + # print(verilog.convert(dut, ios={dut.i, dut.o})) + tb = Transfer(dut) + + x, y = tb.run(samples=1 << 10, amplitude=.8) + tb.analyze(x, y) + plt.show() + + +if __name__ == "__main__": + _main() diff --git a/artiq/test/gateware/test_accu.py b/artiq/test/gateware/test_accu.py new file mode 100644 index 000000000..384fba9cc --- /dev/null +++ b/artiq/test/gateware/test_accu.py @@ -0,0 +1,46 @@ +import numpy as np + +from migen import * +from migen.fhdl.verilog import convert + +from artiq.gateware.dsp.accu import Accu, PhasedAccu +from .tools import xfer + + +def read(o, n): + p = [] + for i in range(n): + p.append((yield from [(yield pi) for pi in o.payload.flatten()])) + yield + return p + + +def _test_gen_accu(dut, o): + yield dut.o.ack.eq(1) + yield from xfer(dut, i=dict(p=0, f=1, clr=1)) + o.extend((yield from read(dut.o, 8))) + yield from xfer(dut, i=dict(p=0, f=2, clr=0)) + o.extend((yield from read(dut.o, 8))) + yield from xfer(dut, i=dict(p=0, f=2, clr=1)) + o.extend((yield from read(dut.o, 8))) + yield from xfer(dut, i=dict(p=8, f=-1, clr=1)) + o.extend((yield from read(dut.o, 8))) + yield from xfer(dut, i=dict(p=0, f=0, clr=1)) + yield from xfer(dut, i=dict(p=1, f=0, clr=0)) + o.extend((yield from read(dut.o, 8))) + + +def _test_accu(): + dut = PhasedAccu(8, parallelism=8) + + if False: + print(convert(dut)) + else: + o = [] + run_simulation(dut, _test_gen_accu(dut, o), vcd_name="accu.vcd") + o = np.array(o) + print(o) + + +if __name__ == "__main__": + _test_accu() diff --git a/artiq/test/gateware/test_sawg.py b/artiq/test/gateware/test_sawg.py new file mode 100644 index 000000000..a5eea31bd --- /dev/null +++ b/artiq/test/gateware/test_sawg.py @@ -0,0 +1,36 @@ +import numpy as np + +from migen import * +from migen.fhdl.verilog import convert + +from artiq.gateware.dsp import sawg +from .tools import xfer + + +def _test_gen_dds(dut, o): + yield from xfer(dut, + a=dict(a0=10), + p=dict(a0=0), + f=dict(a0=1), + ) + for i in range(256//dut.parallelism): + yield + o.append((yield from [(yield _) for _ in dut.xo])) + + +def _test_channel(): + widths = sawg._Widths(t=8, a=4*8, p=8, f=16) + orders = sawg._Orders(a=4, p=1, f=2) + dut = sawg.SplineParallelDDS(widths, orders, parallelism=2) + + if False: + print(convert(dut)) + else: + o = [] + run_simulation(dut, _test_gen_dds(dut, o), vcd_name="dds.vcd") + o = np.array(o) + print(o[:, :]) + + +if __name__ == "__main__": + _test_channel() diff --git a/artiq/test/gateware/test_sawg_fe.py b/artiq/test/gateware/test_sawg_fe.py new file mode 100644 index 000000000..34a850c62 --- /dev/null +++ b/artiq/test/gateware/test_sawg_fe.py @@ -0,0 +1,225 @@ +import unittest + +import migen as mg +from numpy import int32 + +from artiq.coredevice import sawg, spline +from artiq.language import (at_mu, now_mu, delay, + core as core_language) +from artiq.gateware.rtio.phy.sawg import Channel +from artiq.sim import devices as sim_devices, time as sim_time + + +class RTIOManager: + def __init__(self): + self.outputs = [] + + def rtio_output(self, now, channel, addr, data): + self.outputs.append((now, channel, addr, data)) + + def rtio_output_wide(self, *args, **kwargs): + self.rtio_output(*args, **kwargs) + + def patch(self, mod): + assert not hasattr(mod, "_saved") + mod._saved = {} + for name in "rtio_output rtio_output_wide".split(): + mod._saved[name] = getattr(mod, name, None) + setattr(mod, name, getattr(self, name)) + + def unpatch(self, mod): + mod.__dict__.update(mod._saved) + del mod._saved + + +class SAWGTest(unittest.TestCase): + def setUp(self): + core_language.set_time_manager(sim_time.Manager()) + self.rtio_manager = RTIOManager() + self.rtio_manager.patch(spline) + self.core = sim_devices.Core({}) + self.core.coarse_ref_period = 6.66666 + self.t = self.core.coarse_ref_period + self.channel = mg.ClockDomainsRenamer({"rio_phy": "sys"})( + Channel(width=16, parallelism=2)) + self.driver = sawg.SAWG({"core": self.core}, channel_base=0, + parallelism=self.channel.parallelism) + + def tearDown(self): + self.rtio_manager.unpatch(spline) + + def test_instantiate(self): + pass + + def test_make_events(self): + d = self.driver + d.offset.set(.9) + delay(2*self.t) + d.frequency0.set(.1) + d.frequency1.set(.1) + delay(2*self.t) + d.offset.set(0) + v = int(round((1 << 48) * .1 * self.t)) + self.assertEqual( + self.rtio_manager.outputs, [ + (0., 1, 0, int(round( + (1 << self.driver.offset.width - 1)*.9))), + (2.*self.t, 8, 0, int(round( + (1 << self.driver.frequency0.width) * + self.t/self.channel.parallelism*.1))), + (2.*self.t, 3, 0, [int32(v), int32(v >> 32)]), + (4.*self.t, 1, 0, 0), + ]) + + def run_channel(self, events): + def gen(dut, events): + c = 0 + for time, channel, address, data in events: + time //= self.t + assert c <= time + while c < time: + yield + c += 1 + for phy in dut.phys: + yield phy.rtlink.o.stb.eq(0) + rt = dut.phys[channel].rtlink.o + if isinstance(data, list): + data = sum(int(d) << (i*32) for i, d in enumerate(data)) + yield rt.data.eq(int(data)) + yield rt.stb.eq(1) + assert not (yield rt.busy) + # print("{}: set ch {} to {}".format(time, channel, hex(data))) + + def log(dut, data, n): + for i in range(dut.latency): + yield + for i in range(n): + yield + data.append((yield from [(yield _) for _ in dut.o])) + + data = [] + # print(int(events[-1][0]) + 1) + mg.run_simulation(self.channel, [ + gen(self.channel, events), + log(self.channel, data, int(events[-1][0]//self.t) + 1)], + vcd_name="dds.vcd") + return data + + def test_run_channel(self): + self.test_make_events() + self.run_channel(self.rtio_manager.outputs) + + def test_coeff(self): + import struct + # these get discrete_compensate + # [.1, .01, -.00001], [.1, .01, .00001, -.000000001] + for v in [-.1], [.1, -.01]: + ch = self.driver.offset + p = ch.coeff_as_packed(v) + t = ch.time_width + w = ch.width + p = [_ & 0xffffffff for _ in p] + p0 = [int(round(vi*ch.scale*ch.time_scale**i)) + for i, vi in enumerate(v)] + p0 = [struct.pack("<" + "_bhiiqqqq"[(w + i*t)//8], vi + )[:(w + i*t)//8] + for i, vi in enumerate(p0)] + p0 = b"".join(p0) + if len(p0) % 4: + p0 += b"\x00"*(4 - len(p0) % 4) + p0 = list(struct.unpack("<" + "I"*((len(p0) + 3)//4), p0)) + with self.subTest(v): + self.assertEqual(p, p0) + + def test_linear(self): + d = self.driver + d.offset.set_coeff_mu([100, 10]) + delay(10*self.t) + d.offset.set_coeff([0]) + delay(1*self.t) + out = self.run_channel(self.rtio_manager.outputs) + for i in range(len(out) - 1): + with self.subTest(i): + v = 100 + i*10 + self.assertEqual(out[i], [v, v]) + self.assertEqual(out[-1], [0, 0]) + + def test_pack(self): + ch = self.driver.offset + self.assertEqual(ch.coeff_as_packed_mu([1]), [1]) + self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 16]), [1, 1]) + self.assertEqual(ch.coeff_as_packed_mu([1, 1 << 32]), [1, 0]) + self.assertEqual(ch.coeff_as_packed_mu([0x1234, 0xa5a5a5a5]), + [0xa5a51234, 0xa5a5]) + self.assertEqual(ch.coeff_as_packed_mu([1, 2, 3, 4]), + [0x20001, 0x30000, 0, 4, 0]) + self.assertEqual(ch.coeff_as_packed_mu([-1, -2, -3, -4]), + [0xfffeffff, 0xfffdffff, -1, -4, -1]) + self.assertEqual(ch.coeff_as_packed_mu([0, -1, 0, -1]), + [0xffff0000, 0x0000ffff, 0, -1, -1]) + + def test_smooth_linear(self): + ch = self.driver.offset + ch.smooth(.1, .2, 13*self.t, 1) + ch.set(.2) + delay(1*self.t) + out = self.run_channel(self.rtio_manager.outputs) + a = int(round(.1*ch.scale)) + da = int(round(.1*ch.scale*(1 << ch.width)//13)) + for i in range(len(out) - 1): + with self.subTest(i): + v = a + (i*da >> ch.width) + self.assertEqual(out[i], [v, v]) + a = int(round(.2*ch.scale)) + self.assertEqual(out[-1], [a, a]) + + def test_smooth_cubic(self): + ch = self.driver.offset + ch.smooth(.1, .2, 13, 3) + ch.set(.2) + delay(1*self.t) + out = self.run_channel(self.rtio_manager.outputs) + out = sum(out, []) + if False: + import matplotlib.pyplot as plt + plt.plot(out) + plt.show() + + @unittest.skip("needs artiq.sim.time.TimeManager tweak for " + "reverse timeline jumps") + def test_demo_2tone(self): + MHz = 1e-3 + ns = 1. + self.sawg0 = self.driver + + t_up = t_hold = t_down = 400*ns + a1 = .3 + a2 = .4 + order = 3 + + self.sawg0.frequency0.set(10*MHz) + self.sawg0.phase0.set(0.) + self.sawg0.frequency1.set(1*MHz) + self.sawg0.phase1.set(0.) + self.sawg0.frequency2.set(13*MHz) + self.sawg0.phase2.set(0.) + t = now_mu() + self.sawg0.amplitude1.smooth(.0, a1, t_up, order) + at_mu(t) + self.sawg0.amplitude2.smooth(.0, a2, t_up, order) + self.sawg0.amplitude1.set(a1) + self.sawg0.amplitude2.set(a2) + delay(t_hold) + t = now_mu() + self.sawg0.amplitude1.smooth(a1, .0, t_down, order) + at_mu(t) + self.sawg0.amplitude2.smooth(a2, .0, t_down, order) + self.sawg0.amplitude1.set(.0) + self.sawg0.amplitude2.set(.0) + + out = self.run_channel(self.rtio_manager.outputs) + out = sum(out, []) + if True: + import matplotlib.pyplot as plt + plt.plot(out) + plt.show() diff --git a/artiq/test/gateware/test_sawg_phy.py b/artiq/test/gateware/test_sawg_phy.py new file mode 100644 index 000000000..35666a5f6 --- /dev/null +++ b/artiq/test/gateware/test_sawg_phy.py @@ -0,0 +1,70 @@ +import numpy as np +from operator import or_ + +from migen import * +from migen.fhdl.verilog import convert + +from artiq.gateware.rtio.phy.sawg import Channel +from .tools import rtio_xfer + + +def pack_tri(port, *v): + r = 0 + w = 0 + for vi, p in zip(v, port.payload.flatten()): + w += len(p) + r |= int(vi*(1 << w)) + return r + + +def gen_rtio(dut): + yield + yield from rtio_xfer( + dut, + a1=pack_tri(dut.a1.a, .1), + f0=pack_tri(dut.b.f, .01234567), + f1=pack_tri(dut.a1.f, .01234567), + a2=pack_tri(dut.a1.a, .05), + f2=pack_tri(dut.a1.f, .00534567), + ) + + +def gen_log(dut, o, n): + for i in range(3 + dut.latency): + yield + for i in range(n): + yield + o.append((yield from [(yield _) for _ in dut.o])) + #o.append([(yield dut.a1.xo[0])]) + + +def _test_channel(): + width = 16 + + dut = ClockDomainsRenamer({"rio_phy": "sys"})( + Channel(width=width, parallelism=4) + ) + + if False: + print(convert(dut)) + return + + o = [] + run_simulation( + dut, + [gen_rtio(dut), gen_log(dut, o, 128)], + vcd_name="dds.vcd") + o = np.array(o)/(1 << (width - 1)) + o = o.ravel() + np.savez_compressed("dds.npz", o=o) + + import matplotlib.pyplot as plt + fig, ax = plt.subplots(2) + ax[0].step(np.arange(o.size), o) + ax[1].psd(o, 1 << 10, Fs=1, noverlap=1 << 9, scale_by_freq=False) + fig.savefig("dds.pdf") + plt.show() + + +if __name__ == "__main__": + _test_channel() diff --git a/artiq/test/gateware/test_spline.py b/artiq/test/gateware/test_spline.py new file mode 100644 index 000000000..fe2d82c28 --- /dev/null +++ b/artiq/test/gateware/test_spline.py @@ -0,0 +1,31 @@ +import numpy as np + +from migen import * +from migen.fhdl.verilog import convert + +from artiq.gateware.dsp.spline import Spline +from .tools import xfer + + +def _test_gen_spline(dut, o): + yield dut.o.ack.eq(1) + yield from xfer(dut, i=dict(a0=0, a1=1, a2=2)) + for i in range(20): + yield + o.append((yield dut.o.a0)) + + +def _test_spline(): + dut = Spline(order=3, width=16, step=1) + + if False: + print(convert(dut)) + else: + o = [] + run_simulation(dut, _test_gen_spline(dut, o), vcd_name="spline.vcd") + o = np.array(o) + print(o) + + +if __name__ == "__main__": + _test_spline() diff --git a/artiq/test/gateware/tools.py b/artiq/test/gateware/tools.py new file mode 100644 index 000000000..8d22ad475 --- /dev/null +++ b/artiq/test/gateware/tools.py @@ -0,0 +1,49 @@ +def set_dict(e, **k): + for k, v in k.items(): + if isinstance(v, dict): + yield from set_dict(getattr(e, k), **v) + else: + yield getattr(e, k).eq(v) + + +def xfer(dut, **kw): + ep = [] + for e, v in kw.items(): + e = getattr(dut, e) + yield from set_dict(e, **v) + ep.append(e) + for e in ep: + yield e.stb.eq(1) + while ep: + yield + for e in ep[:]: + if hasattr(e, "busy") and (yield e.busy): + raise ValueError(e, "busy") + if not hasattr(e, "ack") or (yield e.ack): + yield e.stb.eq(0) + ep.remove(e) + + +def szip(*iters): + active = {it: None for it in iters} + while active: + for it in list(active): + while True: + try: + val = it.send(active[it]) + except StopIteration: + del active[it] + break + if val is None: + break + else: + active[it] = (yield val) + val = (yield None) + for it in active: + active[it] = val + + +def rtio_xfer(dut, **kwargs): + yield from szip(*( + xfer(dut.phys_named[k].rtlink, o={"data": v}) + for k, v in kwargs.items())) diff --git a/conda/artiq-kc705-phaser/build.sh b/conda/artiq-kc705-phaser/build.sh new file mode 100644 index 000000000..64625afc2 --- /dev/null +++ b/conda/artiq-kc705-phaser/build.sh @@ -0,0 +1,14 @@ +#!/bin/bash + +BUILD_SETTINGS_FILE=$HOME/.m-labs/build_settings.sh +[ -f $BUILD_SETTINGS_FILE ] && . $BUILD_SETTINGS_FILE + +SOC_PREFIX=$PREFIX/lib/python3.5/site-packages/artiq/binaries/kc705-phaser +mkdir -p $SOC_PREFIX + +$PYTHON -m artiq.gateware.targets.phaser --toolchain vivado $MISOC_EXTRA_VIVADO_CMDLINE +cp misoc_phaser_kc705/gateware/top.bit $SOC_PREFIX +cp misoc_phaser_kc705/software/bios/bios.bin $SOC_PREFIX +cp misoc_phaser_kc705/software/runtime/runtime.fbi $SOC_PREFIX + +wget -P $SOC_PREFIX https://raw.githubusercontent.com/jordens/bscan_spi_bitstreams/master/bscan_spi_xc7k325t.bit diff --git a/conda/artiq-kc705-phaser/meta.yaml b/conda/artiq-kc705-phaser/meta.yaml new file mode 100644 index 000000000..e843ec666 --- /dev/null +++ b/conda/artiq-kc705-phaser/meta.yaml @@ -0,0 +1,29 @@ +package: + name: artiq-kc705-phaser + version: {{ environ.get("GIT_DESCRIBE_TAG", "") }} + +source: + git_url: ../.. + +build: + noarch_python: true + number: {{ environ.get("GIT_DESCRIBE_NUMBER", 0) }} + string: py_{{ environ.get("GIT_DESCRIBE_NUMBER", 0) }}+git{{ environ.get("GIT_DESCRIBE_HASH", "")[1:] }} + +requirements: + build: + - migen 0.5.dev + - misoc 0.5.dev + - jesd204b 0.2 + - llvm-or1k + - binutils-or1k-linux >=2.27 + - rust-core-or1k + - cargo + - numpy + run: + - artiq {{ "{tag} py_{number}+git{hash}".format(tag=environ.get("GIT_DESCRIBE_TAG"), number=environ.get("GIT_DESCRIBE_NUMBER"), hash=environ.get("GIT_DESCRIBE_HASH")[1:]) if "GIT_DESCRIBE_TAG" in environ else "" }} + +about: + home: https://m-labs.hk/artiq + license: GPL + summary: 'Bitstream, BIOS and runtime for Phaser on the KC705 board' diff --git a/doc/manual/core_device.rst b/doc/manual/core_device.rst index e70b30f11..b765d2c0c 100644 --- a/doc/manual/core_device.rst +++ b/doc/manual/core_device.rst @@ -130,6 +130,30 @@ To avoid I/O contention, the startup kernel should first program the TCA6424A ex See :mod:`artiq.coredevice.i2c` for more details. + +Phaser +++++++ + +The Phaser adapter is an AD9154-FMC-EBZ, a 4 channel 2.4 GHz DAC on an FMC HPC card. + ++--------------+------------+--------------+ +| RTIO channel | TTL line | Capability | ++==============+============+==============+ +| 0 | SMA_GPIO_N | Input+Output | ++--------------+------------+--------------+ +| 1 | LED | Output | ++--------------+------------+--------------+ +| 2 | SYSREF | Input | ++--------------+------------+--------------+ +| 3 | SYNC | Input | ++--------------+------------+--------------+ + +The SAWG channels start with RTIO channel number 4, each occupying 3 channels. + +The board has one non-RTIO SPI bus that is accessible through +:mod:`artiq.coredevice.ad9154`. + + Pipistrello ----------- diff --git a/doc/manual/core_drivers_reference.rst b/doc/manual/core_drivers_reference.rst index 9895b04f7..fdd467879 100644 --- a/doc/manual/core_drivers_reference.rst +++ b/doc/manual/core_drivers_reference.rst @@ -10,7 +10,7 @@ These drivers are for the core device and the peripherals closely integrated int :members: :mod:`artiq.coredevice.ttl` module ------------------------------------ +---------------------------------- .. automodule:: artiq.coredevice.ttl :members: @@ -43,7 +43,7 @@ These drivers are for the core device and the peripherals closely integrated int :members: :mod:`artiq.coredevice.cache` module ------------------------------------------ +------------------------------------ .. automodule:: artiq.coredevice.cache :members: @@ -53,3 +53,21 @@ These drivers are for the core device and the peripherals closely integrated int .. automodule:: artiq.coredevice.exceptions :members: + +:mod:`artiq.coredevice.spline` module +------------------------------------- + +.. automodule:: artiq.coredevice.spline + :members: + +:mod:`artiq.coredevice.sawg` module +----------------------------------- + +.. automodule:: artiq.coredevice.sawg + :members: + +:mod:`artiq.coredevice.ad9154` module +------------------------------------- + +.. automodule:: artiq.coredevice.ad9154 + :members: diff --git a/doc/manual/installing.rst b/doc/manual/installing.rst index 3d9761944..948bf8c49 100644 --- a/doc/manual/installing.rst +++ b/doc/manual/installing.rst @@ -141,6 +141,7 @@ Then, you can flash the board: For the KC705, the next step is to flash the MAC and IP addresses to the board. See :ref:`those instructions `. +.. _configuring-core-device: Configuring the core device ---------------------------