Forum: FPGA, VHDL & Co. Zentrierte PWM erstellen


von Dennis L. (eslon)


Lesenswert?

Servus

Ich habe folgenden Code für ein PWM gefunden:
http://www.lothar-miller.de/s9y/archives/54-PWM.html

Sehr schön das ganze, danke Lothar.

Jetzt zu meiner Frage, wie kann ich es bewerkställigen, dass die Pulse 
der PWM zentriert sind, das Ganze soll später mal für eine 
Raumzeigermodulation benutzt werden.

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity PWM is
6
    Generic ( width: natural := 8;        -- Breite
7
              fclk : integer := 50000000; -- Taktfrequenz
8
              fpwm : integer := 1000      -- PWM-Frequenz
9
             ); 
10
    Port    ( clk      : in  std_logic;
11
              pwmvalue : in  std_logic_vector (width-1 downto 0);
12
              pwmout   : out std_logic
13
             );
14
end PWM;
15
16
architecture Behavioral of PWM is
17
signal   cnt : integer range 0 to 2**width-2 := 0;
18
signal   pre : integer range 0 to fclk/(fpwm*(2**width-2)) := 0;
19
begin
20
   -- Vorteiler teilt FPGA-Takt auf PWM-Frequenz*Zählschritte
21
   process begin
22
      wait until rising_edge(clk);
23
      if (pre<fclk/(fpwm*(2**width))) then 
24
         pre <= pre+1;
25
      else
26
         pre <= 0;
27
      end if;
28
   end process;
29
   
30
   -- PWM-Zähler         
31
   process begin
32
      wait until rising_edge(clk);
33
      if (pre=0) then
34
         if (cnt<2**width-2) then cnt <= cnt+1;
35
         else                     cnt <= 0;
36
         end if;
37
      end if;
38
   end process;
39
   
40
   -- Vergleicher, registriert für Ausgabe auf IO-Pin ohne Glitches
41
   process begin
42
      wait until rising_edge(clk);
43
      if(cnt<=to_integer(unsigned(pwmvalue)) then pwmout <= '0';
44
      else                                        pwmout <= '1';
45
      end if;
46
   end process;
47
end Behavioral;

von Düsendieb (Gast)


Lesenswert?


von Jens (Gast)


Lesenswert?

Dann brauchst du einen Zähler, der nicht nur rauf zählt, sonder rauf und 
runter. Stichwort "Dreieck"!

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Sowas etwa:
1
signal   dir : std_logic := '0'; -- 0=up
2
:
3
:
4
    -- PWM-Zähler         
5
    process begin
6
       wait until rising_edge(clk);
7
       if (pre=0) then
8
          if(dir = '0') then -- up
9
             if (cnt<2**width-2) then 
10
                 cnt <= cnt+1;
11
             else                     
12
                 dir <= '1'; 
13
                 cnt <= cnt-1;
14
             end if;
15
          else               -- down
16
             if (cnt>0) then 
17
                 cnt <= cnt-1;
18
             else                     
19
                 dir <= '0'; 
20
                 cnt <= cnt+1;
21
             end if;
22
          end if;
23
       end if;
24
    end process;
Interessant ist jetzt noch eine Betrachtung der Umschaltpunkte bei max. 
und bei 0...

von Dennis L. (eslon)


Lesenswert?

Also bei low funktioniert es wunderbar, nur durchgehen high pegel 
funktioniert nicht richtig, da sind immer unterbrechungen drin.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dennis Lindner schrieb:
> Also bei low funktioniert es wunderbar, nur durchgehen high pegel
> funktioniert nicht richtig, da sind immer unterbrechungen drin.
Ja, so wie ich schon schrieb:
>> Interessant ist jetzt noch eine Betrachtung der Umschaltpunkte bei max.
>> und bei 0...
Mach doch einfach mal eine Simulation, dann siehst du schnell, wo es da 
klemmt...

von Dennis L. (eslon)


Lesenswert?

Das habe ich gemacht und auch festgestellt, dass pwmout auf 0 springt, 
wenn cnt bei 0 angelangt ist.

Wegen diesem Vergleich:
1
if(cnt<=to_integer(unsigned(pwmvalue))) then pwmout <= '0';

Hab auch schon probiert was zu ändern, bisher ohne Erfolg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Dennis Lindner schrieb:
> Hab auch schon probiert was zu ändern, bisher ohne Erfolg
1
      if(cnt>=to_integer(unsigned(pwmvalue))) then pwmout <= '0';
Kleine Ursache, große Wirkung...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.