Intel® FPGA University Program
University Program Material, Education Boards, and Laboratory Exercises
1174 Discussions

Generate Triangular Wave Table

Altera_Forum
Honored Contributor II
4,196 Views

Hello! 

 

I'm doing a project at school using the DE2 board as the digital controller of a DC-AC inverter. The goal is to output a 120V 60Hz sine wave from a ~300VDC input.  

 

Right now the design uses a ADC to read in the values of current output (scaled down of course) and this is to be compared with the Altera board to a 60Hz triangular wave (of equal magnitude scale) so that the board can control the gates of the inverter. 

 

 

I read this post on the forum: http://www.alteraforum.com/forum/showthread.php?t=4365&highlight=triangle 

 

but I'm still a little confused. One person suggested doing the triangle wave in logic (accumulator) and other people mentioned the Altera Megafunction generator. 

 

My plan was to either save in the values of the perfect 60Hz triangular wave to a table that can be compared to the value read in from the ADC and control the correction accordingly. 

 

I read on another post about using Matlab to generate VHDL code? Is it possible to make a triangle function in Matlab then export it some how to VHDL? 

 

Thanks a bunch guys, 

 

-J
0 Kudos
7 Replies
Altera_Forum
Honored Contributor II
2,335 Views

Hi, 

 

Things are done in different ways. For a triangular wave I will use a counter. 

It is easy but there are some subtleties. 

Remember the period of your wave = Fs/60 where Fs is your clk frequency or enable frequency. To get things clean and without dc offset I can use Fs of 6KHz then the period = 100 so I can use an 8 bit counter that goes from  

(-125 to 125) and back incrementing/decrementing by 5. (check that your ADC uses 2'Scomplement) 

 

The following untested code gives you the idea of getting 100 samples per period: 

The wave goes from -125 to 125 (51 samples) then 120 to -120 (49 samples)  

signal count : signed(7 downto 0); 

------ 

process(reset,clk) -- assuming clk = 6KHz 

if reset= '1' then 

count <= -125; 

updown <= '0'; 

elsif rising_edge(clk) then 

 

if updown = '0' then 

if count < 125 

count <= count + 5; 

end if; 

 

if count = 120 then 

updown <= '1'; 

end if; 

 

else -- if updown = '1' then 

if count >-125 

count <= count - 5; 

end if; 

 

if count = -120 then 

updown <= '0'; 

end if; 

end if; 

 

end if; 

end process; 

 

output <= std_logic_vector(count);
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

 

--- Quote Start ---  

Hi, 

 

Things are done in different ways. For a triangular wave I will use a counter. 

It is easy but there are some subtleties. 

Remember the period of your wave = Fs/60 where Fs is your clk frequency or enable frequency. To get things clean and without dc offset I can use Fs of 6KHz then the period = 100 so I can use an 8 bit counter that goes from  

(-125 to 125) and back incrementing/decrementing by 5. (check that your ADC uses 2'Scomplement) 

 

The following untested code gives you the idea of getting 100 samples per period: 

The wave goes from -125 to 125 (51 samples) then 120 to -120 (49 samples)  

signal count : signed(7 downto 0); 

------ 

process(reset,clk) -- assuming clk = 6KHz 

if reset= '1' then 

count <= -125; 

updown <= '0'; 

elsif rising_edge(clk) then 

 

if updown = '0' then 

if count < 125 

count <= count + 5; 

end if; 

 

if count = 120 then 

updown <= '1'; 

end if; 

 

else -- if updown = '1' then 

if count >-125 

count <= count - 5; 

end if; 

 

if count = -120 then 

updown <= '0'; 

end if; 

end if; 

 

end if; 

end process; 

 

output <= std_logic_vector(count); 

--- Quote End ---  

 

 

Hi !  

 

I tried using this code but I'm getting errors with the minus sign in front of 125. How should it be placed on the code ?
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

Declare count as: 

signal count: signed(7 downto 0);
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

 

--- Quote Start ---  

Hi, 

 

Things are done in different ways. For a triangular wave I will use a counter. 

It is easy but there are some subtleties. 

Remember the period of your wave = Fs/60 where Fs is your clk frequency or enable frequency. To get things clean and without dc offset I can use Fs of 6KHz then the period = 100 so I can use an 8 bit counter that goes from  

(-125 to 125) and back incrementing/decrementing by 5. (check that your ADC uses 2'Scomplement) 

 

The following untested code gives you the idea of getting 100 samples per period: 

The wave goes from -125 to 125 (51 samples) then 120 to -120 (49 samples)  

signal count : signed(7 downto 0); 

------ 

process(reset,clk) -- assuming clk = 6KHz 

if reset= '1' then 

count <= -125; 

updown <= '0'; 

elsif rising_edge(clk) then 

 

if updown = '0' then 

if count < 125 

count <= count + 5; 

end if; 

 

if count = 120 then 

updown <= '1'; 

end if; 

 

else -- if updown = '1' then 

if count >-125 

count <= count - 5; 

end if; 

 

if count = -120 then 

updown <= '0'; 

end if; 

end if; 

 

end if; 

end process; 

 

output <= std_logic_vector(count); 

--- Quote End ---  

 

 

Hi,  

 

I've been trying to generate a triangular wave that can go up to 76, based on your example. The waveform goes up to 64, then goes down with negative values until a point then goes to 63 to count down properly. What could be the problem ? 

P.S :See attached file
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

 

--- Quote Start ---  

Hi, 

 

Things are done in different ways. For a triangular wave I will use a counter. 

It is easy but there are some subtleties. 

Remember the period of your wave = Fs/60 where Fs is your clk frequency or enable frequency. To get things clean and without dc offset I can use Fs of 6KHz then the period = 100 so I can use an 8 bit counter that goes from  

(-125 to 125) and back incrementing/decrementing by 5. (check that your ADC uses 2'Scomplement) 

 

The following untested code gives you the idea of getting 100 samples per period: 

The wave goes from -125 to 125 (51 samples) then 120 to -120 (49 samples)  

signal count : signed(7 downto 0); 

------ 

process(reset,clk) -- assuming clk = 6KHz 

if reset= '1' then 

count <= -125; 

updown <= '0'; 

elsif rising_edge(clk) then 

 

if updown = '0' then 

if count < 125 

count <= count + 5; 

end if; 

 

if count = 120 then 

updown <= '1'; 

end if; 

 

else -- if updown = '1' then 

if count >-125 

count <= count - 5; 

end if; 

 

if count = -120 then 

updown <= '0'; 

end if; 

end if; 

 

end if; 

end process; 

 

output <= std_logic_vector(count); 

--- Quote End ---  

 

See my attached file. What could be the problem ?
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

Don't read too much into my syntax and especially >, < etc. 

The purpose is to give the idea only. 

 

A neat way is to have two states (s1,s2) 

in s1 : count goes up and change state 

in s2: count goes down and change state
0 Kudos
Altera_Forum
Honored Contributor II
2,335 Views

 

--- Quote Start ---  

Don't read too much into my syntax and especially >, < etc. 

The purpose is to give the idea only. 

 

A neat way is to have two states (s1,s2) 

in s1 : count goes up and change state 

in s2: count goes down and change state 

--- Quote End ---  

 

 

I've managed to fix that code and it can now produce a PWM by comparing it with a sine wave , using a look up table in VHDL, but now I was asked to produce a sine wave with a C code written for a Nios II core. I've actually written one, but using sin function. Would it be better if I write one with the look up table instead? And plz do you have a simple example for such a code?
0 Kudos
Reply