PID Regler durch VHDL

OP #4424453
Lesenswert?
• ▲
▼
Hallo Alle,

der FPGA bekommt von einem Mikrocontroller die Reglerparameter und den 
Sollwert. Sollen alle Ein-und Ausgänge im Port (außer clock und reset) 
von std_logic_vector auf double oder signed geändert werden? Die 
restlichen Variablen sollten dann ebenfalls auf double gesetzt werden 
oder?
Und ist die Testbench eigentlich absolut notwendig? Ich habe es gerade 
mal so geschafft, den Design Code zusammenzubasteln und wollte direkt 
als nächstes die Synthese erstellen.

Vielen Vielen Dank im Vorraus und liebe Grüße !




Hier ist der Code:

•
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.std_logic_arith.all;
4

5

6

7

8
entity PID_Regler is
9
   generic(
10
    data_width: integer:= 14;
11
    intern_data_width: integer:= 28;
12
    TA: integer:=1 
13
     );
14
   port (
15
    w : in std_logic_vector(data_width-1 downto 0); --:= (others => '0');
16
    x : in std_logic_vector(data_width-1 downto 0); --:= (others => '0');
17
    y : out std_logic_vector(data_width-1 downto 0); --:= (others => '0');
18
    TP  : in std_logic_vector(intern_data_width-1 downto 0);
19
    TI  : in std_logic_vector(intern_data_width-1 downto 0);
20
    TD  : in std_logic_vector(intern_data_width-1 downto 0);
21
    clk_i : in  std_logic;
22
    rst_i : in  std_logic
23
);
24
end PID_Regler;
25

26
architecture Behavioral of PID_Regler is
27

28
signal e1 : std_logic_vector(data_width-1 downto 0) := (others => '0');
29
signal ealt : std_logic_vector(data_width-1 downto 0) := (others => '0');
30
signal e2 : std_logic_vector(data_width-1 downto 0) := (others => '0');
31
signal e3 : std_logic_vector(data_width-1 downto 0) := (others => '0');
32

33
begin
34

35
Regler1: process(clk_i, rst_i)
36
--rst_i wurde hinzugefügt
37
variable yp: std_logic_vector(intern_data_width-1 downto 0);
38
variable yi: std_logic_vector(intern_data_width-1 downto 0);
39
variable yi_alt: std_logic_vector(intern_data_width-1 downto 0);
40
variable yd: std_logic_vector(intern_data_width-1 downto 0); 
41
 
42
 begin
43
if (rst_i = '1') then  
44
      yp := (others => '0');
45
      yi := (others => '0');
46
      yi_alt:=(others => '0');
47
      yd := (others => '0');
48
      y <= (others => '0');
49
elsif (clk_i='1') then
50
      e1  <= std_logic_vector(signed(w) - signed(x));  
51
      yp := (signed(TP)*signed(e1));
52
      yi := yi_alt+(TI*e1*TA); -- yi_alt=yi
53
      yd := (TD*((e1-ealt)/TA)); -- ealt=e
54
      ealt <= e1;
55
      y <= (yp+yi+yd);
56

57
yi_alt := yi;
58
end if;
59
end process Regler1;
60

61

62

63
Regler2: process(clk_i, rst_i)
64
--rst_i wurde hinzugefügt
65
variable yp: std_logic_vector(intern_data_width-1 downto 0);
66
variable yi: std_logic_vector(intern_data_width-1 downto 0);
67
variable yi_alt: std_logic_vector(intern_data_width-1 downto 0);
68
variable yd: std_logic_vector(intern_data_width-1 downto 0); 
69
 
70
 begin
71
if (rst_i = '1') then  
72
      yp := (others => '0');
73
      yi := (others => '0');
74
      yd := (others => '0');
75
     ealt <= (others => '0');
76
      y <= (others => '0');
77
elsif (clk_i='1') then
78
      e2  <= std_logic_vector(signed(w) - signed(x));  
79
      yp := ((TP)*(e2));
80
      yi := ((yi_alt)+((TI)*(e2)*TA)); -- yi_alt=yi
81
      yd := ((TD)*(((e2)-(ealt))/TA)); -- ealt=e
82
      ealt <= e2;
83
      y <= ((yp)+(yi)+(yd));
84

85
yi_alt := yi;
86
end if;
87
end process Regler2;
88

89

90
Regler3: process(clk_i, rst_i)
91
--rst_i wurde hinzugefügt
92
variable yp: std_logic_vector(intern_data_width-1 downto 0);
93
variable yi: std_logic_vector(intern_data_width-1 downto 0);
94
variable yi_alt: std_logic_vector(intern_data_width-1 downto 0);
95
variable yd: std_logic_vector(intern_data_width-1 downto 0); 
96
 
97
 begin
98
if (rst_i = '1') then  
99
      yp := (others => '0');
100
      yi := (others => '0');
101
      yd := (others => '0');
102
      y <= (others => '0');
103
elsif(clk_i='1') then
104
      e3  <= std_logic_vector(signed(w) - signed(x));  
105
      yp := ((TP)*e3);
106
      yi := ((yi_alt)+((TI)*(e3)*TA)); -- yi_alt=yi
107
      yd := ((TD)*(((e3)-(ealt))/TA)); -- ealt=e
108
      ealt <= (e3);
109
      y <= ((yp)+(yi)+(yd));
110

111
yi_alt := yi;
112
end if;
113
end process Regler3;
114
end Behavioral;
115

116
•
Moderator (Firma: Titel) Persönliche Seite #4424869
Lesenswert?
• ▲
▼
Mueid S. schrieb:
> Und ist die Testbench eigentlich absolut notwendig?
Nein. Eine Testbench ist einfach nur der "Debugger" der Hardware. Wenn 
du deine Software ohne Debugger zum Laufen bekommst, dann brauchst du 
für die Hardware auch keinen Simulator.

> Ich habe es gerade
> mal so geschafft, den Design Code zusammenzubasteln und wollte direkt
> als nächstes die Synthese erstellen.
Und, läuft alles wie es soll?

Mueid S. schrieb:
> y <= ((yp)+(yi)+(yd));
Ohne auf Einzelheiten in deinem Code einzugehen: ist diese Berechnung 
Vorzeichenbehaftet oder nicht?
Oder anders: man rechnet nicht mit uneingeschränkten Datentypen. Nimm 
die numeric_std und passende Datentypen...
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

Und das mit dem "double" als Datentyp kannst du für die Synthese schnell 
vergessen. Denn auf dem FPGA sind alle Zahlen irgendwelche Bitmuster. 
Und welches Bitmuster hat ein "double"? Dazu musst du die IEEE 754 
konsultieren.
Gast #4425035
Lesenswert?
• ▲
▼
> Und ist die Testbench eigentlich absolut notwendig?
Fuer dich ja, wenn ich mir deinen Code so anschaue.

Siehe:
1
      yd := (others => '0');
2
      y <= (others => '0');
3
elsif(clk_i='1') then
4
      e3  <= std_logic_vector(signed(w) - signed(x));  
5
      yp := ((TP)*e3);
6
      yi := ((yi_alt)+((TI)*(e3)*TA)); -- yi_alt=yi

da sollte wohl ein rising_edge(clk_i) stehen.


hannes
OP #4426508
Lesenswert?
• ▲
▼
Lothar M. schrieb:
>> Ich habe es gerade
>> mal so geschafft, den Design Code zusammenzubasteln und wollte direkt
>> als nächstes die Synthese erstellen.
> Und, läuft alles wie es soll?

Ich weiß es leider nicht. Kann ich das überprüfen, ohne extra eine 
Testbech zu schreiben?

>> y <= ((yp)+(yi)+(yd));
>Ohne auf Einzelheiten in deinem Code einzugehen: ist diese Berechnung
Vorzeichenbehaftet oder nicht?

Nein. Die Werte sind immer positiv.

An double habe ich gedacht, weil die Werte, die von Microcontroller in 
den Fpga reingehen, double Werte sind. Oder muss ich die double Werte in 
binär Werte konvertieren bzw. kann ich einfach mit den double Werten 
weiterrechnen?
Moderator (Firma: Titel) Persönliche Seite #4426572
Lesenswert?
• ▲
▼
Mueid S. schrieb:
> Ich weiß es leider nicht. Kann ich das überprüfen, ohne extra eine
> Testbech zu schreiben?
Wenns auf der Hardware läuft ist es ok.
Wenn nicht: schreib eine Testbench. Das ist ja keine Raketentechnik, 
sondern hier sogar super einfach: du brauchst ja nur ein paar statiche 
Eingangswerte und ein paar Sprünge im Sollwert. Das ist in 15 min. 
erledigt...

> Nein. Die Werte sind immer positiv.
Warum schreibst du dann " signed(w) - signed(x)"?

> Oder muss ich die double Werte in binär Werte konvertieren
Ich würde einfach mal sagen: Ja, tu das.

> kann ich einfach mit den double Werten weiterrechnen?
Nein "einfach" im Sinne von "schnell und ressourcenschonend" geht das 
nicht. Und "einfach" im Sinne von "dann muss ich nichts Denken" geht es 
auch nicht...

Mueid S. schrieb:
> wollte direkt als nächstes die Synthese erstellen.
Und was sagt der Synthesizer?
(Firma: abaxor engineering) #4426613
Lesenswert?
• ▲
▼
Mueid S. schrieb:
> Thomas R. schrieb:
>
>> wie hoch ist dein Takt?
>>
>> Tom
>
> Die Abtastrate für das Signal oder die Taktfrequenz der Clock? Also die
> Abtastrate wird auf jeden Fall kleiner als die Integrierzeit, genau habe
> ich sie allerdings nicht festgelegt. Die Taktfrequenz habe ich noch
> nicht genau definiert. Ich weiß auch nicht nach welchen Kriterien ich
> sie festlegen soll.

Genau darauf wollte ich hinaus. Denn in deinem Beispiel durchläufst du 
mit jedem Takt eine Berechnung. D.h. im PID-Regler ist deine 
Abtastfrequenz gleich der Taktfrequenz. Da die Taktfrequenz 
üblicherweise ein paar MHz ist wäre das auch deine Abtastfrequenz. Du 
brauchst noch ein Signal DataValid, dass dir sagt, jetzt kommt ein neues 
Sample. Dann darfst du nur einen einzigen Reglerdurchlauf machen, sonst 
ist dein I- und D-Anteil falsch.

Tom
Moderator (Firma: Titel) Persönliche Seite #4426731
Lesenswert?
• ▲
▼
Mueid S. schrieb:
> Ich dachte dafür ist das Clock Signal da. Nämlich anzugeben, dass jetzt
> eine neue Berechnung kommt.
Dann muss der Takt aber zum Regler passen...

Der Takt in einem FPGA ist dazu da, irgendwelche Flipflops dazu zu 
bewegen, die Daten am Eingang zu speichern und am Ausgang 
bereitzustellen. Deshalb ist dieser FPGA-Takt erst mal komplett 
unabhängig vom Filtertakt/Reglertakt. Denn wenn der Regler z.B. mit 1ms 
Zyklus laufen soll, dann muss ein FPGA mit 100 MHz Taktfrequenz genau 
100000 Takte lang nichts tun, und dann wieder 1x den Regler berechnen.
(Firma: abaxor engineering) #4426734
Lesenswert?
• ▲
▼
Mueid S. schrieb:
> Thomas R. schrieb:
>> Du
>> brauchst noch ein Signal DataValid, dass dir sagt, jetzt kommt ein neues
>> Sample.
>
> Ich hab das nicht ganz verstanden. Soll ich das als zusätzliche If
> Bedingung einfügen? Ich dachte dafür ist das Clock Signal da. Nämlich
> anzugeben, dass jetzt eine neue Berechnung kommt.

Nein, dein Takt kommt von einem Quarz üblicherweise mit einigen 10 MHz. 
Der kann völlig unabhängig von deiner Samplingfrequenz sein. Es ist 
sogar besser, wenn er Takt deutlich höher als die Samplingfrequenz ist.

Bei dem was du vorhast, könnte dein Takt auch unterschiedliche 
Frequenzen haben. Das ist etwas, was man nicht in einem FPGA haben will.

Tom

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.