Post Go back to editing

AD9102 Output Signal

I’m using  AD9102, I write and read in all register but I haven't output signal.

What is the minimum registers configuration for generate a signal?

Can it work without calibration?

In attachment the schematic.



  • Hello Valemea,

    I struggled with this as well. The documentation is appalling.

    Anyway, the secret of making it work is to understand that it is only the shadow registers that are updated when you write to the register set. We used a clock frequency of 167.772160 MHz to give a 10 Hz step resolution. This is the sequence I used to output a sine wave based on the built in DDS sine wave generator:

    Out_port(~ad9102_nTrigger, ad9102_nTrigger);          //Trigger is off

    Out_port(~sig_gen_reset,sig_gen_reset );       //reset is inactive

    usleep(100);  //I don't know how long it takes to come out of reset - not in data sheet

    sig_gen_control_701(SPICONFIG, 0x0);    //use 4 wire mode - seperate transmit and receive pins

    sig_gen_control_701(POWERCONFIG,0);    //set the power config

    sig_gen_control_701(CLOCKCONFIG,0);    //set the clock config

    sig_gen_control_701(DDS_TW32, 0);                    //we go for 1000 Hz, in 10 Hz steps = 100. 0 in upper word

    sig_gen_control_701(DDS_TW1, 100 <<8);   //1kHz, but in upper 8 bits of lower tuning word

    sig_gen_control_701(DAC_DGAIN, DAC_GAIN_x1 <<4);          //set the gain to 1. DAC_GAINx1 = 0400h

    sig_gen_control_701(DACDOF, 0);                              //No offset

    sig_gen_control_701(WAV_CONFIG, WAVE_DDS_SINE | WAVE_prestored);          //set the waveform to DDS SINE

    sig_gen_control_701(PAT_TYPE,0);        //repeat continuously

    sig_gen_control_701(RAMUPDATE,1);   //update all SPI registers --ABSOLUTELY CRUCIAL

    sig_gen_control_701(PAT_STATUS,1);      //start pattern

    Out_port(~ad9102_nTrigger, 0);          //Start Trigger

    After that you can change frequency with:

    sig_gen_control_701(DDS_TW32, freq_value >> 8);  //put bits [23..8] in upper tuning word

    sig_gen_control_701(DDS_TW1, (freq_value & 0xFF) << 8);   //put bits [7..0] upper 8 bits of lower tuning word

    sig_gen_control_701(RAMUPDATE,1);   //update all SPI registers --ABSOLUTELY CRUCIAL

    I hope this helps.


  • Hi -

    Yes the shadow register concept is expalined in the paragraph below from the data sheet. Teh idea is for the user to be able to update shadow registers while active registers are in use generating a signal. We're looking to continuosly improve our presentation of data sheet material. We will endeavor to get a better rating than appalling in the future.


    Configuration Register Update Procedure

    Most SPI accessible registers are double buffered. An active register set controls operation of the AD9102 during pattern generation. A set of shadow registers stores updated register values. Register updates can be written at any time. When configuration update is complete, the user writes a 1 to the UPDATE bit in the RAMUPDATE register. The UPDATE bit arms the register set for transfer from shadow registers to active registers. The AD9102

    performs this transfer automatically the next time the pattern generator is off. This procedure does not apply to the 4k × 14 SRAM. For the SRAM update procedure, see the SRAM section.




  • Hello Larry,

    Yes it is true the paragraph discusses RAMUPDATE, but there is no example of a minimum control sequence in the data sheet, which I think many users would have found helpful (as evidenced by the number of people having problems with it!). My confusion initially was that I assumed (incorrectly) that the shadow registers were only used when running, and not all the time. In addition it appears that nTrigger is required to transition to start an output.

    Other points that could be in the data sheet:

    1. The time from reset to being able to program values, and the minimum duration of the reset pulse.

    2. The format of the DAC_DGAIN value. The data sheet says -2 to +2. Is this two's compliment? I found 0x400 is x1.

    3. Please be specific about the sample format saved to RAM. It appears that the sample is stored in [15:2], and not  [11:0] as Table 14 claims.

        A value of 0 is mid range, up to 0x1FFF <<2 denoting maximum +ve amplitude, and 0x2000 <<2 denoting maximum -ve amplitude, and

        0x3FFF <<2 being one count negative from the 0 point. 

    4. Confirm what the Start Address means. I found that the address range programmed is 0 ..  0xFFF <<4.

    5. Confirm that the output sequence goes from start address to stop address inclusive and not start address to stop address - 1.

    6. Confirm that Ram Update is required both when the pattern is running, and also when it is not running.

    7. Make clearer that you cannot change a pattern (eg DDS sine to RAM), unless the pattern is off first. 

    8. I want to clock the RAM pattern at the rising edge of the DDS MSB rate. So I set DDS_CONFIG to 0x04 (bit 2 = 1), but this does not seem to work the way I expect.

    9. The meaning of the DDS_PW (Phase Offset) is not defined. It is a 16 bit number. This suggests 0- 0xFFFF is 0 - 2pi radians. However, in my tests, I found the Phase register is not set absolutely (as in the AD9834), instead the DDS_PW represents an offset from the current phase value, which is random. It is not possible (please confirm) to reset the phase to a know angle (eg 0). This means we cannot start generating at a particular phase angle - most annoying. So what is the use of this register in a single channel application?

    Anyway, the device is pretty good in some areas, so thanks - but I'm sad about the Triangle Wave generation, and Phase setting lackings.


  • Hello Larry,

    I also seem to have two other problems.

    1. DDS Clock Source

    I cannot make the DDS_MSB_EN work in the DDS_CONFIG register.

    My assumption is that if I program the RAM to have two values, 0x1FFF <<2 and 0x2000 <<2 at 0x6000 on, I set Start_addr to 0 <<4 and Stop_addr to 1<<4, and Pattern_period to 2, then I should get a square wave. If the DDS_MSB_EN is 0, then the square wave frequency should be CLK/2 frequency. If DDS_MSB_EN = 1, then the square wave should be at the DDS/2 frequency - which is what I want.

    However, the DDS_MSB_EN bit does not seem to have any effect.

    2. Sawtooth Frequency

    I cannot work out how to change the Sawtooth frequency. Set to Triangle, I see the generator outputting 16384 samples increasing from -max to + max, and then 16384 samples from +max to -max, and repeating this. This yields just one frequency.

    I can see that I can dwell at one sample for between 1 and 64 clock cycles, but that is a very coarse approach to setting the frequency. It means you can only get 64 frequencies - the next being half of the previous one. Kind of not very useful!  I had assumed (silly of me) that the part would use the phase accumulator with the linear to sine wave conversion turned off (just as the AD9834 does), and so I could get any frequency. However, I cannot figure out how to do this. I would be grateful for any help.

    Can you clarify what I'm doing wrong?  Thanks.


  • 1. I've attached an example where I used the DDS MSB enable as part of generating a chirp waveform with AD9106. The SRAM contains a list of DDS tuming words. The result (included) is one sinewave cycle at each DDS frequency.

    2. For SAW tooth waveforms you can only adjust teh number of samples per step.

    I hope thuis helps.


  • Hello Larry,

    sadly the link you included did not go anywhere. I did see your memory content. All I actually need is the very few register allocations to show how to make the RAM address use the DDS MSB as clock rather than the input clock.

    Now I don't want to chirp the DDS, I want to output directly from the RAM, WITHOUT the DDS, but using the DDS_MSB as clock. (I do understand that this means I could get jitter of 1 CLK In period, but I can work around that).  I have this horrible feeling that the chip does not work this way. Yet another failing of the data sheet.

    Currently this is my complete initialization (sig_gen_control_701 does the work of saving to the AD9102) to get going with:

    Out_port(~ad9102_nTrigger, ad9102_nTrigger);          //Trigger is off

    sig_gen_control_701(SPICONFIG, 0x0);    //use 4 wire mode

    sig_gen_control_701(PAT_STATUS,0);      //stop patterns if they are on

    sig_gen_control_701(POWERCONFIG,0);    //set the power config

    sig_gen_control_701(CLOCKCONFIG,0);    //set the clock config

    sig_gen_control_701(DDS_TW32, 0);         //initialize with 1000 Hz, in 10 Hz steps = 100. 0 in upper word

    sig_gen_control_701(DDS_TW1, 100 <<8);   //1kHz, but in upper 8 bits of lower tuning word

    //The important bit:

    sig_gen_control_701(DDS_CONFIG, RAM_DDS_MSB_CLK); //the RAM sequence is output on the rising DDS MSB    <----- this is what I do, but it has no effect  (RAM_DDS_MSB_CLK = 0x04)

    sig_gen_control_701(DAC_DGAIN, DAC_GAIN_x1 <<4);          //set the gain to 1

    sig_gen_control_701(DACDOF, 0);                              //No offset

    sig_gen_control_701(SAW_CONFIG, SAW_TRIANGLE);  //make the sawtooth a triangle, with 1 sample/step

    sig_gen_control_701(WAV_CONFIG, 0);          //set the waveform to output from RAM from start to stop address

    sig_gen_control_701(PAT_TYPE,0);        //repeat continuously

    sig_gen_control_701(PAT_PERIOD,4000);   //the pattern is 4000 samples long - just to experiment with

    sig_gen_control_701(START_ADDR,0<<4);      //set the start address to 0 - used for square wave output

    sig_gen_control_701(STOP_ADDR,4000<<4);       //set end address inclusive

    sig_gen_control_701(DAC_CST,0); //make sure constant value is 0   

    sig_gen_control_701(PAT_STATUS,MEM_ACCESS); //access memory

    for (n=0; n<2000; n++) sig_gen_control_701(SRAM_DATA+n,0x7fff);      //output minimum value for square wave

    for (n=2000; n<4000; n++) sig_gen_control_701(SRAM_DATA+n,0x8000);      //output max value for square wave

    sig_gen_control_701(SRAM_DATA+4000, 0); //output 0 value - just to check how start/stop address works

    sig_gen_control_701(PAT_STATUS,1);      //start pattern

    Out_port(~ad9102_nTrigger, 0);          //Trigger is on

    My whole design was predicated on the chip working this way, and this is the way I read the data sheet. I am very sad that I cannot do a swept Triangle wave, and now it looks like I can't do a swept arbitrary wave either. I guess that means throwing away the board (made a 100 so far), and just using a DAC, and using the FPGA instead. I was trying to save time, but no. (As an aside this is the second AD disappointment this year. The first was major, and caused a complete extra design loop, with added component cost and loss of performance - I'm using the AD4817 op-amp, and discovered when you power it down that the +IN input gets dragged to -V, confirmed with the designer as a chip bug. Now I have to isolate the input with a relay. Blah).



  • Hi -

    If you describe a waveform you want to generate and how you want to generate it I'll get it running in the lab if the AD9102 can do it and send you the regval file.

    - Larry

  • Hello Larry,

    Thanks for getting back to me so fast.

    The simplest waveform I want to generate is a swept square wave.

    So Ram [0] = 0x7FFF  (-ve min)

          Ram [1] = 0x8000  (+ve max)

    Start = 0, Stop =1, Pattern length = 2

    Output directly from Ram, continuous pattern, Address counter incremented by DDS_MSB

    Set DDS frequency to any value (I used 1000 Hz).

    I expect  a Square Wave of 500 Hz.

    If this can be done, I'll be grateful!



  • Hi Bart –

    I tried this in the lab just now. It turns out the DDS output MSB can only be used as the SRAM address counter clock if the DDS Tuning word source is set to RAM data.

    -        Larry

  • Hello Larry,

    well that is a great shame. The utility of the chip has been severely compromised from my point of view - not wiring the Phase accumulator contents for triangle wave generation, and not allowing variable frequency AWG seems a huge loss of capability from what should have been simple given what is already in the chip.

    I would not have used the chip if I had known these things. So as an AD insider, how does one go about improving the data sheet so that instead of saying

    "The SRAM address counter can be programmed to be incremented by CLKP/CLKN (default) or by the rising edge of the DDS MSB" on page 23,

    and again

    "Selects the SRAM address counter clock as CLKP/CLKN when set to 0x0, DDS MSB when set to 0x1." in the Pattern Control 2 register description on page 34, both of which are WRONG, to say "but ONLY when the DDS Tuning word source is set to RAM data".

    The designer needed his head read, I reckon.

    So now I have two significant AD fails under my belt - the ADA4817 op-amp with a chip fault that drags the +IN pin to V- when powered down, and caused a great deal of angst on our part trying to re-design a 300 MHz capable work-around, and the AD9102, which we designed in on the strength of the data sheet, built a hundred boards, and find it can't do what the data sheet says. I am cross.

    - Bart