Forum: FPGA, VHDL & Co. FPGA Resource Verbrauch optimieren- bitte um Hilfe


von Tomy (Gast)


Lesenswert?

Hallo zusammen,

ich nutze einen Altera 4e. Der verfügt über 55,800 LEs und 2,300,000 
Speicher Bits. Für meine Applikation habe ich ca. 124 PI-Rechner mit 
I-Anteil gehalten oder mit einem Faktor verrechnet bei der Begrenzung 
und paar Kleinigkeiten. Alle Reglerausgänge werden zum Schluß 
miteinander addieren.

Ein PI-Regler (~1250 LEs) verfügt über:
Input: - Ki/Kp Exponent/Mantise 16 Bits
       - Output Max/Min 16-Bits
       - Soll/Ist-Wert 16 Bits
       - reset
       - Start
       - clear Limit
Output: - PiOutput 32 und 16 Bits
        - Limit Status
        - done status


Wenn die Regler parallel (am einfachsten für mich) laufen sollen, dann 
kann der FPGA nur ca. 50 Regler tragen. Deswegen habe ich versucht, nur 
einen gemeinsamen 4 x PI-Regler(4 in Parallel) in einem synchronen 
Statemachine einzupacken. Es scheint zu gehen. Ich verbrauche dann für 
alle Regler ca. 90% (mit Optimization Technique: Area).

Für die Statemachine brauche ich einen Mux für den 4 x Integrator 
(jeweils 32-Bits).
1
    CtrlStateMachine_pro: PROCESS (Clk, Rst_n)
2
    BEGIN
3
      IF Rst_n = '0' THEN
4
        -- Zustandmaschine zuruecksetzen
5
        CtrlState <= CTRL_WAIT_R1_DONE;
6
        -- Signals zurücksetzen
7
        -- ...
8
      ELSIF RISING_EDGE(Clk) THEN
9
        -- Pulse
10
        CtrlInput_s.Start <= '0';        
11
        -- Zustandmaschine
12
        CASE CtrlState IS
13
          -- auf Regler1 "Done" Warten
14
          WHEN CTRL_WAIT_R1_DONE =>
15
            CtrlState <= CTRL_WAIT_R1_DONE;
16
            IF CtrlOutput_s.Done = '1' THEN -- "Done" 1 Pulse Clock
17
              -- Ergebnisse des Reglers-1 umlagern
18
              ArrayYiOldOutput_s(REGLER1_BIT) <= YiOldOutput_s; -- 4x I-Anteil (x32 Bits) umlagern
19
              ArrayCtrlOutput_s(REGLER1_BIT) <= CtrlOutput_s; -- 4x Regler Output (x16 Bits) umlagern
20
              -- Start Regler2
21
              CtrlInput_s.Err <= ArrayErr_i(REGLER2_BIT); -- 4x Regler Abweichung (x16 Bits)
22
              YiOldInput_s <= ArrayYiOldOutput_s(REGLER2_BIT); -- 4x alten Integral (x32 Bits)
23
              CtrlInput_s.Start   <= '1'; -- 1 Clock pulse
24
              -- next state
25
              CtrlState <= CTRL_WAIT_R2_DONE;
26
            END IF;
Alle Speicherbits sind noch frei. Nur LEs wurden genutzt.

Wie kann ich besser machen?

Vielen Dank im Voraus!

Lg Tomy

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


Lesenswert?

Tomy schrieb:
> Alle Speicherbits sind noch frei.
Logisch, denn mit dieser Beschreibung kann kein RAM angesprochen und 
umgesetzt werden. Es muss ja jeder Speicher gleichzeitig angesprochen 
werden können, weil es am einfachsten ist, ...
> Wenn die Regler parallel laufen sollen


Die Frage ist eher: wie schnell müssen die Regler laufen?
Und wieviel Zeit braucht davon deine Fließkommarechnung?
Wenn dir dann noch Zeit übrigbleibt, dann kannst du zu speichernde Werte 
ins RAM auslagern. Übrigens: warum musst du eigentlich so viel 
speichern? In einem analogen PI Regler speichert ja auch nur der I-Wert. 
Du speicherst aber viel mehr:
 ArrayYiOldOutput_s
 ArrayCtrlOutput_s
 CtrlInput_s.Err
 YiOldInput_s

> Für die Statemachine brauche ich einen Mux
Alles, was hinter einem rising_edge zugewiesen wird, muss als Flipflop 
realisiert werden. Ein Multiplexer an sich hat aber üblicherweise keine 
Speicherelemente. Deiner schon...


Tomy schrieb:
> Für meine Applikation habe ich ca. 124 PI-Rechner
Tomy schrieb:
> kann der FPGA nur ca. 50 Regler tragen.
Du brauchst 124 und konntest bisher maximal 50 realisieren, oder 
wie?


BTW:
> der FPGA
Ein FPGA ist ein Feldprogrammierbares Gate Array.
Und der richtige Artikel zu "Array" ist das Array.
Ergo heißt es auch das FPGA.

von Der L. (vhdl-neuling)


Lesenswert?

Lothar Miller schrieb:
> BTW:
>> der FPGA
> Ein FPGA ist ein Feldprogrammierbares Gate Array.
> Und der richtige Artikel zu "Array" ist das Array.
> Ergo heißt es auch das FPGA.

Vielleicht meinte er ja "der FPGA-Baustein" und der Baustein wurde 
wegoptimiert :-)

von Mac G. (macgyver0815)


Lesenswert?

Das FPGA flog in die Kiste!
Der FPGA-Baustein flog in die Kiste!
Den FPGA-Baustein aus der Kiste holen!
Die FPGA-Bausteine aus der Kiste holen!
Dem FPGA-Baustein seine Kiste holen!

Oder der neudeutsche Universalartikel:
De FPGA flog voll aus de Kiste, ey!

;-)

von Tomy (Gast)


Lesenswert?

Hallo zusammen,
Danke erst mal für eure Antwort:-)

Lothar Miller schrieb:
> wie schnell müssen die Regler laufen?

ca. 20µS haben die Regler Zeit. (Clock "Clk" ist dabei 50MHz)

Lothar Miller schrieb:
> Und wieviel Zeit braucht davon deine Fließkommarechnung?

ich habe nur Fixed Point Operation. Damit ich weiß, wann der Regler 
fertig ist (wann das Status-Bit "Done" gesetzt wird), mache ich in 
meinem PI-Regler mit "Clock-Enable", also meine ich so etwa:
1
-- PI Control Process
2
PiCtrl_pro: PROCESS(clk, reset_n) IS    
3
BEGIN              
4
 if reset_n = '0' then -- asyn reset_n
5
   yout_sat_reg <= (others=> '0');
6
   Ki_Mantise_reg <= (others=> '0');
7
   Kp_expopnet_reg <= (others=> '0');
8
   Ki_exp_reg <= (others=> '0');
9
   ysum_reg <= (others=> '0');
10
   yi_alt <= (others=> '0');
11
   start_delay <= (others=> '0');
12
   op1_reg <= (others=> '0');
13
   op2_reg <= (others=> '0');
14
   -- ...
15
 elsif rising_edge(clk) then        
16
 -- start: los!
17
  if ( start = '1' ) then -- Uebernahme gueltige Daten
18
   start_delay(0) <= '1';
19
   op1_reg <= Kp_mantise_inp;
20
   Kp_exponent_reg <= Kp_exponent_inp;
21
   Ki_exponent_reg <= Ki_exponent_inp;
22
   Ki_mantise_reg  <= Ki_mantise_inp;          
23
  else
24
   start_delay(0) <= '0';
25
  end if;
26
    
27
-- clock enable Vorbereiten
28
  if start_delay(1) = '1' then start_delay(2) <= '1';  else  start_delay(2) <= '0';end if ;
29
  if start_delay(2) = '1' then start_delay(3) <= '1';  else  start_delay(3) <= '0';end if ;
30
  if start_delay(3) = '1' then start_delay(4) <= '1';  else  start_delay(4) <= '0';end if ;
31
  if start_delay(4) = '1' then start_delay(5) <= '1';  else  start_delay(5) <= '0';end if ;
32
  if start_delay(5) = '1' then start_delay(6) <= '1';  else  start_delay(6) <= '0';end if ;
33
  if start_delay(6) = '1' then start_delay(7) <= '1';  else  start_delay(7) <= '0';end if ;
34
  if start_delay(7) = '1' then start_delay(8) <= '1';  else  start_delay(8) <= '0';end if ;
35
  if start_delay(8) = '1' then start_delay(9) <= '1';  else  start_delay(9) <= '0';end if ;
36
  if start_delay(9) = '1' then start_delay(10)<= '1';  else  start_delay(10) <= '0';end if ;
37
38
 -- Delay 1 Clock nach "Start"
39
  if start_delay(0) = '1' then
40
   start_delay(1) <= '1';          
41
   AbsKpExp_r <= AbsKpExp_s; 
42
   AbsKiExp_r <= AbsKiExp_s;           
43
  else  
44
   start_delay(1) <= '0';
45
  end if ;
46
 -- Regelabweichung mit Überlauf check und Korrektur
47
  if start_delay(1) = '1' then op2_reg <= DeltaMitOVcheck_s; end if;
48
 -- (kp_mantise * delta)
49
  if start_delay(2) = '1' then yp1_reg <= i32Tmp_s; end if; -- yp1_reg = DeltaMitOVcheck_s * Kp_mantise_inp
50
 -- mux
51
  if start_delay(3) = '1' then op1_reg <= Ki_man_reg; end if; 
52
 -- ...              
53
 -- ...
54
 -- "done" nach 12 Clock
55
  if start_delay(10) = '1' then  
56
    done <= '1';
57
    y_out <= y_sat_tmp;
58
  else 
59
    done <= '0'; 
60
  end if;
61
end process;
62
63
-- Absolutwertsbildung
64
AbsKpExp_s <= Kp_exponent_reg when Kp_exponent_reg(15) = '0' else - Kp_exponent_reg;
65
AbsKiExp_s <= Ki_exponent_reg when Ki_exponent_reg(15) = '0' else - Ki_exponent_reg;
66
67
-- gemeinsame Multiplikation: (delta * Kp_mantise) oder (delta * Ki_mantise)
68
i32Tmp_s <= op1_reg * op2_reg;
69
70
-- Regelabweichung mit Überlauf check und Korrektur
71
DeltaMitOVcheck_s <= OV_SUB16(ref_inp, act_inp); -- (ref - act)
72
73
-- ..
74
-- ..
75
-- ..

Wie implementiert ihr eigentlich euren PI-Regler?

Lothar Miller schrieb:
> Wenn dir dann noch Zeit übrigbleibt, dann kannst du zu speichernde Werte
> ins RAM auslagern

wie genau kann ich das machen?

Lothar Miller schrieb:
> Übrigens: warum musst du eigentlich so viel
> speichern? In einem analogen PI Regler speichert ja auch nur der I-Wert.
> Du speicherst aber viel mehr:
>  ArrayYiOldOutput_s
>  ArrayCtrlOutput_s
>  CtrlInput_s.Err
>  YiOldInput_s

Ich nutze nur eine gemeinsame PI-Regler Block. In diesem Block befinden 
sich 4 parallel PI-Regler, die gemeinsam "start", "Ki", "Kp" besitzen. 
Die separate Inputs sind:
 1) 4x Regelabweichungen (in Array "CtrlInput_s.Err")
 2) 4x Integralswerte von der letzten Abtastzeit (in Array 
"YiOldInput_s")
Die separaten Outputs sind:
 1) 4x aktuelle Integralswerte (in "ArrayYiOldOutput_s");
 2) 4x Regleroutput

Wenn ein Block fertig ist, muss ich erst mal die Ergebnisse umlagern, 
und dann vorbereite ich die Inputs für die Block, anschließend mit 
"start".

Lothar Miller schrieb:
> Du brauchst 124 und konntest bisher maximal 50 realisieren, oder
> wie?

Ich brauche 124 Regler. Wenn ich alle Regler als 124 Instanzen (also 
parallel laufend) definieren würde, dann gibts nicht genug Resource. 
Also kann ich dann nur 50 Instanzen einpacken. Dabei liegt der 
Resource-Verbrauch um ca. 95%.

Wenn ich aber mit der oberen Zustandmaschine realisiere, dann können 124 
Regler eingepackt werden, und Resource-Verbrauch ist dann 90%.

Lothar Miller schrieb:
> Ein FPGA ist ein Feldprogrammierbares Gate Array.
> Und der richtige Artikel zu "Array" ist das Array.
> Ergo heißt es auch das FPGA.

Danke für den Hinweis:-)

Euch noch ein schönes Wochenende!

lg Tomy

von Tomy (Gast)


Lesenswert?

Lothar Miller schrieb:
>> der FPGA
> Ein FPGA ist ein Feldprogrammierbares Gate Array.
> Und der richtige Artikel zu "Array" ist das Array.
> Ergo heißt es auch das FPGA.

ps.
Entschuldigung für mein kaputtes Deutsch! Jeder Hinweis ist willkommen! 
^^

nochmal ciao!

von Tomy (Gast)


Lesenswert?

Hallo,

keine Idee?

von abcd (Gast)


Lesenswert?

1
-- clock enable Vorbereiten
2
  if start_delay(1) = '1' then start_delay(2) <= '1';  else  start_delay(2) <= '0';end if ;
3
  if start_delay(2) = '1' then start_delay(3) <= '1';  else  start_delay(3) <= '0';end if ;
4
  if start_delay(3) = '1' then start_delay(4) <= '1';  else  start_delay(4) <= '0';end if ;
5
  if start_delay(4) = '1' then start_delay(5) <= '1';  else  start_delay(5) <= '0';end if ;
6
  if start_delay(5) = '1' then start_delay(6) <= '1';  else  start_delay(6) <= '0';end if ;
7
  if start_delay(6) = '1' then start_delay(7) <= '1';  else  start_delay(7) <= '0';end if ;
8
  if start_delay(7) = '1' then start_delay(8) <= '1';  else  start_delay(8) <= '0';end if ;
9
  if start_delay(8) = '1' then start_delay(9) <= '1';  else  start_delay(9) <= '0';end if ;
10
  if start_delay(9) = '1' then start_delay(10)<= '1';  else  start_delay(10) <= '0';end if ;

Das scheint mir ein sehr unkonventionell beschriebenes Schieberegister 
zu sein. Möglicherweise versteht das die Synthese nicht und macht was 
kompliziertes draus. Ich würde das mal wie ein Schieberegister 
beschreiben und kucken obs was hilft.

von Klaus Könner (Gast)


Lesenswert?

abcd schrieb:
>
1
> -- clock enable Vorbereiten
2
>   if start_delay(1) = '1' then start_delay(2) <= '1';  else 
3
> start_delay(2) <= '0';end if ;
4
>   if start_delay(2) = '1' then start_delay(3) <= '1';  else 
5
> start_delay(3) <= '0';end if ;
6
>   if start_delay(3) = '1' then start_delay(4) <= '1';  else 
7
> start_delay(4) <= '0';end if ;
8
>   if start_delay(4) = '1' then start_delay(5) <= '1';  else 
9
> start_delay(5) <= '0';end if ;
10
>   if start_delay(5) = '1' then start_delay(6) <= '1';  else 
11
> start_delay(6) <= '0';end if ;
12
>   if start_delay(6) = '1' then start_delay(7) <= '1';  else 
13
> start_delay(7) <= '0';end if ;
14
>   if start_delay(7) = '1' then start_delay(8) <= '1';  else 
15
> start_delay(8) <= '0';end if ;
16
>   if start_delay(8) = '1' then start_delay(9) <= '1';  else 
17
> start_delay(9) <= '0';end if ;
18
>   if start_delay(9) = '1' then start_delay(10)<= '1';  else 
19
> start_delay(10) <= '0';end if ;
20
>
>
> Das scheint mir ein sehr unkonventionell beschriebenes Schieberegister
> zu sein. Möglicherweise versteht das die Synthese nicht und macht was
> kompliziertes draus. Ich würde das mal wie ein Schieberegister
> beschreiben und kucken obs was hilft.

und weiter oben den asynchronenen reset von start_delay entfernen

start_delay <= (others=> '0');

Dann stehen die chancen gut das die Synthese SRL Macros statt FF 
instanziert. Eine LUT ersetzt im best case 10 FF.
MfG

von Tomy (Gast)


Lesenswert?

vielen Dank für eure schnelle Antwort!:)

Ich würde eure Empfehlungen ausprobieren:)

lg Tomy

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.