Forum: FPGA, VHDL & Co. VHDL PWM auf fpga4fun.com


von Sepp (Gast)


Lesenswert?

Hallo,

ich spiel gerade mit VHDL herum und wollte eine PWM implementieren.

Da meine ersten Versuche in die Hose gingen bin ich bei Freund Google 
mal auf Ideensuche gegangen und habe folgendes gefunden:

1
library IEEE;
2
use IEEE.STD_LOGIC_1164.all;
3
use IEEE.STD_LOGIC_UNSIGNED.ALL;
4
5
entity PWM is
6
  port (
7
   clk : in std_logic;
8
   PWM_in : in std_logic_vector (7 downto 0) := "00000000";
9
   PWM_out : out std_logic
10
  );
11
end PWM;
12
13
architecture PWM_arch of PWM is
14
  signal  PWM_Accumulator : std_logic_vector(8 downto 0);
15
begin
16
  process(clk, PWM_in)
17
  begin
18
    if rising_edge(clk) then      
19
      PWM_Accumulator  <=  ("0" & PWM_Accumulator(7 downto 0)) + ("0" & PWM_in);
20
    end if;
21
  end process;
22
23
  PWM_out <= PWM_Accumulator(8);
24
end PWM_arch;
Quelle: http://www.fpga4fun.com/PWM_DAC.html


Wenn ich mir das recht überlege, hab ich hier doch aber keine echte 
Puls-Weiten-Modulation sondern eher eine Pulsfrequenzmodulation 
(http://de.wikipedia.org/wiki/Pulsfrequenzmodulation) oder?

Ich hab eine Konstante Pulsbreite von einem clk Zyklus.

Entweder das stimmt so, wie ich es sage oder ich stehe auf dem Schlauch.

Danke

Gruß
Sepp

von Georg A. (Gast)


Lesenswert?

Ja, ist keine PWM. PFM aber auch nicht, weil der Abstand der Pulse nicht 
konstant ist (Bsp: PWM_IN=255 gibt 0-0-1-0-1-0...-1-0-0-1...). Also eher 
eine Pulse Distribution Modulation... PDM ist an sich nicht verkehrt, 
weil zB. der Ripple nach einem RC-Glied bei vielen PWM-Werten kleiner 
wird. Aber mit der Methode habe ich es auch noch nicht gesehen...

Der Code ist aber ohnehin nicht so toll. In der Entity gibts eine 
Default-Zuweisung an PWM_in, dabei ist das doch grad der wichtigste 
Eingang... Dafür fehlt eine Initialisierung vom Akku, entweder per 
explizitem Reset oder := in der Deklaration. Damit ist der Akku 
undefiniert ('U'). Geht zwar in echt, aber nur da. Obiges wird im 
Simulator nach einem Takt lauter nette rote 'X'e produzieren, weil 
'U'+irgendwas immer 'X' gibt...

Weiterhin will man "IEEE.STD_LOGIC_UNSIGNED.ALL" nicht mehr verwenden. 
Trotz des Namens ist das kein Standard. Nimm den Typ unsigned von 
"IEEE.NUMERIC_STD.all" (hätte auch signed). Vermutlich ist das auch der 
Grund, warum es bei dir nichts geworden ist. Normale Vektoren sind reine 
Aneinanderreihung von Bits ohne arithmetische Interpretation. D.h. +/- 
oder Grössenvergleiche ausser = Gleichheit sind eigentlich nicht 
definiert. Synopsys hat ein paar Bibliotheken verbrochen (u.a. obige), 
die das mit diversen Nebenwirkungen reingewürgt haben.

Wenn man numeric_std nimmt, kann man als Typen zB. unsigned(7 downto 0) 
definieren und die ganze Arithmetik geht ohne grösseren Aufwand, soweit 
Overloading und Typprüfung in VHDL das zulassen...

Mit numeric_std und passend definierten Signalen würde der innere Teil 
einer PWM zB so aussehen:

pwm_acc<=pwm_acc+1;
pwm_out<='0';
if pwm_acc<pwm_in then
  pwm_out<'1';
end if;

Ist aber nicht ganz optimal, da das < eine Subtraktion produziert. Man 
kann auch nur bei Gleichheit das Bit setzen und nur beim Wraparound 
wieder auf 0 zwingen. Aber viel bringts nicht und ist bei heutigen FPGAs 
auch recht egal.

von Michael (Gast)


Lesenswert?

>Synopsys hat ein paar Bibliotheken verbrochen
und wie so soft wurden sie dafür nie zur Verantwortung gezogen, obwohl 
sie tausende Programmierer behindert und millionen Arbeitsstunden 
vernichtet haben :-)

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.