Controlling an AD7303 DAC with VHDL

Status
Not open for further replies.

GeoMX

New Member
Hi everybody . I'm working on a couple of projects that will need analog<->digital conversion. I've been required to work using an FPGA (I have a Spartan 3 Starter board) and the AD7823 (ADC) and AD7303 (DAC) serial converters, I got this board from Digilent: Digilent Analog I/O 1. I've managed to control the ADC (after some corrections to my program), but I've been trying several times and had no success with the DAC. So I'd like to ask whether you've worked with this chip and/or if you have any advice/idea what I may be doing wrong .

This is my current code (I've been changing it a bit):

Code:
-- Control AD7303
-- José Jorge Enríquez Rodríguez
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity control_dac is
	port(
		clk_50MHz: in std_logic;	-- Board clock (50 MHz)
		reset: in std_logic;
		data: in std_logic_vector( 7 downto 0 );	-- Data
		dac_sync: out std_logic;
		dac_sclk: out std_logic;
		dac_din: out std_logic
	);
end control_dac;

architecture Behavioral of control_dac is

begin

	process( reset, clk_50MHz )
		variable temp: integer := 0;
	begin
		if ( reset = '1' ) then
			temp := 0;
			dac_sync <= '1';
			dac_sclk <= '0';
			dac_din <= '0';
		elsif ( rising_edge( clk_50MHz ) ) then
			temp := temp + 1;
			if ( temp < 3 ) then				  -- Starts sync high
				dac_sync <= '1'; dac_sclk <= '0';
			elsif ( temp < 5 ) then
				dac_sync <= '1'; dac_sclk <= '1';	-- Ends sync high
			elsif ( temp < 7 ) then				-- Starts data transfer (bit 16)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- Internal reference
			elsif ( temp < 9 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 11 ) then			-- (bit 15)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- Uncommited bit
			elsif ( temp < 13 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 15 ) then			-- (bit 14)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- LDAC
			elsif ( temp < 17 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 19 ) then			-- (bit 13)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '1';	-- Disables channel B
			elsif ( temp < 21 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 23 ) then			-- (bit 12)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- Enables channel A
			elsif ( temp < 25 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 27 ) then			-- (bit 11)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- Address channel A
			elsif ( temp < 29 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 31 ) then			-- (bit 10)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '0';	-- CR1
			elsif ( temp < 33 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 35 ) then			-- Last config bit (bit 9)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= '1';	-- CR0 (update DAC input reg. from shift register)
			elsif ( temp < 37 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 39 ) then			-- MSB data (bit 8)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 7 );
			elsif ( temp < 41 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 43 ) then			-- (bit 7)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 6 );
			elsif ( temp < 45 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 47 ) then			-- (bit 6)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= dato_paralelo( 5 );
			elsif ( temp < 49 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 51 ) then			-- (bit 5)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 4 );
			elsif ( temp < 53 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 55 ) then			-- (bit 4)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 3 );
			elsif ( temp < 57 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 59 ) then			-- (bit 3)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 2 );
			elsif ( temp < 61 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 63 ) then			-- (bit 2)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 1 );
			elsif ( temp < 65 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			elsif ( temp < 67 ) then			-- LSB data(bit 1)
				dac_sync <= '0'; dac_sclk <= '0';
				dac_din <= data( 0 );
			elsif ( temp < 68 ) then
				dac_sync <= '0'; dac_sclk <= '1';
			else
				temp := 0;
			end if;
		end if;
	
	end process;

end Behavioral;
This is my simulation output (test bench waveform module in Xilinx ISE):
**broken link removed**

I'm trying this:
- sclk toggles every two rising edges of the 50 MHz clock in the Spartan board.
- sync stays high for 40ns and then changes to 0 while the data (16 bits) is sent to the AD7303.
- data bits are put on din when sclk is low, the AD7303 is supposed to read on sclk's highs.

I'm simulating the 8 bit value to convert using the eight slide switches included in the Spartan3 board, but the AD7303 output does not change when I open/close the switches. I'm powering the AD7303 with 5Vcc, and using its internal reference.

Please, any advice/comment will be of help. I'm trying to get another AD7303 to confirm mine is not damaged, since I think my program should work .

Thanks for your attention,
José Jorge Enríquez.
 
Last edited:
Look at the register diagram and the control register/CR0/CR1 table more closely. You're not updating the DAC register, only the input register. The line you want is CR1=1, CR0=0.

The VHDL code could use a lot more work - Look under the ISE menu Edit > language templates, then go to VHDL > Synthesis Constructs > Coding Examples and read up on multiplexers or shift registers. Either of them would make your code much easier to read/write.
 
Thank you so much for your comments hjames. I was sure the program should work that way, it worked next day when testing it again . I have a doubt though, I'm working with AD7303's internal reference, I though the output should range from 0 to this reference, but the output really ranges from 0 to Vdd (as stated in the datasheet), is it correct? It's just that I thought it should range from 0 to Vref from my prior experience with AD converters .

And yep, it's really ugly code for electronics circuit, but I think it's really explicit . I worked the same for the ADC, but now I should work on improving them. I'll use an eight shift register + control unit for the ADC, and a similar structure for this one (the DAC).

Again, thans a lot for your help,
José Jorge Enríquez R.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…