Post Go back to editing

EVAL-ADAQ400X HDL low sampling rate

Hello,

I'm working on a new project now involving ADAQ4003 and Zedboard.  Compared to a previous thread, I decided to do everything and not rely on other personnel here in my company.  I posted this new question as I think my concern is more on the HDL side than a Linux driver one.

I'm using the EVAL-ADAQ4003 board with Zedboard and petalinux meta-adi 2020.1, as well as very recent ADI HDL checkout (hash ID 1fe0d5f8e00b119a5a389213cf05e9db4646c86a) for ad400x, I think the project name is ad40xx_fmc.  I think the default settings of this HDL project is for AD4020 eval board (which I worked with before very recently).  The HDL project has a constraint file for ADAQ400X which connects the board to a PMOD connector JA1, not FMC.  So I made the following change to the project's system_bd.tcl and system_project.tcl files:

## Please select which eval board do you want to use
##
##    1 - EVAL-AD40XX-FMCZ
##    0 - EVAL-ADAQ400x
##
set AD40XX_ADAQ400X_N [get_env_param AD40XX_ADAQ400X_N 0]

# specify ADC resolution -- supported resolutions 16/18/20 bits
set ADC_RESOLUTION [get_env_param ADC_RESOLUTION 18]

I modified the default parameters in the tcl file and built it with the "make" command in the command-line (not through Vivado IDE).  I also set the compatible string to "ad4003" in the device tree in Linux.

Overall, it works - Linux can get ADC values from the HDL and ADC, and it also works with libiio.  However, the actual sampling rate is just around ~900000 samples per second.  I didn't modify the sampling_rate parameter in the TCL files so I expected it to be 1800000 samples per second but it's just 900000 (I'm measuring it using oscilloscope).  Whereas when the project was left in its default state to support AD4020 eval board, I've verified that indeed actual sampling rate is ~1800000 per second (sampling period is ~562ns) so the default project is okay.

There must be something I'm missing here.  I'm not very experienced in HDL so I'm very reliant on ADI user guides or this forum.



Added hash of adi-hdl git checkout branch for identification
[edited by: ubermensch at 8:07 AM (GMT -4) on 24 Sep 2021]
Parents
  • Hi,

    Could you please tell me the exact CS period that you measured with the scope? Could you measure the SCLK period as well?

    After that, please edit this line in the script

    https://github.com/analogdevicesinc/hdl/blob/7ed4955661271deec149901d2cc84272e2dfafb1/projects/ad40xx_fmc/common/ad40xx_bd.tcl#L52

    to this: ad_ip_parameter trigger_gen CONFIG.PULSE_PERIOD 93

    then build and see if anything changes.

    it things look the same try changing the line to about half. and by this i mean depending on the CS period that you measured with the scope it should be 93*558/(measured period)

    ~Sergiu

  • Hello ,

    I tried your suggestions, but there's no improvement.

    I first hard-coded CONFIG.PULSE_PERIOD to 93 as you suggested, but the resulting CS period and sampling rate are same as before.

    Next, I tried halving it as you suggested (changing the line to about half), so I set CONFIG.PULSE_PERIOD to 46 in the TCL script.  Is this way correct?  Anyway, after compiling the hdl with this change and rebuilding petalinux for the images, the CS period and sampling rate are still the same as before.

  • I suspect that your new hardware was not copied to the sd card correctly, or was overwritten somehow since it is impossible for it to behave the same way.

    besides that, i suspect that the zynq 166MHz clock output is somehow changed to 83MHz since both the CS and the SCLK seem to move at half their speed. Please try to build the HDL from this branch

    https://github.com/sarpadi/hdl/tree/debug_adaq40xx

    I have added an ip which will tell us the actual value for the frequency. You will need to start the zedboard with this HDL and use memtool to read its registers

    https://manpages.ubuntu.com/manpages/xenial/man8/memtool.8.html

    the address that we are interested in is 0x41330040

    once the value is read this formula must be applied to it to get the frequency

    F = (regval * 100000000 + 0x7FFF) >> 16)

    F should be 166

    Let me know if there are any questions regarding this procedure.

    ~Sergiu

  • Thanks .  I'm on the process of trying and testing out your steps.

    One question though.  I noticed that the tcl scripts in debug_adaq40xx branch sets Vivado to version 2021.1.  Does it have to be Vivado 2021.1 or will Vivado 2020.2 or 2020.1 be alright to use to build it?  My latest Vivado is 2020.2 and so far the HDL command-line build via make successfully completed.  On the other hand, ADI's latest meta-adi and petalinux is for 2020.1 and I'm worried whether there will be version compatibility issues.  The previous days' builds were done on 2020.1 (after modifying the script that set it to higher Vivado versions).

    I'm on my way to test the HDL build done by Vivado 2020.2 with my Zedboard meta-adi Linux.

  • Hello Sergiu ,

    I tried the hdl branch you've given me, built it with Vivado 2020.2, and used it with meta-adi Petalinux.  Here is the value from the register you've asked me to read, which I read via devmem:

    The register value is 0x1AAAB.

    When I used this regval to the equation you gave me, (F = (regval * 100000000 + 0x7FFF) >> 16)), F is computed to be 166667175.

  • Hi Sergiu ,

    Is this new HDL supposed to set my ADAQ400X CS period to ~560ns or 1.8MSPS sampling rate?  I'm still getting the same 900KSPS sampling rate as before.

    I'm trying to rebuild everything in the SW including the petalinux part.

  • this line will tell you the supported Vivado version for that particular commit

    github.com/.../adi_project_xilinx.tcl

    could you be more specific regarding those tcl scripts?

    using a different vivado version should generate a fail with a wrong version warning

    you can make the tool ignore that warning and it might build with a different version but it is generally not recommended. we support one version at a time.

    our master is currently at 2021.1 so we can upgrade if needed or we can stick to 2020.2, the project will build the same.

  • Hello

    During the previous builds from the previous days, I did change these two files to accomodate Vivado 2020.1:

    hdl/project/scripts/adi_project_xilinx.tcl

    hdl/library/scripts/adi_ip_xilinx.tcl

    For the latest HDL build, the one you just shared (https://github.com/sarpadi/hdl/tree/debug_adaq40xx), I didn't change anything there and built it as it is.  I used Vivado 2020.2 during its first and only build.  2020.2 seems to work with it (unlike 2020.1) so I'm sticking with 2020.2 for now.  The HDL built by 2020.2 also didn't encounter compatibility issues with my ADI petalinux, so another reason to stick with 2020.2.

  • Hello ,

    I've already created a new meta-adi petalinux project so I can rebuild Linux from scratch.  It uses the latest HDL from your git branch you just sent me.  Despite all these, sampling rate is still 900KSPS.

    The register value from 0x41330040 is still 0x0001AAAB, so calculating F still yields 166667175.

  • Hello Sergiu

    Any new updates in here or new ideas that I can try?  Still stuck in this.  So far I've tried looking at the clk_div and the SPI engine instruction (set by the SW) for clues and discrepancies between ADAQ4003 and AD4020.  However, both of them use almost the same instructions and values (except the data width of course).  It seems this was a wrong angle to search as the clk_div only concerns the SCLK when the sampling rate problem encompass the CS period as well.

    I'm trying to learn using ILA as well as the no-OS FW in Zedboard.  Have you tried out your git branch into no-OS?  Also, any internal signals in spi-engine that I can tap for debugging or gaining insight on what determines sampling rate?

Reply
  • Hello Sergiu

    Any new updates in here or new ideas that I can try?  Still stuck in this.  So far I've tried looking at the clk_div and the SPI engine instruction (set by the SW) for clues and discrepancies between ADAQ4003 and AD4020.  However, both of them use almost the same instructions and values (except the data width of course).  It seems this was a wrong angle to search as the clk_div only concerns the SCLK when the sampling rate problem encompass the CS period as well.

    I'm trying to learn using ILA as well as the no-OS FW in Zedboard.  Have you tried out your git branch into no-OS?  Also, any internal signals in spi-engine that I can tap for debugging or gaining insight on what determines sampling rate?

Children
  • Hello,

    I tried the branch with no-os and it works fine. I would encourage you to try it as well if you haven't. It would help validate the HDL at least.

    In the HDL there are also a couple of IP cores which could provide some more information. Here is the wiki page for it. https://wiki.analog.com/resources/fpga/docs/axi_sysid

    Normally our linux comes with a driver which makes things easier to read but I was told that is not available under petalinux. It would be a good idea to read out the data and make sure that the HDL is the same one that you are debugging.

    We should read starting from this offset

    0x200     0x0800     SYSROM_START

    it's a 32bit memory 512 lines deep. the data needs to be have the byte order reversed and then converted to ascii. you can paste the contents of the memory here if you want and i will look at them.

    ~Sergiu

  • Hello 

    Thanks for the reply.  I think there is a Linux driver for the ad400x ADC devices (which I think should cover the ADAQ400X).  That's what I've been using.  I just changed the compatible string in the device tree from "ad4020" to "ad4003" so it would initialize as an 18-bit ADC device just like ADAQ4003/AD4003 is.  This is mentioned in https://wiki.analog.com/resources/tools-software/linux-drivers/iio-adc/ad400x?rev=1610005286

    So far, here's the data I've read from the SYSROM_START offset you gave, all 512 32-bit lines.  I read this from Linux shell of zedboard using devmem command (such as devmem 0x45000800).  I think 0x45000000 is the correct base address for this?

    Value               Offset

    0x00000002    0x800
    0x00000010    0x804
    0x000001D0    0x808
    0x000001D8    0x80c
    0x000001E0    0x810
    0x00000000    0x814
    0x00000000    0x818
    0x00000000    0x81c
    0x00000000    0x820
    0x00000000    0x824
    0x00000000    0x828
    0x00000000    0x82c
    0x00000000    0x830
    0x00000000    0x834
    0x00000000    0x838
    0x63000000    0x83c
    0x75626564    0x840
    0x64615F67    0x844
    0x30347161    0x848
    0x00007878    0x84c
    0x00000000    0x850
    0x00000000    0x854
    0x00000000    0x858
    0x62393165    0x85c
    0x65316164    0x860
    0x63343363    0x864
    0x64326333    0x868
    0x34373232    0x86c
    0x39633564    0x870
    0x65386138    0x874
    0x38663138    0x878
    0x33626235    0x87c
    0x63353937    0x880
    0x00000000    0x884
    0x00000074    0x888
    0x6A646176    0x88c
    0x32333631    0x890
    0x32353139    0x894
    0x00003131    0x898
    0x00000000    0x89c
    0x3D000000    0x8a0
    0x00000000    0x8a4
    0x00000000    0x8a8
    0x00000000    0x8ac
    0x00000000    0x8b0
    0x00000000    0x8b4
    0x00000000    0x8b8
    0x00000000    0x8bc
    0x00000000    0x8c0
    0x00000000    0x8c4
    0x00000000    0x8c8
    0x00000000    0x8cc
    0x00000000    0x8d0
    0x00000000    0x8d4
    0x00000000    0x8d8
    0x00000000    0x8dc
    0x00000000    0x8e0
    0x00000000    0x8e4
    0x00000000    0x8e8
    0x00000000    0x8ec
    0x00000000    0x8f0
    0x00000000    0x8f4
    0x00000000    0x8f8
    0x00000000    0x8fc
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000
    0x00000000

    Let me know what you will find.

  • Hello,

    The contents translate to something like this:

    branch: debug_adaq40xx

    commit hash: e19bda1ec34c3c2d2274d5c98a8e81f85bb3795c

    timestamp (epoch): 1632915211

    So this rules out the possibility that the HDL is not correct.

    Unfortunately I still cannot reproduce your issue.

    Have you tried using no-OS?

    ~Sergiu

  • Hello ,

    Yes, I've just tried the no-OS earlier today together with the HDL you gave me.  I have to do the no-OS in Vitis.  The only thing I've modified there is the dev_id - I've changed it to ID_AD4003 from the original ID_AD4020 so it would use 18-bits resolution.  The result here is that it worked - timing is correct, CS period is around 568 ns.  Here are some waveforms I got.

    I've also tried the original ID_AD4020 configuration in the no-OS with your HDL.  Given that you changed the resolution in the TCL to 18-bits, I'm not expecting it to work but I was surprised that this ID_AD4020 also worked, together with correct timing and sampling rate.

    So, my observations are:

    1. Linux, ad400x_fmc HDL, AD4020 - sampling rate correct

    2. Linux, ad400x_fmc HDL, ADAQ4003/AD4003 - sampling rate got halved

    3. no-OS, ad400x_fmc HDL, AD4020 - sampling rate correct

    4. no-OS, ad400x_fmc HDL, ADAQ4003/AD4003 - sampling rate correct

    Can you also try this in meta-adi Linux?

  • There is an option to divide the SCLK using a prescaler. You can read about it here https://wiki.analog.com/resources/fpga/peripherals/spi_engine/instruction_format

    It is configured using this register

    0x44     0x0110     OFFLOAD0_CDM_FIFO

    Could you make sure that the prescaler is set to 0 (not used) ? By default it should be 0.

    ~Sergiu

  • Hello ,

    In checking the Linux driver code (spi-axi-spi-engine.c and the ad400x.c), I printed the resulting  commands that're being compiled and written to the OFFLOAD_CDM_FIFO register you mentioned in ADAQ4003.  This is the default code and I haven't made any changes to this yet.

    p[0] : 2100
    p[1] : 2001
    p[2] : 2212
    p[3] : 11fe
    p[4] : 200
    p[5] : 11ff
    p[6] : 3002

    So from the instruction format specs:

    2100 - Configuration write, SPI configuration reg, new value = 0

    2001 - Configuration write, prescaler config reg, div = 1

    2212 - Configuration write, dynamic transfer length reg, word length = 18 (since it's ADAQ4003)

    11fe  - Chip select instruction, delay = 1, new CS configuration = 0xfe

    0200 - transfer instruction, read, transfer length = 0+1 = 1 word

    11fe  - Chip select instruction, delay = 1, new CS configuration = 0xff

    3002 - Synchronize instruction, with id = 2.

    This set of commands was taken after reading just a single ADC value.  On the other hand, the following are the cmds seen with AD4020:

    p[0] : 2100
    p[1] : 2001
    p[2] : 2214
    p[3] : 11fe
    p[4] : 200
    p[5] : 11ff
    p[6] : 3002

    So in ADAQ4003, clk_div = 1 while you said it should be zero.  But in AD4020 which is working in terms of timing, it's also 1.  Are there other instructions/cmds that are suspicious in terms of its values?

  • Hello

    Thanks for this great suggestion.  Now for the good news.  I've changed the computation of the clk_div value to ensure its value is zero and upon testing, the CS sampling period has changed to 562 ns, just like in the SDK code.  Now the sampling rate is correct.

    The offending line in the Linux driver axi-spi-axi-engine.c is that clk_div is computed as

    clk_div = DIV_ROUND_UP(166666665, (2 x 71000000)) - 1

    where DIV_ROUND_UP(n, d) --> ((n) + (d) - 1) / (d)

    This yields a result of clk_div = 1 which is different from that in the SDK code.  In the SDK it used the equation which is as specified in https://wiki.analog.com/resources/fpga/peripherals/spi_engine/instruction_format and so clk_div is

    clk_div = f_clk / ((2 x fsclk) - 1) = (166666666 / ((2 x 83333333) - 1) = 0

    Once I implemented this on the spi axi engine Linux driver even if max SPI frequency used is <71000000> then everything fell into the right place.

  • Hi

    That's great news indeed. Glad it all worked out.

    ~Sergiu