Merge branch 'phaser2-rust-init'

This commit is contained in:
Sebastien Bourdeauducq 2017-01-03 21:31:21 +01:00
commit fbf5a4d4a2
19 changed files with 75 additions and 3984 deletions

View File

@ -1,7 +1,7 @@
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.
ARTIQ 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*:
@ -15,13 +15,13 @@ Ultimately it will be the basis for the ARTIQ Sayma Smart Arbitrary Waveform Gen
* 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.
The hardware required 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
* In ARTIQ, the SAWG and Phaser code: https://github.com/m-labs/artiq
* The Migen/MiSoC JESD204B core: https://github.com/m-labs/jesd204b
@ -49,11 +49,11 @@ https://m-labs.hk/artiq/manual-master/index.html
- binutils-or1k-linux
* Install a recent version of Vivado (tested and developed with 2016.2).
* Do a checkout of the ARTIQ phaser2 branch: ::
* Do a checkout of ARTIQ: ::
mkdir ~/src
cd ~/src
git clone --recursive -b phaser2 https://github.com/m-labs/artiq.git
git clone --recursive https://github.com/m-labs/artiq.git
cd ../artiq
python setup.py develop
@ -89,29 +89,19 @@ Setup
* 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.
The RTIO clock, DAC deviceclock, FPGA deviceclock, and SYSREF are derived from this signal.
* 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).

View File

@ -1,106 +0,0 @@
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)

File diff suppressed because it is too large Load Diff

View File

@ -1,291 +0,0 @@
# = 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

View File

@ -12,8 +12,7 @@
"module": "artiq.coredevice.core",
"class": "Core",
"arguments": {
"ref_period": 5e-9/6,
"external_clock": True
"ref_period": 5e-9/6
}
},
"core_cache": {
@ -21,11 +20,6 @@
"module": "artiq.coredevice.cache",
"class": "CoreCache"
},
"ad9154": {
"type": "local",
"module": "artiq.coredevice.ad9154",
"class": "AD9154"
},
"ttl_sma": {
"type": "local",
"module": "artiq.coredevice.ttl",
@ -44,34 +38,28 @@
"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}
"arguments": {"channel_base": 3, "parallelism": 2}
},
"sawg1": {
"type": "local",
"module": "artiq.coredevice.sawg",
"class": "SAWG",
"arguments": {"channel_base": 14, "parallelism": 2}
"arguments": {"channel_base": 13, "parallelism": 2}
},
"sawg2": {
"type": "local",
"module": "artiq.coredevice.sawg",
"class": "SAWG",
"arguments": {"channel_base": 24, "parallelism": 2}
"arguments": {"channel_base": 23, "parallelism": 2}
},
"sawg3": {
"type": "local",
"module": "artiq.coredevice.sawg",
"class": "SAWG",
"arguments": {"channel_base": 34, "parallelism": 2}
"arguments": {"channel_base": 33, "parallelism": 2}
}
}

View File

@ -1,362 +0,0 @@
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 least 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)

View File

@ -14,7 +14,7 @@ class SAWGTest(EnvExperiment):
@kernel
def run(self):
self.core.break_realtime()
self.core.reset()
self.ttl_sma.output()
while True:

View File

@ -14,7 +14,7 @@ class SAWGTest(EnvExperiment):
@kernel
def run(self):
self.core.break_realtime()
self.core.reset()
self.ttl_sma.output()
while True:

View File

@ -1,3 +1,5 @@
# TODO: move to firmware
from artiq.coredevice.ad9154_reg import *
from artiq.experiment import *

View File

@ -1,3 +1,5 @@
# TODO: move to firmware
from artiq.coredevice.ad9154_reg import *
from artiq.experiment import *

View File

@ -1,3 +1,5 @@
# TODO: move to firmware
from jesd204b.transport import seed_to_data
from artiq.coredevice.ad9154_reg import *

View File

@ -1,72 +0,0 @@
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.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)

View File

@ -35,6 +35,12 @@ fn read(addr: u16) -> u8 {
}
}
fn jesd_reset(rst: bool) {
unsafe {
csr::ad9154::jesd_jreset_write(if rst {1} else {0})
}
}
fn jesd_enable(en: bool) {
unsafe {
csr::ad9154::jesd_control_enable_write(if en {1} else {0})
@ -454,6 +460,10 @@ fn cfg() -> Result<(), &'static str> {
pub fn init() -> Result<(), &'static str> {
spi_setup();
// Release the JESD clock domain reset late, as we need to
// set up clock chips before.
jesd_reset(false);
for i in 0..99 {
let outcome = cfg();
match outcome {

View File

@ -11,6 +11,16 @@ include!(concat!(env!("BUILDINC_DIRECTORY"), "/generated/csr.rs"));
pub mod spr;
pub mod irq;
pub mod clock;
// XXX #[cfg(has_ad9516)]
#[allow(dead_code)]
mod ad9516_reg;
// XXX #[cfg(has_ad9516)]
pub mod ad9516;
// XXX #[cfg(has_converter_spi)]
#[allow(dead_code)]
mod ad9154_reg;
// XXX #[cfg(has_converter_spi)]
pub mod ad9154;
extern {
pub fn flush_cpu_dcache();

View File

@ -1,75 +0,0 @@
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);
}
}

View File

@ -116,23 +116,4 @@ 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),
];

View File

@ -50,8 +50,6 @@ 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;

View File

@ -118,6 +118,10 @@ pub unsafe extern fn rust_main() {
}
info!("continuing boot");
#[cfg(has_ad9516)]
board::ad9516::init().unwrap();
#[cfg(has_converter_spi)]
board::ad9154::init().unwrap();
network_init();
let mut scheduler = sched::Scheduler::new();

View File

@ -37,6 +37,13 @@ class _PhaserCRG(Module, AutoCSR):
self.clock_domains.cd_rtio = ClockDomain()
self.clock_domains.cd_rtiox4 = ClockDomain(reset_less=True)
external_clk = Signal()
user_sma_clock = platform.request("user_sma_clock")
platform.add_period_constraint(user_sma_clock.p, 20/3)
self.specials += Instance("IBUFDS",
i_I=user_sma_clock.p, i_IB=user_sma_clock.n,
o_O=external_clk)
pll_locked = Signal()
rtio_clk = Signal()
rtiox4_clk = Signal()
@ -46,7 +53,7 @@ class _PhaserCRG(Module, AutoCSR):
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,
i_CLKIN1=refclk, i_CLKIN2=external_clk,
# Warning: CLKINSEL=0 means CLKIN2 is selected
i_CLKINSEL=~self._clock_sel.storage,
@ -58,13 +65,11 @@ class _PhaserCRG(Module, AutoCSR):
o_CLKFBOUT=rtio_clk,
p_CLKOUT0_DIVIDE=2, p_CLKOUT0_PHASE=0.0,
o_CLKOUT0=rtiox4_clk,
),
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)
MultiReg(pll_locked, self._pll_locked.status)
]
self.cd_rtio.clk.attr.add("keep")
platform.add_period_constraint(self.cd_rtio.clk, 20/3)
@ -72,6 +77,9 @@ class _PhaserCRG(Module, AutoCSR):
class AD9154JESD(Module, AutoCSR):
def __init__(self, platform):
self.jreset = CSRStorage(reset=1)
self.jsync = CSRStatus()
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)
@ -79,11 +87,6 @@ class AD9154JESD(Module, AutoCSR):
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")
@ -92,7 +95,7 @@ class AD9154JESD(Module, AutoCSR):
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")),
AsyncResetSynchronizer(self.cd_jesd, self.jreset.storage),
]
self.cd_jesd.clk.attr.add("keep")
platform.add_period_constraint(self.cd_jesd.clk, 1e9/refclk_freq)
@ -113,11 +116,18 @@ class AD9154JESD(Module, AutoCSR):
converter_data_width=32))
self.submodules.control = to_jesd(JESD204BCoreTXControl(self.core))
sync_pads = platform.request("ad9154_sync")
jsync = Signal()
self.specials += [
DifferentialInput(sync_pads.p, sync_pads.n, jsync),
MultiReg(jsync, self.jsync.status)
]
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),
self.core.start.eq(jsync),
platform.request("user_led", 3).eq(jsync),
]
# blinking leds for transceiver reset status
@ -135,11 +145,6 @@ class AD9154JESD(Module, AutoCSR):
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)]
@ -186,10 +191,16 @@ class Phaser(MiniSoC, AMPSoC):
self.register_kernel_cpu_csrdevice("i2c")
self.config["I2C_BUS_COUNT"] = 1
ad9154_spi = platform.request("ad9154_spi")
self.comb += ad9154_spi.en.eq(1)
self.submodules.converter_spi = spi_csr.SPIMaster(ad9154_spi)
self.csr_devices.append("converter_spi")
self.config["CONVERTER_SPI_DAC_CS"] = 0
self.config["CONVERTER_SPI_CLK_CS"] = 1
self.config["HAS_AD9516"] = None
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
self.csr_devices.append("ad9154")
rtio_channels = []
@ -208,11 +219,6 @@ class Phaser(MiniSoC, AMPSoC):
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)