ADC interfacing with Spartan 6 FPGA project Board
The Analog to digital converter (ADC) is used to convert analog signal into digital signal. To process the analog signal onto digital devices like as FPGA which should be converted as digital form. The analog form means such as voltage or current. After the signal conversion, data is processed using FPGA.
The ADC input is analog signal such a current or voltage form and output as binary form (0 or 1). ADC conversion is given below Fig 1
Fig1: Block diagram of ADC
Many type of ADC available for conversion of signal. There are
a) Flash ADC
b) Dual slope ADC
c) Successive approximation ADC
d) Sigma- delta ADC
12 Bit SPI ADC
These ADCs are SPI Bus based which is a serial communication Protocol. So the number of pins in IC is very low. The MCP3202 IC is based on SAR Conversion technique. It has only 8 pins which are showed below Fig2.
Successive approximation register method
In this type of ADC contain the register (SAR), initially the MSB bit of SAR will be 1. Then the register monitor comparator output if the binary values of SAR greater or less then analog input and adjusted the binary value according to it.
Fig2: Pin diagram of MCP3202
Shutdown/chip select (SHDN/CS)
The SHDN/CS pin is used to initiate the communication between the FPGA and ADC. If this pin is low, the conversation will initiate. If the pin is high, the device will go standby mode.
There are two independent channels which are called as CH0/CH1. These channels can be programmed as two independent channels in single mode or a single pseudo differential input where one is IN+ and other one is IN-.
This pin is connected to GND.
Serial input (Din)
This pin is used as clock in to input channel configuration data.
Serial data out (Dout)
This pin can be used as shit out the result of the serial conversion. The data will be change on the falling edge of each clock.
Serial clock (SCK)
The serial clock is used to initiate the conversion and it gives the clock for each bit of conversion.
This both pins are common for supply and reference input of the ADC.
Interfacing SPI ADC with Spartan 6 FPGA project Board
The Spartan3an FPGA Project Kit has 2-channel 12 Bit SPI ADC, indicated as in Figure. As you know in synchronous serial communication there is a clock line (SCK in case of SPI) which synchronizes the transfer.
The clock is always controlled by the MASTER. In our case the FPGA is the MASTER and the MCP3202 is a slave on the bus. SPI is full duplex, which means data can be sent and received simultaneously.
A SPI transfer is initiated by the MASTER pulling the CS line low. The CS line sits at HIGH during idle state. Now master can write to the bus in 8bit (or 1 byte) chunks.
One most important thing to note about SPI is that for every byte MASTER writes to SLAVE the MASTER receives one byte in return. So the only transaction possible is exchange of data.
Fig3: Interfacing ADC with Spartan 6 FPGA project Board
VHDL Code description
The code has been written as read samples from the variable POT on the Spartan 6 FPGA project Board and compare with reference (Vdd/Vref) voltage. Finally the equivalent Binary values are generated with help of Vref. The output of ADC would be 12 bit value which is shown on the 12 LEDs. Here the jumper has been used to select the internal &external analog input. Among the two channels one channel for POT analog input and another one for Temperature sensor.
VHDL code for ADC
library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity adc_ch0 is port ( clk : in std_logic; cs : out std_logic; sc : out std_logic; do : out std_logic; din : in std_logic; led : out std_logic_vector(11 downto 0)); end adc_ch0; architecture Behavioral of adc_ch0 is type state is (spi,conversion,transmission); signal presentstate : state := spi; signal f : std_logic; type arr is array (0 to 12) of std_logic_vector(9 downto 0); signal store : arr; begin process(clk) --variable i : std_logic_vector(12 downto 0) := "0000000000000"; variable i,j,k : integer := 0; variable tot : std_logic_vector(11 downto 0) := "000000000000"; begin if clk'event and clk = '1' then if presentstate = spi then if i <= 50 then ---"0000000110010" then i := i + 1; sc <= '1'; elsif i > 50 and i < 100 then ---"0000000110010" and i < "0000001100100" then i := i + 1; sc <= '0'; elsif i = 100 then ---"0000001100100" then i := 0; ----"0000000000000"; if j < 18 then j := j + 1; elsif j = 18 then presentstate <= conversion; j := 0; end if; end if; if j = 0 or j >= 18 then cs <= '1'; else cs <= '0'; end if; if i > 40 and i < 60 then --- "0000000101000" and i < "0000000111100" then case j is when 0 => do <= '0'; when 1 => do <= '1'; when 2 => do <= '1'; when 3 => do <= '0'; -----channel bit when 4 => do <= '1'; when others => null; end case; end if; if i >= 0 and i < 10 then --"0000000000000" and i < "0000000001010" then case j is when 6 => tot(11) := din; when 7 => tot(10) := din; when 8 => tot(9) := din; when 9 => tot(8) := din; when 10 => tot(7) := din; when 11 => tot(6) := din; when 12 => tot(5) := din; when 13 => tot(4) := din; when 14 => tot(3) := din; when 15 => tot(2) := din; when 16 => tot(1) := din; when 17 => tot(0) := din; when others => null; end case; end if; end if; -------------------------------------------------------------- if presentstate = conversion then cs <= '1'; led <= tot; if i < 5000 then --"1001110001000" then i := i + 1; elsif i = 5000 then --"1001110001000" then i := 0; ---"0000000000000"; presentstate <= spi; end if; end if; end if; end process; end Behavioral;
User Constraint File
NET "clk" LOC = P85; NET "cs" LOC = P87; NET "din" LOC = P92; NET "do" LOC = P93; NET "sc" LOC = P88; NET "clk" LOC = P85; NET "cs" LOC = P87; NET "din" LOC = P92; NET "do" LOC = P93; NET "sc" LOC = P88; NET "led" LOC = P34; NET "led" LOC = P61; NET "led" LOC = P62; NET "led" LOC = P35; NET "led" LOC = P38; NET "led" LOC = P40; NET "led" LOC = P41; NET "led" LOC = P43; NET "led" LOC = P44; NET "led" LOC = P45; NET "led" LOC = P58; NET "led" LOC = P59;