# how to implement a DAC in VHDL

Status
Not open for further replies.

#### OhJ

##### Newbie level 3
hello,

can someone please help me with the basic explanation (1, 2, 3) / functionlity of how a DAC can be implemented in VHDL. Ive read so much info on the internet, im now confused. j Im wondering why things are being done differently.

My question is with regards to using a look-up table.
1) what determines the boundaries of the lookup table.
2) how do I calculate the steps based on the lookup table,
etc..

pls assist
regards
OhJ

#### K-J

hello,

can someone please help me with the basic explanation (1, 2, 3) / functionlity of how a DAC can be implemented in VHDL. Ive read so much info on the internet, im now confused.
You haven't given anyone here what you've read and what you're confused about, so all we can do is add to what you've read and maybe to your confusion...or maybe not.

First, a DAC cannot be implemented in VHDL. VHDL defines digital logic, 1 and 0, that's it. The voltage that 1 and 0 represent depends on the target device, but typically the I/O supply voltage is 3.3V and the parts can drive nearly rail to rail which means you can implent something that generates 0V and 3.3V directly. But now consider a digital signal that toggles very fast (say 100 MHz), half the time it is a 1 (3.3V), half the time it is 0 (0V). Put a multimeter on it and you'll read 3.3 / 2 = 1.65V. Look at the signal on a scope and you'll see that things are indeed toggling though. Now put a resistor in series with the output signal followed by a capacitor to ground. Make the RC time constant large enough such that the bandwidth of this filter is say 1 MHz. Now look at the node where the RC connect on the scope and you'll see a pretty stable 1.65V.

Now change the VHDL so that once every 4 clock cycles you output a 1, the other times 0. You'll now measure 3.3 / 4 = 0.82V at the RC.

Assuming you're understanding now that the ratio of ones to zeros basically defines the steady state voltage then you understand how to implement a DAC with VHDL plus an RC filter.

There are other points to consider when implementing a DAC, but since you asked no specific question with your post, I'll just leave it at this for now.

Im wondering why things are being done differently.
What's wrong with different? Not to mention 'different' from what?

My question is with regards to using a look-up table.
1) what determines the boundaries of the lookup table.
2) how do I calculate the steps based on the lookup table,
etc..
What lookup table? The above mentioned description for how to create a DAC requires no lookup table. The digital output is a pulse width modulated signal which can be implemented with at most two counters and nothing else.

Consider adding more specifics to whatever questions you actually have.

Kevin Jennings

graphene

### graphene

points: 2

#### gongdori

##### Full Member level 2
As Kevin said, FPGA cannot output somewhere between logic 1 and logic 0. Thus, you cannot implement a DAC with only FPGA.
But, you can also implement DAC with multiple output pins of FPGA and resistor network. You will get more information about it if you search R-2R ladder network.

#### OhJ

##### Newbie level 3
hello sirs,

I asked my question after reading several stuffs on the internet about DAC in VHDL, sine wave in VHDL, etc., for example: below:
http://www.doulos.com/knowhow/vhdl_designers_guide/models/analogtodigital_converter_model/
http://www.scribd.com/doc/60291432/...erter-circuitry-and-VHDL-code-for-the-DAC0808,

etc., I forgot the others. So I myself was now wondering what the basic concept of a DAC in VHDL is.

Thanks for your updates. Im working with a Nexys2 board and their DAC PMOD, which they say can convert digital to analog signals:
http://digilentinc.com/Products/Detail.cfm?NavPath=2,401,501&Prod=PMOD-DA1

so maybe I should be looking for how to control the PMOD instead?

On the other hand, what kind of input am I supposed to have for a DAC? suppose I am trying to control a DAC chip with VHDL. For ex: Somebody told me that I could have an 8bit digital input, for ex: "FF" or whatever which is fed into my system and this could be converted into an analog signal. I wasnt too comfortable with the explanation as I wondered how such could be done with pen and paper at least.

My idea is a system, suppose after synthesis, etc, and then I program my board with the .bit file, and then I can give inputs to the design using external sources: switches, whatever. Is this idea correct? I dont think so, but please help me clarify.

About the lookup table I mentioned earlier, I dont know how I got to the link, but the idea there was that there were some values hardcoded in a case statement, used as the DAC's inputs. My dilema here was how the beginning and ending values are determined, how the intervals are calculated and the relationships between them, etc. Ill look for the link and post it.

regards
OhJ

#### gongdori

##### Full Member level 2
The first link shows how to "model" DAC in VHDL. You cannot implement it on real circuit, but simulate it.
The second link shows how to build a interface module in VHDL to a specific DAC. In this case, you need to have a board with the FPGA and the specific silicon.
I hope it helps...

#### Kepsz

##### Member level 1
Pmod DA1 is outdated, if i know right, currently only DA2 is able to buy. (at least in Hungary only DA2 avaible)

Pmod DA2 is waits for 12 bit vector in the input ( in 16 bit form where 16 - 13 bits are control bits), so u can set the output voltage between gnd and V+ (3.3V?) in 4095 steps. This communication is a simply serial communication, wich can works up to 30MHz ( frequency is limited by DA2's capabilties ).

The DAC's very simple, if it's got the input, it will sets the output immideatly and keeps it while new data arrives.

This code below is the actualised version of Digilent's bit outdated example code for pmod DA2, using ieee.numeric_std instead of arith and others...:

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.numeric_std.all;

entity DAC is
Port (
CLK, RST, START					: in std_logic;
D1, D2, CLK_OUT, nSYNC,DONE	: out std_logic;
DATA1, DATA2    					: in std_logic_vector(11 downto 0));
end DAC;

architecture Behavioral of DAC is
type states is (Idle,ShiftOut,SyncData);
signal current_state 		: states;
signal next_state    		: states;
signal temp1, temp2			: std_logic_vector(15 downto 0);
signal clk_div, shiftCounter, enShiftCounter, enParalelLoad       : std_logic;

begin

clkdiv: process(clk, rst)
variable clk_counter : integer range 0 to 5;  --for 120MHz system clock. 120/5 = 24MHz serial clock.
begin
if (rising_edge(clk)) then
if (rst = '1') then
clk_div <= '0';
clk_out <= '0';
clk_counter := 0;
else
if (clk_counter = 5) then
clk_div <= '1';
clk_out <= '1';
clk_counter := 0;
else
clk_div <= '0';
clk_out <= '0';
clk_counter := clk_counter + 1;
end if;
end if;
end if;
end process;

counter : process(clk_div, shiftcounter, enParalelLoad, enShiftCounter, DATA1, DATA2)
variable count : integer range 0 to 15;
begin
if (rising_edge(clk_div)) then
shiftCounter <= '0';
temp1 <= "0000" & DATA1;
temp2 <= "0000" & DATA2;
elsif (enShiftCounter = '1') then
temp1 <= temp1(14 downto 0)&temp1(15);
temp2 <= temp2(14 downto 0)&temp2(15);
count := count + 1;
if (count = 15) then
shiftcounter <= '1';
end if;
end if;
end if;
end process;

D1 <= temp1(15);
D2 <= temp2(15);

SYNC_PROC: process (clk_div, rst)
begin
if (rising_edge(clk_div)) then
if (rst = '1') then
current_state <= Idle;
else
current_state <= next_state;
end if;
end if;
end process;

OUTPUT_DECODE: process (CLK, current_state)
begin
if (rising_edge(CLK)) then
if (current_state = Idle) then
enShiftCounter <='0';
DONE <='1';
nSYNC <='1';
elsif (current_state = ShiftOut) then
enShiftCounter <='1';
DONE <='0';
nSYNC <='0';
else
enShiftCounter <='0';
DONE <='0';
nSYNC <='1';
end if;
end if;
end process;

NEXT_STATE_DECODE: process (CLK, current_state, START, shiftCounter)
begin
if (rising_edge(CLK)) then
next_state <= current_state;
case (current_state) is
when Idle =>
if (START = '1') then
next_state <= ShiftOut;
end if;
when ShiftOut =>
if (shiftCounter = '1') then
next_state <= SyncData;
end if;
when SyncData =>
if (START = '0') then
next_state <= Idle;
end if;
when others =>
next_state <= Idle;
end case;
end if;
end process;
end Behavioral;
This code is fully works, just edit the clkdiv process for your board's base clock.