Forum: FPGA, VHDL & Co. was gefällt dem Compiler nicht?


von Dima S. (onkelbenz)


Lesenswert?

Hallo

ich habe eine state maschiene, die Impulse bestimmter dauer generieren 
soll. Dazu wird auf dem Eingang "lang" ein 8 bit breiter wert (den 
bekomme ich über eine serielle Schnittstelle) eigegeben. Damit keine 
Leitungen "in der Luft hängen" begrenze ich die range auf 256 Werte. Der 
Impuls wird generiert sobald "time20" = '1'. Für den Beispiel ist alles 
vereinfacht bis zum geht nicht mehr.

Hier ist meine state maschiene:
1
entity PWM_machine is 
2
  Port
3
  (
4
    clk     : in    STD_LOGIC;
5
    rst     : in    STD_LOGIC;
6
    time20  : in    STD_LOGIC;
7
    lang    : in    integer range 0 to 255; 
8
    pulse   : out   STD_LOGIC
9
  );
10
end PWM_machine;
11
12
-- 10000 cycles = 1 ms
13
14
architecture Behavioral of PWM_machine is
15
  type signal_machine is ( init, start_pulse, end_pulse );
16
  signal cur_state: signal_machine := init;
17
begin
18
  pulse20ms: process(clk, rst)
19
    variable i:     natural range 0 to 10001 := 0;
20
    variable timer: natural := 0;
21
    begin
22
      if( clk = '1' and clk'event ) then
23
        case cur_state is
24
          when init =>
25
            pulse <= '0';
26
            i := t1;
27
            cur_state <= start_pulse;
28
          when start_pulse =>
29
            if ( time20 = '1' ) then
30
              timer := ((lang * 10000 / 256) + 10000);
31
              cur_state <= end_pulse;
32
              pulse <= '1';
33
              i := 10000;
34
            end if;
35
          when end_pulse =>
36
            if ( i = 0 ) then
37
              cur_state <= start_pulse;
38
              pulse <= '0';
39
            else
40
              i := i - 1;
41
            end if;
42
        end case;
43
      end if;
44
  end process pulse20ms;
45
46
end Behavioral;

jetzt mein der compiler, dass "lang" Eingang nie benutz wird, obwohl der 
ja eindeutig für die berechnung "timer := ((lang * 10000 / 256) + 
10000);" gebraucht wird. Deswegen schließt er den gar nicht erst an. 
Dieses Problem kann behoben werden, wenn ich am Eingang integer nicht 
begrenze, dann passt es an einer anderen Stelle (nämlich ist dann das 
Ergebnis länger als 31 bit) nicht mehr und zusätzlich muss noch eine 
Fehlerbehandlung eingebaut werden, für den Fall, dass der wert nicht 
zwischen 0 und 255 liegt.

dann gibt es noch 2 weitere fehlermeldungen, mit denen ich gar nichts 
anfangen kann:
WARNING:Xst:647 - Input <lang> is never used. This port will be 
preserved and left unconnected if it belongs to a top-level block or it 
belongs to a sub-block and the hierarchy of this sub-block is preserved.
WARNING:Xst:1426 - The value init of the FF/Latch FFd2 hinder the 
constant cleaning in the block FSM.
   You should achieve better results by setting this init to 1.
WARNING:Xst:1426 - The value init of the FF/Latch FSM_FFd2 hinder the 
constant cleaning in the block FSM_0-parent.
   You should achieve better results by setting this init to 1.


Was passiert da?

von Lattice User (Gast)


Lesenswert?

Dima Schmitt schrieb:
> jetzt mein der compiler, dass "lang" Eingang nie benutz wird, obwohl der
> ja eindeutig für die berechnung "timer := ((lang * 10000 / 256) +
> 10000);" gebraucht wird.

Der Compiler hat Recht. timer wird nicht benutzt und damit wird auch 
lang nicht benutzt.

von Dima S. (onkelbenz)


Lesenswert?

... wie simpel jetzt der Antwort war - ist irgendwann mal zwischen den 
Zahllosen umschreibungen passiert...


Aber was ist jetzt mit den anderen 2 warnungen?

WARNING:Xst:1426 - The value init of the FF/Latch FFd2 hinder the 
constant cleaning in the block FSM.
   You should achieve better results by setting this init to 1.
WARNING:Xst:1426 - The value init of the FF/Latch FSM_FFd2 hinder the 
constant cleaning in the block FSM_0-parent.
   You should achieve better results by setting this init to 1.

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


Lesenswert?

Ohne näher auf deine Warnungen einzugehen, hier noch ein paar 
Anmerkungen:

Dima Schmitt schrieb:
>    variable i:     natural range 0 to 10001 := 0;
Das gibt Platz für einen Zähler mit 10002 Schritten. Willst du das?

>                i := 10000;
>             end if;
>           when end_pulse =>
>             if ( i = 0 ) then
>               cur_state <= start_pulse;
>               pulse <= '0';
>             else
>               i := i - 1;
i zählt hier 10001 Schritte. Das stimmt mich nachdenklich, weil Menschen 
oft im Zehnersystem denken...

Man sollt einen Zähler nicht rückwärts zählen lassen und mit 0 
vergleichen. Sondern (weil ressourcensparender) hochzählen und mit 0 
laden.

> Aber was ist jetzt mit den anderen 2 warnungen?
Die kommen vermutlich von der unnötigen Verwendung der Variablen (und 
daraus resultierenden Seiteneffekten)...

von Dima S. (onkelbenz)


Angehängte Dateien:

Lesenswert?

ich dachte, dass der vergleich gegen 0 für hardware einfacher ist, als 
gegen einen anderen wert - deswegen fange ich bei 10000 an (ich zähle 
10000 cycles ab bei 50MHz, was in der summe 1 ms ergibt) un zähle runter 
auf 0. Dieses vorgehen habe ich noch aus optimierungsvorgängen in C 
übernomen.

Ich habe jetzt die Anzahl der Variablen auf 1 reduziert, sodass jetzt es 
so aussieht:
1
--...
2
pulse20ms: process(clk, rst)
3
    variable i:     natural range 0 to 20001 := 0;
4
    begin
5
      if( clk = '1' and clk'event ) then
6
        case cur_state is
7
          when init =>
8
            pulse <= '0';
9
            i := 10000; -- 10000 cycles = 1 ms
10
            cur_state <= start_pulse;
11
          when start_pulse =>
12
            if ( time20 = '1' ) then
13
              i := ((lang * 10000 / 256) + 10000);    -- varibal "timer" ist weg
14
              cur_state <= end_pulse;
15
              pulse <= '1';
16
            end if;
17
          when end_pulse =>
18
            if ( i = 0 ) then
19
              cur_state <= start_pulse;
20
              pulse <= '0';
21
            else
22
              i := i - 1;
23
            end if;
24
        end case;
25
      end if;
26
  end process pulse20ms;

Die warnungen bleiben trotzdem. Die Entsprechende Stelle sieht im so RTL 
View so aus (Bild1). Im schematic View sieht die (vermutlich) 
entsprechende Stelle so aus wie aufm Bild2

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


Lesenswert?

Dima Schmitt schrieb:
> deswegen fange ich bei 10000 an (ich zähle
> 10000 cycles ab bei 50MHz, was in der summe 1 ms ergibt) un zähle runter
> auf 0.
Zähl mal selber nach. Du zählst eines zuviel.
Richtig müsste es sogar so lauten:
    variable i:     natural range 0 to 1999;
So sehen jedenfalls alle meine Zähler aus:
von 0 bis zur Anzahl der Zählschritte minus 1.
Denn ein Zähler von 0 bis 3 braucht 4 Takte.
Einer von 0 bis 7 braucht 8.
Und einer von 0 bis 999 braucht demnach wieviele?

> Dieses vorgehen habe ich noch aus optimierungsvorgängen in C übernomen.
Das ist KÄSE!!!  (Ich kann gar nicht genug Ausrufezeichen machen...)
Du machst hier PARALLELE HARDWARE mit VHDL, nicht SEQUENTIELLE SOFTWARE 
mit einem PROZESSOR.

Das hört sich an wie: zwar fliege ich jetzt ein Flugzeug (VHDL), ich 
werde aber versuchen, auf der Landebahn rückwärts einzuparken, denn ich 
habe herausgefunden, dass das mit einem Auto (C) die platzsparendste Art 
ist. Insgesamt eine schlüssige Argumentation, nicht wahr?

Dima Schmitt schrieb:
> Die warnungen bleiben trotzdem.
Dann lass mal die Initialisierung weg (was die Warnung ja auch sagt):
    variable i:     natural range 0 to 20001;
Diese Initialisierung ist sowieso komplett 
unsinnig/unnötig/hinderlich, weil gleich danach das hier kommt:
        i := 10000; -- 10000 cycles = 1 ms
Und das sagt dir die Synthese...

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.