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
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.
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.
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.
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.
In the technology MAP viewer are reported the input and output pad buffers.
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.
Even in Technology MAP viewer of Figure8 is present a logic cell used as a mux.
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.
The Figure10 reports the input DDR buffer architecture of Cyclone III
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.
The ADC is 10 bit ADC and FPGA is Cyclone III EP3C16 shown in Figure12.
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:
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.
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:
Thx for this post.
Please can you tell me what board did you use in your example?
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.
Hello ,can i get the test bench.
Shwethan27@gmail.com
Thank you
Just put your email in the box on the right
I need to interface ad0808 with fpga spartan 6mini v3 will you help me with that
very useful…pl tell how to select ADC wrt to FPGA
it depends on what you need.
Do not confuse ADC with FPGA
ADC is analog to digital converter
FPGA is a digital programmable logic
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.
The AD7476 is a serial ADC. Are you able to read data from ADC?
yes it give serial data but not able to read data till now….
You can start from here to read from ADC,
http://surf-vhdl.com/how-to-design-spi-controller-in-vhdl/
Interested this article and forum
Hello,can you send the testbench of this code?
medine.bolat.287@gmail.com
hi dear,
what means is 45.056/80.000.000= 563,2 us???
Interested this article and forum
please more explain about Table2 – ADC-FPGA interface maximum storage selection
i dont know how calculate memory buffer or remaining block
Table 2 represents the M9K Altera Ram block possible configuration.
You can find the complete Altera Cyclone III description in the handbook
https://www.altera.com/content/dam/altera-www/global/en_US/pdfs/literature/hb/cyc3/cyclone3_handbook.pdf
If you use all memory block available you can store 45.056 bits.
Sampling @80 MHz (i.e. 12.5 ns)
you will fill up the entire memory in: 45.056 x 12.5 ns = 563,2 us of storage time
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.
Can you please tell me which ADC I can use to interface with cyclone iii EP3C5 board?
It depends on your requirements, I mean if you need fast ADC, maybe you should use parallel interface, if your sampling rate is slow (about up to 3 MHz) you can use a serial ADC. You can also take a look at this post:
http://surf-vhdl.com/how-to-connect-serial-adc-fpga/
really usefull post.thanks .i appreciate that.
Thank you very much for your feedback
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.
great post! thank you!
Thank You Nilesh, I really appreciate your feedback!
Thank you for the great post.
I’m now trying to read data from ADC AD7760. The clock timing diagram is complicated. Could you please teach me how to connect FPGA with such kind of ADC?
Here is the datasheet of AD7760: http://www.analog.com/media/en/technical-documentation/data-sheets/AD7760.pdf
Thank you for the great post.
I’m now trying to read data from ADC AD7760. The clock timing diagram is complicated. Could you please teach me how to make communication between FPGA and this ADC?
Here is the datasheet of AD7760: http://www.analog.com/media/en/technical-documentation/data-sheets/AD7760.pdf
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
could you please explain how block/ word and ADC word memory buffer are decided. and what is the meaning of remaining block (table-2)
No worries, I have figured out, but thanks for this information
I need to interface the ads5463 adc to a xilinx virtex 4 fpga. can u help me out ?
Please may explain about block/word, ADC word memory buffer and remaining block?
“word” is the ADC sample. In the example, a single word consists of 10 bits.
“Block” is the set of word
Hi
please I work on frequency (25-30)khz , Can you advice me which ADC can I use ?
any serial ADC should work. You have take care to the input level as well as the frequency
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.
it depends on the ADC you are interfacing.
You should read the ADC interface timing and implement a test bench that emulate that timing
Can you help me out for programming Smart fusion A2F500 FG484 FPGA board in Libero soc V11.9 software
you need the programmer. Do you have it?
Are there code vhdl for adc module with 12 bits
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?
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
Hello,can you send the testbench of this code?
medine.bolat.287@gmail.com
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!
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.
Please share ad9269 adc code for interfacing with zynq FPGA
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.
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.