How to Connect an ADC to an FPGA

What is an Analog-to-Digital Converter (ADC)

The ADC converters translate analog electrical signals, usually the voltage amplitude, into a sequence of discrete values (integer number) for data processing purposes. The bit resolution of the analog to digital conversion determines the magnitude of the quantization error. The number of discrete levels depends on the number of ADC bit resolution. For an N-bit ADC, the number of discrete possible values is 2^N.

For example, for 8-bit ADC the input signal is discretized in 2^8=256 different values.

You can find a complete description of ADC here:

https://en.wikipedia.org/wiki/Analog-to-digital_converter

There are a wide number of ADC vendors. Here below you can check for the best ADC for your design:

The Figure1 shows the ADC transfer function: the analog input voltage referred to the Full-Scale Range (FSR) vs. the digital output ADC code. In the example, a 3 bit ADC is taken into account

Figure1 ADC conversion transfer function
Figure1 – ADC conversion transfer function 

The principal ADC digital interfaces are:

  • Parallel Single Data Rate (SDR), here you can find an example.
  • Parallel Dual Data Rate (DDR)
  • Serial interface I2C, SPI
  • Serialized LVDS interface
  • JESD204A/ JESD204B serial interface. You can find out more at www.jedec.org

Parallel interface is used for high-speed ADC typically > 1MSPS

Serial SPI or I2C interface are used for low-speed ADC < 10 MSPS.

The JEDEC standard for ADC JESD204A high-speed serial interface reduces board routing requirements and lowers pin count requirements for the receiving device.

An example of JEDEC ADC is the TI ADC12J1600 12-Bit, 1.6 GSPS RF sampling ADC with JESD204B interface or the Analog device AD9690 14-Bit, 500 MSPS / 1 GSPS JESD204B, Analog-to-Digital Converter

In this post, we want to cover the basic of ADC interfacing so we will start with the parallel single data rate ADC interface.

In this example, we will refer to the Texas Instruments ADC ADS5542 14-Bit, 80MSPS Analog-to-Digital Converter. This ADC implements a simple parallel output interface to output the digital data from the device.

The component in the example is summarized in Figure2

On the left side is represented the differential analog input clock and analog input data.

Figure2 - ADS5542 internal architecture
Figure2 – ADS5542 internal architecture

on the right side the digital output clock “CLKOUT is used to clock the converted data D0—D13 of the ADC. In the timing diagram of Figure3, the ADC provides output converted data on falling clock output edge. It is possible to program ADC to provide data on output clock rising edge. For further information, you can check the ADC datasheet here.

Figure3- ADS5542 conversion timing
Figure3- ADS5542 conversion timing

 

 

ADC-FPGA interface

At this point let’s see how to interface an ADC with Single Data Rate (SDR) parallel output to an FPGA. Our Hypothesis is to have a timing diagram like the Figure3 above, i.e. ADC digital data present at ADC output interface at rising edge ADC digital clock. Under this condition, the best clock edge should be the rising edge of ADC “output clock”. This is true if the input delay of clock and data is the same. In Figure4 Dly1 = Dly2.

fpga-input-buffer
Figure4 – FPGA Data vs Clock delay

If Dly1-Dly2= clock period/2 the best clocking edge will be the falling edge.

In order to guarantee optimum sampling a simple trick is to foresee the clock sampling swap at the FPGA ADC input interface and to set the input flip-flop inside the FPGA pad if allowed by the technology.

The following simple VHDL example can be used to sample ADC data at FPGA input. The example is customized for 4-bit input only for the sake of simplification the RTL and technology MAP viewer example.

library ieee;
use ieee.std_logic_1164.all;

entity adc_parallel_interface is
port (
  i_clk      : in  std_logic;
  i_rstb     : in  std_logic;
  i_data     : in  std_logic_vector(3 downto 0);
  o_data     : out std_logic_vector(3 downto 0));
end adc_parallel_interface;

architecture rtl of adc_parallel_interface is

signal r_data   : std_logic_vector(3 downto 0);

begin

p_adc_parallel_interface : process(i_clk,i_rstb)
begin
  if(i_rstb='0') then
    r_data              <= (others=>'0');
    o_data              <= (others=>'0');
  elsif(rising_edge(i_clk)) then
    r_data              <= i_data;
    o_data              <= r_data;
  end if;
end process p_adc_parallel_interface;

end rtl;

The RTL viewer of Quartus II in Figure5 reports the four-bit input and output registers.

Figure5 Quartus II RTL viewer for FPGA-ADC SDR interfacing

In the technology MAP viewer are reported the input and output pad buffers.

Figure5
Figure6 Quartus II MAP viewer for FPGA-ADC SDR interfacing

Most of the FPGA technologies allow mapping input and output registers directly on FPGA pad. The input and output register mapping should be enabled using their custom setting.

In Quartus II, it is possible to enable mapping input and output register using the  “Pin Planner” windows or adding the following constraint on TCL script file:

For Output register mapping:

set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_data[3]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_data[2]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_data[0]
set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_data[1]

For Input register mapping:

set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_data[3]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_data[2]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_data[1]

You can use also wildcard

set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to o_data[*]
set_instance_assignment -name FAST_INPUT_REGISTER ON -to i_data[*]

The following VHDL code can be used to sample input ADC data using rising and falling clock edge. The signal “i_rise_fall_b” is used to select the clock edge to be used.

library ieee;
use ieee.std_logic_1164.all;

entity adc_parallel_interface_ddr is
port (
  i_clk            : in  std_logic;
  i_rise_fall_b    : in  std_logic;
  i_data           : in  std_logic_vector(3 downto 0);
  o_data           : out std_logic_vector(3 downto 0));
end adc_parallel_interface_ddr;

architecture rtl of adc_parallel_interface_ddr is

signal r_data_rise      : std_logic_vector(3 downto 0);
signal r_data_fall      : std_logic_vector(3 downto 0);

begin

p_sample_rise : process(i_clk)  -- sample ADC data on rising edge
begin
  if(rising_edge(i_clk)) then
    r_data_rise              <= i_data;
  end if;
end process p_sample_rise;

p_sample_fall : process(i_clk) -- sample ADC data on falling edge
begin
  if(falling_edge(i_clk)) then
    r_data_fall              <= i_data;
  end if;
end process p_sample_fall;

p_output : process(i_clk)  -- select EDGE sampling
begin
  if(rising_edge(i_clk)) then
    if(i_rise_fall_b='1') then
      o_data              <= r_data_rise;
    else
      o_data              <= r_data_fall;
    end if;
  end if;
end process p_output;

end rtl;

The RTL viewer in Figure7 shows the mux used to select between rising and falling edge.

Figure7 Quartus II RTL viewer for FPGA-ADC SDR interfacing
Figure7 Quartus II RTL viewer for FPGA-ADC DDR interfacing

Even in Technology MAP viewer of Figure8 is present a logic cell used as a mux.

Figure8 Quartus II MAP viewer for FPGA-ADC DDR interfacing
Figure8 Quartus II MAP viewer for FPGA-ADC DDR interfacing

Many FPGA has the capability of double data rate (DDR) sampling i.e. the capability to use rising and falling clock edge directly inside the FPGA PAD.

For Cyclone III FPGA used in this example, the input/output flip-flop and the mux are implemented inside the FPGA PAD using dedicated resources as in Figure9.

cyclone-III-PAD
Figure9 – Cyclone III – PAD Architecture

The Figure10 reports the input DDR buffer architecture of Cyclone III

Figure10 - Cyclone III - Input Buffer Architecure
Figure10 – Cyclone III – Input Buffer Architecture

As clear the DDR input is de-muxed in dataout_h and dataout_l


 

How many ADC sampled data can you store into FPGA?

Many ADC evaluation boards contain an FPGA on board connected to the ADC. The FPGA is used to acquire ADC sampled data in order to evaluate the ADC performances. As clear the quantity of ADC sampled data that can be stored depend on the FPGA installed and on the memory available on the evaluation board (EVB).

Let’s see some examples to clarify this issue.

Suppose to have an ADC connected to an FPGA. A possible simplified architecture is in Figure11.

ADC-FPGA interfacing and acquisition
Figure11 – ADC-FPGA interfacing and acquisition

The ADC is 10 bit ADC and FPGA is Cyclone III EP3C16 shown in Figure12.

Figure12 - Cyclone III-FPGA family overview
Figure12 – Cyclone III-FPGA family overview

The FPGA implements 516096 bit internal RAM, so the maximum storage available is equal to the FPGA available RAM.

For a 10-bit ADC, we can store up to

516096/10 = 51609 ADC word

Each ADC word contains 10 bits. Going deep in the FPGA architecture the FPGA RAM is implemented using M9K memory block, in the selected FPGA there are up-to 56 memory blocks available. The Altera M9K blocks support the following features:

  • 8,192 memory bits per block (9,216 bits per block including parity)
  • Independent read-enable (rden) and write-enable (wren) signals for each port
  • Packed mode in which the M9K memory block is split into two 4.5 K single-port RAMs
  • Variable port configurations
  • Single-port and simple dual-port modes support for all port widths
  • True dual-port (one read and one write, two reads, or two writes) operation
  • Byte enables for data input masking during writes
  • Two clock-enable control signals for each port (port A and port B)
  • Initialization file to pre-load memory content in RAM and ROM modes

And the block can be configured as:

Table1 - Altera M9K memory block configuration
Table1 – Altera M9K memory block configuration

So now we can review the number of ADC 10-bit words we can store inside the EP3C16 FPGA memory. The memory buffer must be quantized as reported in the memory block configuration, so let’s compute the storing efficiency for each configuration.

Total memory block = 56.

Table2 - ADC-FPGA interface maximum storage selection
Table2 – ADC-FPGA interface maximum storage selection

The best memory configuration is achieved using 4096×2 configuration (see Table2) that use all the M9K block but one with the higher efficiency. Remember that M9K is a memory block of 8192+1024=9216 bits.

In the last step is to compute how long can be the acquisition.

In this case, we need to know the ADC sampling frequency.

The acquisition time is:

Tacq = Memory Buffer (word)/ASC Speed (MSample/sec)

The ads5542 can sample data up-to 80 MSPS. So at maximum sampling rate we can store up to:

45.056/80.000.000= 563,2 us


 

If you appreciated this post, please help us to share it with your friend.

 

[social_sharing style=”style-6″ fb_like_url=”https://surf-vhdl.com/how-to-connect-an-adc-to-an-fpga/” fb_color=”light” fb_lang=”en_US” fb_text=”like” fb_button_text=”Share” tw_text=”Hi, here ‘How to interface ADC with an FPGA'” tw_lang=”en” tw_url=”https://surf-vhdl.com/how-to-connect-an-adc-to-an-fpga/” tw_button_text=”Share” g_url=”https://surf-vhdl.com/how-to-connect-an-adc-to-an-fpga/” g_lang=”en-US” g_button_text=”Share” linkedin_url=”https://surf-vhdl.com/how-to-connect-an-adc-to-an-fpga/” linkedin_lang=”en_US” alignment=”center”]

 

If you need to contact us, please write to: surf.vhdl@gmail.com

 

We appreciate any of your comment, please post below:

47 thoughts to “How to Connect an ADC to an FPGA”

    1. Thank You for reading.
      There is no specific board for this example.
      In the free course that you can receive signing up from the box aside,
      we use DE0 Altera board to implement the example.

    1. it depends on what you need.
      Do not confuse ADC with FPGA
      ADC is analog to digital converter
      FPGA is a digital programmable logic

      1. i am using AD7476 which is interfaced with cyclone-1 FPGA. I need help in coding in VHDL where i have to compare input value with a reference value if it is greater ref value then LED should glow.

  1. please more explain about Table2 – ADC-FPGA interface maximum storage selection
    i dont know how calculate memory buffer or remaining block

  2. What do you don’t understand of Table2?
    The table represents the FPGA internal memory configuration for the ADC data acquisition w.r.t the internal memory configuration capability.

  3. HI,
    Very informative post. Actually, I have sensed a temperature of the system and then convert to voltage and read through ADC on cyclone V GX . I have little confusion as, to how can I convert the voltage to temperature to within FPGA. As my application requirements, precise temperature measurement so I do not have any idea how to do floating time calculation in binary.It will be very helpful you can make a tutorial about that. on the basis of temperature, I have to change my circuit bias voltage. Thank you very much.

    1. the ADC has a parallel interface,
      you have to use DRDY to start reading the parallel data asserting the CS and RD/WR control signal

  4. could you please explain how block/ word and ADC word memory buffer are decided. and what is the meaning of remaining block (table-2)

    1. “word” is the ADC sample. In the example, a single word consists of 10 bits.
      “Block” is the set of word

  5. I want to interface ADC with FPGA family(Basys 3 or Nexys 4) and according to it,please provide me related details and required testbench and code in VHDL.

    I have to take speech signal as input to FPGA and have to provide delay in input sequence and after delay output sequence should be generated.

    Thank You.

    1. it depends on the ADC you are interfacing.
      You should read the ADC interface timing and implement a test bench that emulate that timing

  6. Hi, can you recommend any resources I can use to perform binning of samples so that I can read for longer periods without reducing clocking frequency of the ADC?

    1. you need a lot of memory on the board, or a fast connection that allow you to store the samples in real time on a PC

  7. Hello,

    Can you explain why you need this signal?
    “signal r_data : std_logic_vector(3 downto 0);”

    Can you skip it and feed the input into the output?

    “elsif(rising_edge(i_clk)) then
    o_data <= i_data;
    end if;"

    Thanks!

    1. it is correct, you can skip the “r_data” signal.
      If you register the input, the synthesizer can put the register in the FPGA pad.
      In this case, you have to worry about only the phase of the clock vs ADC data without worrying about the skew of the ADC data bus.

  8. Sir i want to interface AD7961FMCZ Board to FPGA Virtex 6. So it supports only ISE.Can you tell me the steps to follow and important things to be taken care.

  9. Hi,
    I am looking for the ADC Function to be used in the below VHDL code: I’m doing an FPGA Board designing and am using AD7476A to read out the input. Attaching the code below

    library ieee;
    use ieee.std_logic_1164.all;

    entity adc is
    port (
    clk : in std_logic;
    start : in std_logic;
    dout : out std_logic_vector(7 downto 0)
    );
    end entity;

    architecture rtl of adc is

    signal count : std_logic_vector(7 downto 0);
    signal data_in : std_logic_vector(7 downto 0);
    signal state : std_logic_vector(2 downto 0);

    begin

    process(clk)
    begin
    if rising_edge(clk) then
    case state is
    when “000” => — Idle State
    if start = ‘1’ then
    count ‘0’);
    state — Acquisition State
    count <= count + 1;
    if count = "11111111" then — Wait for 256 cycles
    data_in <= some_adc_function(); — Replace with your own ADC function
    state — Conversion State
    count <= count + 1;
    if count = "11111111" then — Wait for 256 cycles
    dout <= data_in;
    state
    state <= "000"; — Reset to Idle State
    end case;
    end if;
    end process;

    end architecture;

    Here data_in should be assigned to certain ADC Function so as to read the input. But I am confused as to how to initiate this. Could you please help me?

    Thank You.

Leave a Reply

Your email address will not be published. Required fields are marked *