Hamster FPGA tutorials. 8 bit DAC. Questions.


mubase

Recommended Posts

Hi all. Back again with a question about the IntroToSPartanFPGA tutorials from Mike.

I have been trying to understand this chapter on 8 bit DAC and output of waveforms in the audio range.

I get the 8 bit DAC code:

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity dac8 isPort ( Clk : in STD_LOGIC;Data : in STD_LOGIC_VECTOR (7 downto 0);PulseStream : out STD_LOGIC);end dac8;architecture Behavioral of dac8 issignal sum : STD_LOGIC_VECTOR (8 downto 0);beginPulseStream <= sum(8);process (clk, sum)beginif rising_edge(Clk) thensum <= ("0" & sum(7 downto 0)) + ("0" &data);end if;end process;end Behavioral;

 

and have generated a .COE file containing 128 numbers in decimal from 28 to 228 for a lookupt table for the ROM block. Do I now need to generate a counter using the Core gen? Also, how do I send the wave out of the P41 mono audio output on the logicstart (i.e what do i send to it?) Ive tried sending the douta to it but I don't think I know what I am doing...

Link to comment
Share on other sites

You should put the PulseStream into the IO pin for the mono output, this is a sigma-delta DAC it converts the audio to a stream of pulses which have the property that their average value is the same as that of the input data, this stream of pulses is then averaged by the analog low pass filter on the mono output on the logic start.

 

You will need to drive the dac8 clock at something rather high, for now the system clock of 32MHz or so should do,  then you need to feed the waveform into it at the required sample rate, (44100Hz or so) which will require dividing the clock down to the audio sample rate and counting up through the lookup table at that rate.

Link to comment
Share on other sites

Thanks for the hints but nope.I'm going round in circles and am getting frustrated.  How big should the BRAM be? and do I need to generate a counter like in the chapter before on using B RAM?

How many values must I put into the coe file?

 

Sorry to appear so thick. You must excuse me but I am an absolute beginner with this stuff  as much as I am enthusiastic about learning.. :S

Link to comment
Share on other sites

Hi - I don't mind at all.

 

You can here frequency from about 20 cycles per second to maybe 15,000 cycles per second.

 

So if you create a 25 bit counter (24 downto 0) and hook the most significant bit to the audio socket you will hear approx two clicks per second - once for the rising edge, and once for the falling edge.

 

If you keep making the counter, somewhere about bit 21 the clicks will become a low pitched buzz, and maybe about 20 bits it will be perceived as a tone -  you are hearing a 30Hz square wave.

 

If you keep making the counter shorter, at about 17 bits you will have an annoying continuous tone. This tone is 32,000,000/(2^17) = 244 cycles per second (Hz).

 

So, now how to make more complex sounds....

 

If you hook counter(16 downto 9) to the DAC, and the output of the DAC to the headphone you should get a signal of the same pitch/frequency, but of a different tonal quality. The waveform is a "ramp" created as the counter's bits count up from 0 to 255.

 

Now hook the same 8 bits of the counter into the address signals of block ram, and then use the output of the RAM as the input to the DAC. If you have set the RAM to hold "data[x] = sine(x/256*pi()*2)" then you should hear a "8-bit pure" sine wave.

 

Still with me?

 

Now make the counter 5 bits bigger (21 downto 0), feeding counter(21 downto 14) into the address of  the BRAM, and rather than adding just '1' every cycle, add the value that is set by the switches.

 

You will now be able to generate 255 different frequencies, from around 7 HZ to about 2000Hz, by changing the switches. if you set all the switches to 0 then the sound will stop.

 

The size of the BRAM dictates two things - the bit depth of the sample (i.e. how 'steppy' the output waveform is in voltage), and how 'steppy' the waveform is in time. If there is 16 bits resolution in voltage, and around 1/44,000 of a second steps in time between samples then the audio will be near CD in quality. For the lowest audio frequencies (50 Hz) this this requires around 2000 samples for the waveform.  For  "voice quality"  8- bit samples and a table of 256 samples is fine. 

Link to comment
Share on other sites

OK I can generate different frequencies by changing the MSB in the count. 

i.e.

entity audio is    Port ( clk : in  STD_LOGIC;           audio : out  STD_LOGIC;           switch : in  STD_LOGIC_VECTOR (7 downto 0));end audio;architecture Behavioral of audio issignal count : unsigned (15 downto 0) := (others => '0');begin	audio <= std_logic(count(15)); -- MSB out to audio pin. 32000000/(2^15) gives 977 Hz --process (clk)	begin		if rising_edge(clk) then			count <=count+1;			end if;			end process;end Behavioral;

 

I still don't get how to connect counter (16 downto 9) to dac_out. I assume you are referring to the 8 bit DAC code in the tutorial (generating analogue signals.) 

:(

Link to comment
Share on other sites

Hi Mike ( or anyone else looking at his post.)

I've been burning brain cells still trying to understand this.

I did manage to get a sawtooth wave of approx. 500Hz using this code:

entity audio is    Port ( clk : in  STD_LOGIC;           audio : out  STD_LOGIC;           switch : in  STD_LOGIC_VECTOR (7 downto 0));end audio;architecture Behavioral of audio issignal count : unsigned (15 downto 0) := (others => '0');signal pulses         : std_logic; signal data         : std_logic_vector(7 downto 0);COMPONENT dac8   PORT(       Clk : IN std_logic;             Data : IN std_logic_vector(7 downto 0);                 PulseStream : OUT std_logic       );   END COMPONENT;begin	Data <= std_logic_vector(count(15 downto 9));	audio<=pulses;dac8_01: dac8        PORT MAP(           Clk => clk,                     Data => data,           PulseStream => pulses);process (clk)	begin		if rising_edge(clk) then			count <=count+1;			end if;			end process;end Behavioral;

 

With the DAC code looking like this:

 

library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_ARITH.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity dac8 isPort ( Clk : in STD_LOGIC;Data : in STD_LOGIC_VECTOR (7 downto 0);PulseStream : out STD_LOGIC);end dac8;architecture Behavioral of dac8 issignal sum : STD_LOGIC_VECTOR (8 downto 0);beginPulseStream <= sum(8);process (clk, sum)beginif rising_edge(Clk) thensum <= ("0" & sum(7 downto 0)) + ("0" &data);end if;end process;end Behavioral;

 

I would include an oscilloscope image showing the resulting saw wave on a scopex oscilloscope set to 1V/div and 1mS timing/CM but the site won't let me.. :(

 

Does the code make sense to you?  :wacko:

Is it right?

It looks and sounds like a saw wave....

:D

I must be doing something right??

 

 

 

 

Link to comment
Share on other sites

Cracked it finally! 

 

So I Generated a block ram of 8 x 256, added a .coe file for 255 values between 28 and 228 that I generated using a simple program in "Processing.", changed the counter for address and connected the memory to the DAC as suggested. I had to change the counter to 15 downto 8 as the address was set at 8 bits.

The results are in the attachment. The sine came out at 500Hz

Very nice looking sinw wave! Now I have sine, sqr and saw.

Thankyou very much Mike for being patient and helping me to get it.

Now I might be able to understand your synth project on the hamster projects wiki and also have a go at generating different frequencies & I can carry on with your book.

Its all lookin rosy.

:)

 

 

post-36458-0-02247000-1361904144_thumb.j

Link to comment
Share on other sites

  • 1 month later...

Archived

This topic is now archived and is closed to further replies.