IP core for AXI streaming with IIO support

I have a board with an ad7768 adc, and I'm using the ad7768evb demo project to access that devices via libiio.  This works well.

My fpga design also has a custom IP core that accepts an AXIS stream.  I'd also like to use libiio to send data to this device.

Is there an HDL core I could use that would do this, and has iio support in the kernel?



fixed title
[edited by: jay_col at 9:42 PM (GMT -4) on 28 Apr 2021]
Parents
  • Ok, I have this working.  Here is the basic procedure:

    1. Find an example project in hdl/projects that uses the ADI DMAC in memory mapped to streaming mode (DMA_TYPE_DEST 1).  I believe these are all going to be cores that use JESD.  An example is fmcomms11.  Use this project to get the correct setup for the DMA engine.
    2. Make an IP core compatible with the generic axi dac.  THe terminology is very confusing here.  The terms DAC and DDS will be used interchangeably.  But basically what you need to do is provide an AXI-lite interface on your device which has the appropriate registers that cf_axi_dds.c (in the kernel) will look for.  Rather than copy a DAC's hdl code, when you want to look at is the AXI-lite interface of this block: https://github.com/analogdevicesinc/hdl/tree/master/library/jesd204/ad_ip_jesd204_tpl_dac (specifically the regmap module)  You will see that it uses a few common verilog files, that you can use exactly as they are, to act as the axilite interface (off hand i think its up_axi.v, up_dac_common.v and up_dac_channel.v)
    3. In addition to adding those modules to you core you also need to pull in the XDC constraints files associated with those, as they have clock crossing domains in them, again look at the jesd core I mentioned.
    4. Copy one of the existing linux drivers from the drivers/iio/frequency folder.  Something like ad9122 is a good starting point.  I cant really walk you through this part.  I assume you dont have a spi device, in which case get rid of all references to spi, and change the module type from module_spi_init to a regular module_init.
    5. Edit cf_axi_dds.c to add the information for your new driver.  Assuming that you aren't using spi, then copy the existing axidds_core_info struct for a device that has .standalone = true as this will make cf_axi_dds not try and use spi.
    6. Update your dts file.  You don't really need much in there, just enough that the cf_axi_dds.c code can find the correct driver.

    A couple misc notes:

    • One of the confusing things for me was that I assumed that cf_axi_dds.c was just helper code for accessing the iio framework.  This isnt the case.  Its actually a driver itself, and it will look for your driver to load it.
    • In standalone mode it seems that your driver doesnt really need to do anything at all.  It appears that the 'conv' struct is never used, and none of your functions other than 'init' will ever be called.  I guess this means you need to do all your configuration during init, but I'm not really sure how you then provide the appropriate helper functions to do things like set sample rate.  I'm guessing that's maybe all handled through the common registers we added.
    • I wasn't able to get this to work as an out of tree module, in fact I wasnt able to get this to work as a module at all.  I had to enable ALL the analog devices drivers as part of the kernel.
Reply
  • Ok, I have this working.  Here is the basic procedure:

    1. Find an example project in hdl/projects that uses the ADI DMAC in memory mapped to streaming mode (DMA_TYPE_DEST 1).  I believe these are all going to be cores that use JESD.  An example is fmcomms11.  Use this project to get the correct setup for the DMA engine.
    2. Make an IP core compatible with the generic axi dac.  THe terminology is very confusing here.  The terms DAC and DDS will be used interchangeably.  But basically what you need to do is provide an AXI-lite interface on your device which has the appropriate registers that cf_axi_dds.c (in the kernel) will look for.  Rather than copy a DAC's hdl code, when you want to look at is the AXI-lite interface of this block: https://github.com/analogdevicesinc/hdl/tree/master/library/jesd204/ad_ip_jesd204_tpl_dac (specifically the regmap module)  You will see that it uses a few common verilog files, that you can use exactly as they are, to act as the axilite interface (off hand i think its up_axi.v, up_dac_common.v and up_dac_channel.v)
    3. In addition to adding those modules to you core you also need to pull in the XDC constraints files associated with those, as they have clock crossing domains in them, again look at the jesd core I mentioned.
    4. Copy one of the existing linux drivers from the drivers/iio/frequency folder.  Something like ad9122 is a good starting point.  I cant really walk you through this part.  I assume you dont have a spi device, in which case get rid of all references to spi, and change the module type from module_spi_init to a regular module_init.
    5. Edit cf_axi_dds.c to add the information for your new driver.  Assuming that you aren't using spi, then copy the existing axidds_core_info struct for a device that has .standalone = true as this will make cf_axi_dds not try and use spi.
    6. Update your dts file.  You don't really need much in there, just enough that the cf_axi_dds.c code can find the correct driver.

    A couple misc notes:

    • One of the confusing things for me was that I assumed that cf_axi_dds.c was just helper code for accessing the iio framework.  This isnt the case.  Its actually a driver itself, and it will look for your driver to load it.
    • In standalone mode it seems that your driver doesnt really need to do anything at all.  It appears that the 'conv' struct is never used, and none of your functions other than 'init' will ever be called.  I guess this means you need to do all your configuration during init, but I'm not really sure how you then provide the appropriate helper functions to do things like set sample rate.  I'm guessing that's maybe all handled through the common registers we added.
    • I wasn't able to get this to work as an out of tree module, in fact I wasnt able to get this to work as a module at all.  I had to enable ALL the analog devices drivers as part of the kernel.
Children
No Data