forked from M-Labs/artiq
1
0
Fork 0

phaser: 300 MHz sample rate clock/dac

This commit is contained in:
Robert Jördens 2016-11-21 16:58:07 +01:00
parent b3e4a1df03
commit ad264ac070
3 changed files with 20 additions and 24 deletions

View File

@ -7,16 +7,16 @@ Ultimately it will be the basis for the ARTIQ Sayma Smart Arbitrary Waveform Gen
*Features*: *Features*:
* 4 channels * up to 4 channels
* 500 MHz data rate per channel (KC705 limitation) * up to 500 MHz data rate per channel (KC705 limitation)
* 4x interpolation to 2 GHz DAC sample rate * up to 8x interpolation to 2.4 GHz DAC sample rate
* Real-time control over amplitude, frequency, phase of each channel through ARTIQ RTIO commands * Real-time 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 * Full configurability of the AD9154 and AD9516 through SPI with ARTIQ kernel support
* All SPI registers and register bits exposed as human readable names * All SPI registers and register bits exposed as human readable names
* Parametrized JESD204B core (also capable of operation with eight lanes) * 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 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 2 GHz reference clock. 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. This work was supported by the Army Research Lab.
@ -90,7 +90,7 @@ Setup
* Refer to the ARTIQ documentation to configure an IP address and other settings for the transmitter device. * 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. If the board was running stock ARTIQ before, the settings will be kept.
* A 2 GHz 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. * 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. The external 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/``. :: * An example device database, several status and test scripts are provided in ``artiq/examples/phaser/``. ::
@ -113,7 +113,7 @@ Usage
* Run ``artiq_run repository/demo.py`` for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates. * 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. for an example that exercises several different use cases of synchronized phase, amplitude, and frequency updates.
* Implement your own experiments using the SAWG channels. * Implement your own experiments using the SAWG channels.
* Verify clock stability between the 2 GHz reference clock and the DAC outputs. * 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. * Changes to the AD9154 configuration can also be performed at runtime in experiments.
See the example ``dac_setup.py``. 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). 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

@ -19,10 +19,10 @@ ts = JESD204BTransportSettings(
) )
jesd_settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5) jesd_settings = JESD204BSettings(ps, ts, did=0x5a, bid=0x5)
jesd_checksum = jesd_settings.get_configuration_checksum() jesd_checksum = jesd_settings.get_configuration_checksum()
# external clk=2000MHz # external clk=300MHz
# pclock=250MHz # pclock=150MHz
# deviceclock_fpga=250MHz # deviceclock_fpga=150MHz
# deviceclock_dac=2000MHz # deviceclock_dac=300MHz
class DACSetup(EnvExperiment): class DACSetup(EnvExperiment):
@ -123,7 +123,7 @@ class DACSetup(EnvExperiment):
self.ad9154.dac_write(AD9154_SPI_PAGEINDX, 0x3) # A and B dual self.ad9154.dac_write(AD9154_SPI_PAGEINDX, 0x3) # A and B dual
self.ad9154.dac_write(AD9154_INTERP_MODE, 3) # 4x self.ad9154.dac_write(AD9154_INTERP_MODE, 0) # 1x
self.ad9154.dac_write(AD9154_MIX_MODE, 0) 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_DATA_FORMAT, AD9154_BINARY_FORMAT_SET(0)) # s16
self.ad9154.dac_write(AD9154_DATAPATH_CTRL, self.ad9154.dac_write(AD9154_DATAPATH_CTRL,

View File

@ -28,10 +28,10 @@ class StartupKernel(EnvExperiment):
if self.ad9154.clock_read(AD9516_PART_ID) != 0x41: if self.ad9154.clock_read(AD9516_PART_ID) != 0x41:
raise ValueError("AD9516 not found") raise ValueError("AD9516 not found")
# use clk input, dclk=clk/4 # use clk input, dclk=clk/2
self.ad9154.clock_write(AD9516_PFD_AND_CHARGE_PUMP, 1*AD9516_PLL_POWER_DOWN | self.ad9154.clock_write(AD9516_PFD_AND_CHARGE_PUMP, 1*AD9516_PLL_POWER_DOWN |
0*AD9516_CHARGE_PUMP_MODE) 0*AD9516_CHARGE_PUMP_MODE)
self.ad9154.clock_write(AD9516_VCO_DIVIDER, 2) self.ad9154.clock_write(AD9516_VCO_DIVIDER, 0)
self.ad9154.clock_write(AD9516_INPUT_CLKS, 0*AD9516_SELECT_VCO_OR_CLK | self.ad9154.clock_write(AD9516_INPUT_CLKS, 0*AD9516_SELECT_VCO_OR_CLK |
0*AD9516_BYPASS_VCO_DIVIDER) 0*AD9516_BYPASS_VCO_DIVIDER)
@ -47,25 +47,21 @@ class StartupKernel(EnvExperiment):
self.ad9154.clock_write(AD9516_OUT1, 0*AD9516_OUT1_POWER_DOWN | self.ad9154.clock_write(AD9516_OUT1, 0*AD9516_OUT1_POWER_DOWN |
2*AD9516_OUT1_LVPECLDIFFERENTIAL_VOLTAGE) 2*AD9516_OUT1_LVPECLDIFFERENTIAL_VOLTAGE)
# FPGA deviceclk, dclk/2 # FPGA deviceclk, dclk/1
self.ad9154.clock_write(AD9516_DIVIDER_4_3, AD9516_DIVIDER_4_BYPASS_2) self.ad9154.clock_write(AD9516_DIVIDER_4_3, 0*AD9516_DIVIDER_4_NOSYNC |
self.ad9154.clock_write(AD9516_DIVIDER_4_0, 1*AD9516_DIVIDER_4_BYPASS_1 | 1*AD9516_DIVIDER_4_BYPASS_2)
(2//2-1)*AD9516_DIVIDER_0_HIGH_CYCLES |
(2//2-1)*AD9516_DIVIDER_0_LOW_CYCLES)
self.ad9154.clock_write(AD9516_DIVIDER_4_4, 0*AD9516_DIVIDER_4_DCCOFF) 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 | self.ad9154.clock_write(AD9516_OUT9, 1*AD9516_OUT9_LVDS_OUTPUT_CURRENT |
2*AD9516_OUT9_LVDS_CMOS_OUTPUT_POLARITY | 2*AD9516_OUT9_LVDS_CMOS_OUTPUT_POLARITY |
0*AD9516_OUT9_SELECT_LVDS_CMOS) 0*AD9516_OUT9_SELECT_LVDS_CMOS)
# sysref f_data*S/(K*F), dclk/32 # sysref f_data*S/(K*F), dclk/16
self.ad9154.clock_write(AD9516_DIVIDER_3_0, (32//2-1)*AD9516_DIVIDER_3_HIGH_CYCLES_1 | self.ad9154.clock_write(AD9516_DIVIDER_3_0, (16//2-1)*AD9516_DIVIDER_3_HIGH_CYCLES_1 |
(32//2-1)*AD9516_DIVIDER_3_LOW_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 | self.ad9154.clock_write(AD9516_DIVIDER_3_1, 0*AD9516_DIVIDER_3_PHASE_OFFSET_1 |
0*AD9516_DIVIDER_3_PHASE_OFFSET_2) 0*AD9516_DIVIDER_3_PHASE_OFFSET_2)
self.ad9154.clock_write(AD9516_DIVIDER_3_2, (2//2-1)*AD9516_DIVIDER_3_HIGH_CYCLES_2 |
(2//2-1)*AD9516_DIVIDER_3_LOW_CYCLES_2)
self.ad9154.clock_write(AD9516_DIVIDER_3_3, 0*AD9516_DIVIDER_3_NOSYNC | self.ad9154.clock_write(AD9516_DIVIDER_3_3, 0*AD9516_DIVIDER_3_NOSYNC |
0*AD9516_DIVIDER_3_BYPASS_1 | 0*AD9516_DIVIDER_3_BYPASS_2) 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_DIVIDER_3_4, 0*AD9516_DIVIDER_3_DCCOFF)
self.ad9154.clock_write(AD9516_OUT6, 1*AD9516_OUT6_LVDS_OUTPUT_CURRENT | self.ad9154.clock_write(AD9516_OUT6, 1*AD9516_OUT6_LVDS_OUTPUT_CURRENT |
2*AD9516_OUT6_LVDS_CMOS_OUTPUT_POLARITY | 2*AD9516_OUT6_LVDS_CMOS_OUTPUT_POLARITY |