You have no items in your shopping cart.

Subtotal: 0.00

DAC Interface with Spartan6 FPGA Project Kit

DAC interface with Xilinx Spartan 6 FPGA project Board

DAC

As it name implies, DAC is used to convert the form of a digital signal into the form of an analog signal. In some application, the DAC needed for interface the FPGA with some other external devices. The FPGA should process only digital value. So that devices are required such as ADC and DAC.  The function of DAC has been explained below fig 1                                     

Block diagram of DAC                                                                                                                                 

                                                            Fig 1: Block diagram of DAC

The digital input is given to DAC such as 0 or 1 which means the voltages are represented as logic 1 or 0. The binary value can be sent either the form of serial or parallel which is depends up on the chip only. Now the output of DAC would be analog.

12 Bit DAC

Here 12 bit DAC has been used on the FPGA kit which is based on SPI (Serial Peripheral Interface) protocol. The controller designed to covert the digital data into analog, where the digital data is transferred using SPI Controller and DAC (MCP4921) converts the serial data into the analog. SPI Controller controls the speed, data transmission, DAC selection etc.  As it is SPI based DAC, the number of pin in IC is low.

MCP4921

 pin diagram of MCP 4921

Fig 2: pin diagram of MCP 4921

Pin details

   

          Pin No

          Details              

                    Function

1

VDD

Power supply(2.7v to 5v)

2

CS

Chip select

3

SCK

Serial clock input

4

SDI

Serial data input

5

LDAC

Latch DAC input

6

Vref

Reference voltage

7

VSS

Ground

8

VOUT

DAC output

Pin Description

Power supply

VDD is the power supply pin of the DAC which is the range various from 2.7v to 5.5v. If use decoupling capacitor, will improve the performance of DAC.

Chip select (CS)

The CS pin is used to initiate the communication between the FPGA and DAC. If this pin is low, the conversion will initiate. If the pin is high, the conversion will terminate.

Serial clock input

 The serial clock is used to initiate the conversion and it gives clock for each bit while conversion.

Serial data input

This pin is used as clock in to input channel configuration data.

Latch DAC

The pin is called as latch DAC synchronization input. This is used to transfer the data from input latch register to the DAC register (output latch) when the pin is low.

Reference voltage (Vref)

Normally this pin is connected to VDD.

VSS

This is analog ground pin which is connected to ground of the supply.

Vout

This pin is DAC output pin. The voltage range of DAC output varies from VSS to VDD. 

Interfacing DAC with Xilinx Spartan 6 FPGA project Board

Here the FPGA connected to DAC with only three pin which is CS, SCK, SDI. Those signals are control signal for DAC. The data bit are sent to SDI of DAC and CS for initiate the conversion. VDD and VREF are connected to power supply (+5v) with decoupling capacitor. LDAC and VSS are connected to ground. The PCB connector is connected to DAC output on which the multimeter or CRO can be connected to measure the DAC output. The interfacing diagram is given below Fig 3.

interfacing Spartan6 FPGA Project Kit with DAC

Fig 3: interfacing Xilinx Spartan 6 FPGA project Board with DAC

 DAC Placement in Spartan6 FPGA Project Kit

DAC Placement in Xilinx Spartan 6 FPGA project Board

VHDL code description

The code is written to generate an analog sine wave. The input is given to Xilinx Spartan 6 FPGA project Board as 12Bit. Because of the DAC can read 12 bit only. The digital value is stored on the array. When rising edge of the clock, the sample are read and stored in some other variable. When falling edge of the clock, the chip select are enabled (CS =0). Now the conversion has been done. After that the CS are disabled (CS = 1). Finally the analog output is produced by DAC. VHDL Code is divided in to 2 parts DAC.vhd and Clockdivider.vhd

VHDL code for SPI DAC

DAC.VHD

library ieee;
use ieee.std_logic_1164.all;
use IEEE.NUMERIC_STD.ALL;

entity DAC is
	port(
		CLK: in std_logic;
		CLK2: inout std_logic;
		SCK: out std_logic;
		CS: out std_logic;
		MOSI: out std_logic
	);
end DAC;

architecture behavioral of DAC is
signal SEND: std_logic:='1';

signal i : integer range 0 to 255:=0;
signal VALUE: std_logic_vector (15 downto 0);
type memory is array (0 to 255) of std_logic_vector(15 downto 0);
constant sine : memory := (
X"8000", X"8324", X"8647", X"896a", X"8c8b", X"8fab", X"92c7", X"95e1", 
X"98f8", X"9c0b", X"9f19", X"a223", X"a527", X"a826", X"ab1e", X"ae10", 
X"b0fb", X"b3de", X"b6b9", X"b98c", X"bc56", X"bf16", X"c1cd", X"c47a", 
X"c71c", X"c9b3", X"cc3f", X"cebf", X"d133", X"d39a", X"d5f4", X"d842", 
X"da81", X"dcb3", X"ded6", X"e0eb", X"e2f1", X"e4e7", X"e6ce", X"e8a5", 
X"ea6c", X"ec23", X"edc9", X"ef5e", X"f0e1", X"f254", X"f3b5", X"f503", 
X"f640", X"f76b", X"f883", X"f989", X"fa7c", X"fb5c", X"fc29", X"fce2", 
X"fd89", X"fe1c", X"fe9c", X"ff08", X"ff61", X"ffa6", X"ffd7", X"fff5", 
X"ffff", X"fff5", X"ffd7", X"ffa6", X"ff61", X"ff08", X"fe9c", X"fe1c", 
X"fd89", X"fce2", X"fc29", X"fb5c", X"fa7c", X"f989", X"f883", X"f76b", 
X"f640", X"f503", X"f3b5", X"f254", X"f0e1", X"ef5e", X"edc9", X"ec23", 
X"ea6c", X"e8a5", X"e6ce", X"e4e7", X"e2f1", X"e0eb", X"ded6", X"dcb3", 
X"da81", X"d842", X"d5f4", X"d39a", X"d133", X"cebf", X"cc3f", X"c9b3", 
X"c71c", X"c47a", X"c1cd", X"bf16", X"bc56", X"b98c", X"b6b9", X"b3de", 
X"b0fb", X"ae10", X"ab1e", X"a826", X"a527", X"a223", X"9f19", X"9c0b", 
X"98f8", X"95e1", X"92c7", X"8fab", X"8c8b", X"896a", X"8647", X"8324", 
X"8000", X"7cdb", X"79b8", X"7695", X"7374", X"7054", X"6d38", X"6a1e", 
X"6707", X"63f4", X"60e6", X"5ddc", X"5ad8", X"57d9", X"54e1", X"51ef", 
X"4f04", X"4c21", X"4946", X"4673", X"43a9", X"40e9", X"3e32", X"3b85", 
X"38e3", X"364c", X"33c0", X"3140", X"2ecc", X"2c65", X"2a0b", X"27bd", 
X"257e", X"234c", X"2129", X"1f14", X"1d0e", X"1b18", X"1931", X"175a", 
X"1593", X"13dc", X"1236", X"10a1", X"0f1e", X"0dab", X"0c4a", X"0afc", 
X"09bf", X"0894", X"077c", X"0676", X"0583", X"04a3", X"03d6", X"031d", 
X"0276", X"01e3", X"0163", X"00f7", X"009e", X"0059", X"0028", X"000a", 
X"0001", X"000a", X"0028", X"0059", X"009e", X"00f7", X"0163", X"01e3", 
X"0276", X"031d", X"03d6", X"04a3", X"0583", X"0676", X"077c", X"0894", 
X"09bf", X"0afc", X"0c4a", X"0dab", X"0f1e", X"10a1", X"1236", X"13dc", 
X"1593", X"175a", X"1931", X"1b18", X"1d0e", X"1f1`4", X"2129", X"234c", 
X"257e", X"27bd", X"2a0b", X"2c65", X"2ecc", X"3140", X"33c0", X"364c", 
X"38e3", X"3b85", X"3e32", X"40e9", X"43a9", X"4673", X"4946", X"4c21", 
X"4f04", X"51ef", X"54e1", X"57d9", X"5ad8", X"5ddc", X"60e6", X"63f4", 
X"6707", X"6a1e", X"6d38", X"7054", X"7374", X"7695", X"79b8", X"7cdb"
		);
	signal SENDING : std_logic := '0';
	signal reg : std_logic_vector (15 downto 0);
	
	constant DELAY:integer := 3; -- 50 MHz / 3 == 16.667 MHz
	
	constant IGNORE:std_logic := '0'; -- 0:use, 1:ignore
	constant BUFFERED:std_logic := '0'; -- 0:unbuffered, 1:buffered
	constant GAIN:std_logic := '1'; -- 0:2X, 1:1X
	constant ACTIVE:std_logic := '1'; -- 0:shutdown, 1:active
	
begin


	clkDiv : entity work.ClockDivider(Behavioral) 
	generic map(DELAY => DELAY)
	port map (CLK, CLK2);
		
	process(clk2)
	begin
	if(rising_edge(clk2)) then     
		VALUE(15 downto 0) <= sine(i);
		i <= i+ 1;
		if(i = 255) then
		i <= 0;
		end if;
	end if;
	end process;
	
	process(CLK2, SEND) 
	
	variable counter : integer range 0 to 15 := 0;	
	
	begin
	
	if falling_edge(CLK2) then
		
		if SEND = '1' then	
		reg <= IGNORE & BUFFERED & GAIN & ACTIVE & VALUE(15 downto 4);
		counter := 0;	
		CS <= '0';
		SENDING <= '1';
		SEND <= '0';
				
		elsif SENDING = '1' then				
		reg <= reg(14 downto 0) & '0';
					
			if counter = 15 then		
			counter := 0;	
			CS <= '1';
			SENDING <= '0'; 
			SEND <= '1';
			else
			counter := counter + 1;	
			end if;
		end if;			
	end if;
		
	end process;
	
SCK <= CLK2 AND SENDING;
MOSI <= reg(15);
	
end behavioral;

Clockdivider.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity ClockDivider is
	GENERIC (DELAY: integer := 16 );
	PORT 
	( 
		CLK : in  STD_LOGIC;
		CLK_OUT : out  STD_LOGIC := '0'
	);
end ClockDivider;

architecture Behavioral of ClockDivider is
begin	
	
process(CLK)	
variable counter : integer range 0 to DELAY := 0;		
begin
		
	if(CLK'event AND CLK='1') then
	counter := counter + 1;
		if counter = DELAY / 2 then
		CLK_OUT <= '0';
		elsif counter = DELAY then
		counter := 0;
		CLK_OUT <= '1';
		end if;		
	end if;

end process;
end Behavioral;

User Constraint File

NET "CLK" LOC = P85;
NET "CLK2" LOC = P133;
NET "CS" LOC = P94;
NET "MOSI" LOC = P97;
NET "SCK" LOC = P95;
NET "CLK2" CLOCK_DEDICATED_ROUTE = FALSE;