Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

sine wave pwm technique fpga

Status
Not open for further replies.

franticEB

Full Member level 3
Full Member level 3
Joined
May 10, 2010
Messages
153
Helped
1
Reputation
2
Reaction score
2
Trophy points
1,298
Visit site
Activity points
2,551
hi,
with my fpga altera i've to generate a pwm signal for a 40-180Hz sine wave.
I've started from this application note **broken link removed** and i've used the vhdl of ddfs to generate the wave. I've modified the parameter in order to obtain an out frequency of 1Hz for Freq_Data=1 and a 243HZ for Freq_Data=255. So For 1MHz sys clock the accumulator is 20 bit lenght.
This method seems to work for a DAC input, but my problem is PWM...
How could convert my output data to pwm? Are correct the parameters i've imposed? i've tried the pwm methods suggested but they didn't work.
Could you help me or give me some advices on how implement that generator?
Thanks
 

i've tried the pwm methods suggested but they didn't work.
Not very specific, I think. Provided you have a pwm code, you can test it with constant duty cycle first then connect the sine signal and check the output. Every step can be verified in functional simulation.
 

Which step is particularly unclear? I think,the problem can be better understood if you post the code you have so far.
 

this is the dds code
Code:
-- Design IOs :
-- Clk : Global Clock input
-- Rst : Global Reset input
-- Freq_data : 8-bit frequency control vector
-- from DIP switches on the board.
-- Dout : is signed 8-bit output to the DAC.
-- -----------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
-- -----------------------------------------------
Entity DDFS is
-- -----------------------------------------------
Port ( CLK : in std_logic;
	   RST : in std_logic;
	   Freq_Data : in std_logic_vector (7 downto 0);
	   PWMout : out std_logic;
       Dout : out std_logic_vector (7 downto 0)
	 );
end DDFS;
-- -----------------------------------------------
Architecture RTL of DDFS is
-- -----------------------------------------------
signal Address : unsigned (6 downto 0);
signal Result : std_logic_vector (7 downto 0);
signal Accum : unsigned (19 downto 0); -- we want very low Frequencies !
signal Sign : std_logic;
signal Cnt : unsigned (7 downto 0);
signal pwm_clk_cnt,clk_cnt : integer;
signal i_dout : std_logic_vector(7 downto 0);
signal CLK_PWM,clk_dds :std_logic;
begin

-- Signed Accumulator
-- ------------------
Acc: process (CLK,RST)
begin
	if RST='1' then
		Accum <= (others=>'0');
	elsif rising_edge(CLK) then
		Accum <= Accum + unsigned(Freq_Data);
	end if;
END process acc;

Sign <= Accum(Accum'high); -- MSB

-- Lookup Table Index calculation
-- ------------------------------
Address <= unsigned(Accum(Accum'high-1 downto Accum'high-Address'length)); --accum(27 dwonto 21)
-- SINE Look-Up TABLE
-- -------------------
-- Inference of an Asynchronous Rom.
-- A synchronous one would be better, but we register the output.
-- This table has been built by GENVEC.exe (C program)
-- We use only positive values ! (sign comes from quadrant info)
-- This could be further optimized by coding only one quadrant...
lookup: process (Address)
subtype SLV8 is std_logic_vector (7 downto 0);
type Rom128x8 is array (0 to 127) of SLV8; -- 0 to 2**Address'length - 1
constant Sinus_Rom : Rom128x8 := (
	x"00", x"03", x"06", x"09", x"0c", x"0f", x"12", x"15",
	x"18", x"1b", x"1e", x"21", x"24", x"27", x"2a", x"2d",
	x"30", x"33", x"36", x"39", x"3b", x"3e", x"41", x"43",
	x"46", x"49", x"4b", x"4e", x"50", x"52", x"55", x"57",
	x"59", x"5b", x"5e", x"60", x"62", x"64", x"66", x"67",
	x"69", x"6b", x"6c", x"6e", x"70", x"71", x"72", x"74",
	x"75", x"76", x"77", x"78", x"79", x"7a", x"7b", x"7b",
	x"7c", x"7d", x"7d", x"7e", x"7e", x"7e", x"7e", x"7e",
	x"7f", x"7e", x"7e", x"7e", x"7e", x"7e", x"7d", x"7d",
	x"7c", x"7b", x"7b", x"7a", x"79", x"78", x"77", x"76",
	x"75", x"74", x"72", x"71", x"70", x"6e", x"6c", x"6b",
	x"69", x"67", x"66", x"64", x"62", x"60", x"5e", x"5b",
	x"59", x"57", x"55", x"52", x"50", x"4e", x"4b", x"49",
	x"46", x"43", x"41", x"3e", x"3b", x"39", x"36", x"33",
	x"30", x"2d", x"2a", x"27", x"24", x"21", x"1e", x"1b",
	x"18", x"15", x"12", x"0f", x"0c", x"09", x"06", x"03" );
begin
Result <= Sinus_Rom (to_integer(Address));
END process lookup;
-- Output registers
-- ----------------
outreg : process(CLK,RST)
begin
	if RST='1' then
		i_dout <= (others=>'0');
		
	elsif rising_edge(CLK) then
		if Sign='1' then
			i_dout <= Result;
		else
			i_dout <= std_logic_vector (- signed(Result));
		end if;
	end if;
end process outreg;
Dout<=i_dout;

end RTL;

and this is the pwm methods suggested by application note
Code:
library IEEE;
  use IEEE.std_logic_1164.all;
  use IEEE.numeric_std.all;

-- -----------------------------------------
    Entity PWM is
-- -----------------------------------------
    Port (    Rst : In  std_logic;
              Clk : In  std_logic;
              Din : In  std_logic_vector (8 downto 0);
           PWMout : Out std_logic );
end PWM;


-- -----------------------------------------
    Architecture RTL_Accum of PWM is
-- -----------------------------------------
-- AKA "One-Bit DAC", "1st order delta-sima", "Pulse distribution PWM"...
-- Usually not very suitable for motor control.
-- Very useful for audio signals synthesis for example,
-- by driving a simple RC filter...

signal Accum : unsigned (8 downto 0);

begin

U1: process (Clk,Rst)
begin
  if Rst='1' then
    Accum <= (others=>'0');
  elsif rising_edge(Clk) then
    Accum <= '0' & Accum(7 downto 0) + unsigned('0' & Din(7 downto 0));
  end if;
end process U1;

U2: PWMout <= Accum(8) or Din(8);

end RTL_Accum;


-- -----------------------------------------
    Architecture RTL_Comparator of PWM is
-- -----------------------------------------
-- Simple PWM, counter + comparator solution.
-- Minimal the number of switchings.
-- Do NOT use this without registering PWM_out !!!
-- (see RTL_comp below)

signal Cnt : unsigned (7 downto 0);

begin

U1: process (Clk,Rst)
begin
  if Rst='1' then
    Cnt <= (others=>'0');
  elsif rising_edge(Clk) then
    Cnt <= Cnt + 1;
  end if;
end process U1;

U2: PWMout <= '1' when unsigned(Din(7 downto 0)) >= Cnt or Din(8)='1'
         else '0';

end RTL_Comparator;



-- -----------------------------------------
    Architecture RTL_Comp of PWM is
-- -----------------------------------------
-- Simple PWM, counter + comparator solution + output register.
-- Minimal the number of switchings.

signal Cnt : unsigned (7 downto 0);

begin

process (Clk,Rst)
begin
  if Rst='1' then
    Cnt <= (others=>'0');
    PWMout <= '0';
  elsif rising_edge(Clk) then
    Cnt <= Cnt + 1;
    if unsigned(Din(7 downto 0)) >= Cnt or Din(8)='1' then
      PWMout <= '1';
    else
      PWMout <= '0';
    end if;
  end if;
end process;

end RTL_Comp;

with a word of x"34" (Freq_Data) for 50Hz generation the output of dds change every 79us ... how could create a pwm counter tha covers the 79us duration of rom sample?

- - - Updated - - -

i accept also other methods/idea which start from... :thinker:
 

how could create a pwm counter tha covers the 79us duration of rom sample?
The main criterion for PWM counter period will be the intended PWM frequency. The update rate of the sine generator must not necessarily be the same.

Presently you have a mismatch between the signed output of the NCO and the unsigned PWM ramp representation, so connecting the NCO to the PWM generator won't achieve a reasonable modulation. You can overcome it e.g. by inverting the sine output MSB, changing the number representation from signed to straight binary.

More generally you should think about the intended PWM method, there are e.g. two-level versus three-level switching also natural versus regular sampling and edge or center alligned PWM. The present implementation seems to target to 2-level, natural sampling and edge alligned PWM.
 

Presently you have a mismatch between the signed output of the NCO and the unsigned PWM ramp representation, so connecting the NCO to the PWM generator won't achieve a reasonable modulation. You can overcome it e.g. by inverting the sine output MSB, changing the number representation from signed to straight binary.

Could you explain me better this mismatch? How could resolve it? Could you give me a code for example?

Thanks

Anyway is the principle of attach DDS out to comparator in right?
 

Thanks, that's a useful paper. As for the name, I have given up on finding a nomenclature for PWM methods. As you no doubt have noticed each particular PWM method is known by at least 238972349687 different names.

But yes, this 3-level PWM aka Unipolar 4-Quadrant PWM Technique (Form II) aka laser mazer bananafofaser PWM is typically used for motor control. For a new project I think I'll try to use it for controlling some peltier elements (with an extra inductance in series). Not sure if that's going to be super efficient, but it will probably burn less power than a linear approach. :p Especially since I need to control about 250 Watt.

Anyways, I also posted the link to that article because hopefully seeing some pictures of that triangular waveform + comparators will give the OP some inspiration on how to construct the PWM output based on the output from the DDS module...
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
Anyways, I also posted the link to that article because hopefully seeing some pictures of that triangular waveform + comparators will give the OP some inspiration on how to construct the PWM output based on the output from the DDS module...
Yes, it's a good idea to design a PWM generator by modelling an analog ramp and compare circuit. For the 3-level or unipolar PWM a symmetrical triangle wave is required to get center aligned PWM pulses.
 

In the referenced papers/blogs, the "Unipolar 4-Quadrant PWM Technique (Form II)" and the "3-Level PWM" methods are not identical. They will generate the same motor voltage if the "3-level PWM" uses twice the ramp frequency of the "unipolar" method, but the use of the H-bridge is very different. The "unipolar" method will have an alternating use of the legs in the H-bridge. Both legs will switch regardless of the control voltage polarity. In the "3-level PWM", one leg will be switching and the other will be static, depending on the control voltage polarity. I am not sure which one is "best", but the "unipolar" method seems restricted to 3 levels, and the "3-level PWM" method can be extended to more levels (5, 7, 9 etc.).
 
  • Like
Reactions: FvM

    FvM

    Points: 2
    Helpful Answer Positive Rating
In the referenced papers/blogs, the "Unipolar 4-Quadrant PWM Technique (Form II)" and the "3-Level PWM" methods are not identical. They will generate the same motor voltage if the "3-level PWM" uses twice the ramp frequency of the "unipolar" method, but the use of the H-bridge is very different.
You are right for the quoted papers. I'm however under the impression that "3-level" is used as general term to classify the generated waveform, which is the same for both schemes. Also the term unipolar (in contrast to "bipolar" or "2-level") is referring to waveforms, not circuits. Technically, the asymmetrically switched H-bridge has the disadvantage of distributing switching losses unequally, so you'll prefer the symmetrical scheme.
 
Last edited:

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top