Forum: FPGA, VHDL & Co. zusätzliche Arbeit


von Dima S. (onkelbenz)


Lesenswert?

Hi

ich schreibe gerade eine State-Maschiene und bin mir nicht sicher ob ich 
da "spramaßnahmen" einfügen soll oder ob es dem FPGA egal ist.

Ein Beispiel - ich will 20 ms abwarten, dazu zähle ich 100000 cycles ab 
(ist die Zahl übrigens richtig bei 50MHz Takt?). Also schreibe ich 
folgendes:

...
case cur_state is
...
          when count =>
            if ( i >= 100000 ) then -- i ist die Zählvariable
              cur_state <= pulse;
              i := 0;
            else
              i := i + 1;
              -- tick <= '0';
              -- cur_state <= count;
            end if;
...

Fraglich sind die 2 auskommentierte Zeilen.
Erstens spielt die Zeile "tick <= '0';" nur bei dem ersten Durchlauf 
eine Rolle (anders müsste ich ein zusätzliches "init" State einfügen).
Zweitens ist der cur_state sowieso "count", aber zur Sicherheit würde 
ich es gern drin haben (habe so in Beispielen gesehen).
Also sind beide Zeilen mehr oder weniger überflüssig und z.B. in einem C 
Programm würde ich diese Zeilen ganz sicher streichen. Jedoch bin ich 
grad auf einem FPGA und vermute, dass es dem egal ist, ob diese Zeilen 
da ind oder nicht. Sprich sie stellen kein zusätzliches Aufwand für den 
FPGA dar. Oder irre ich mich da?

Was passiert beim hinzufügen / weglassen der Beiden?

von Klaus Falser (Gast)


Lesenswert?

Die Zeile mit
   cur_state <= count;

macht deshalb keinen Unterschied, weil in beiden Fällen cur_state auf 
count bleibt und die selbe Logik erzeugt wird.

Die Zeile mit
   tick <= '0';
kann einen Unterschied machen, je nachdem ob und wie Tick sonst 
verwendet wurde, weil in diesem Fall tick beim Zählen auf 0 gesetzt 
werden muss.

von Der Weise (Gast)


Lesenswert?

Wäre es nicht geschickter, counter zu Anfang auf 100000 zu setzen, nach 
unten zu zählen, und bei 0 etwas zu tuen? Denn der Vergleich mit 0 ist 
angeblich platzsparender als größer-gleich.

von Dima S. (onkelbenz)


Lesenswert?

Meine Frage war eher ob FPGA zusätzliche Arbeit durch diese Zeilen 
bekommt.

Denn daraus werden ja physikalische schaltungen gemacht, und wenn ich 
meine egal ob ich 1 mal oder 100000000000000000000 mal die "tick <= 
'0';" zuweisung mache - die Leitung ist vorhanden, FPGA lässt da einfach 
strom durch und entscheidet nicht jedes mal neu ob er das macht oder 
nicht (verrichtet also keine zusätzliche Arbeit im Vergleich z.B. zu 
einem mikrokontroller, der jedes mal an der Stelle '0' in den Register 
schreiben würde).

Zumindest sehe ich die Sache so, und wollte wissen ob meine Sicht 
richtig ist.

p.s. Die Idee mit dem Vergleich gegen 0 ist meiner ansicht nach richtig, 
nur habe ich so viel platz, dass es mir egal ist; FPGA macht ja beides 
in einem Takt und wird deswegen nicht langsamer

von Falk B. (falk)


Lesenswert?

@  Dima Schmitt (onkelbenz)

>Meine Frage war eher ob FPGA zusätzliche Arbeit durch diese Zeilen
>bekommt.

Dort nicht.

>Denn daraus werden ja physikalische schaltungen gemacht, und wenn ich
>meine egal ob ich 1 mal oder 100000000000000000000 mal die "tick <=
>'0';" zuweisung mache - die Leitung ist vorhanden, FPGA lässt da einfach
>strom durch und entscheidet nicht jedes mal neu ob er das macht oder
>nicht (verrichtet also keine zusätzliche Arbeit im Vergleich z.B. zu
>einem mikrokontroller, der jedes mal an der Stelle '0' in den Register
>schreiben würde).

Richtig.

>p.s. Die Idee mit dem Vergleich gegen 0 ist meiner ansicht nach richtig,
>nur habe ich so viel platz, dass es mir egal ist; FPGA macht ja beides
>in einem Takt und wird deswegen nicht langsamer

Ich dachte du wolltest dem FPGA "Arbeit" sparen? Klar, bei 50 MHz und 
den heutigen FPGAs ist das erstmal egal. Aber wenn man effiziente und 
schnelle Schaltungen bauen will, gelten viele der alten Reglen immer 
noch, nur bei höheren Frequenzen ;-)

MfG
Falk

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


Lesenswert?

Dima Schmitt schrieb:
> case cur_state is
> ...
>           when count =>
>             if ( i >= 100000 ) then -- i ist die Zählvariable
>               cur_state <= pulse;
>               i := 0;
>             else
>               i := i + 1;
Das ist vermutlich die Zwei-Prozess-Schreibweise (wegen 
cur(rent)_state). Und damit ist der Zähler mit i eine (versteckte) 
kombinatorische Schleife.... :-o

http://www.lothar-miller.de/s9y/categories/36-Kombinatorische-Schleife

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


Lesenswert?

Dima Schmitt schrieb:
> Ein Beispiel - ich will 20 ms abwarten, dazu zähle ich 100000 cycles ab
> (ist die Zahl übrigens richtig bei 50MHz Takt?). Also schreibe ich
> folgendes:
>           when count =>
>             if ( i >= 100000 ) then -- i ist die Zählvariable
>               cur_state <= pulse;
>               i := 0;
>             else
>               i := i + 1;
>             end if;
Nur am Rande: 0...10000 sind 10001 Zählschritte. Der Zähler wird also 
systematisch um 0,1 Promille falsch gehen....

von Fetz (Gast)


Lesenswert?

Dima Schmitt schrieb:
> p.s. Die Idee mit dem Vergleich gegen 0 ist meiner ansicht nach richtig,
> nur habe ich so viel platz, dass es mir egal ist;

Wenn du soviel Platz hast, dann kann es dir doch egal sein, ob da noch 
ein Slice mehr oder weniger benötigt wird ...

Seltsame Fragestellung ...

Was du aber machen kannst ist, es einfach synthetisieren zu lassen und 
dir entweder die erzeugte Ersatzschaltung anzusehen, was wirklich 
gemacht wird, oder einfach zu kucken, wie deine FPGA-Auslastung ist.

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


Lesenswert?

Fetz schrieb:
> Wenn du soviel Platz hast, dann kann es dir doch egal sein, ob da noch
> ein Slice mehr oder weniger benötigt wird ...
Es geht eher darum, dass der eine zusätzliche Slice evtl. hinter den 
anderen sitzt und so die max. Taktfrequenz reduziert...

Man kann tun&lassen, was man will, aber wenn man seinen Baustein kennt, 
kann man besser bewerten, was die Konsequenzen draus sind.

von berndl (Gast)


Lesenswert?

Der Weise schrieb:
> Wäre es nicht geschickter, counter zu Anfang auf 100000 zu setzen, nach
> unten zu zählen, und bei 0 etwas zu tuen? Denn der Vergleich mit 0 ist
> angeblich platzsparender als größer-gleich.

Kuehne Behauptung, kannst du die belegen?

Was man machen kann ist, auf Zweierpotenzen abzufragen und die LSBs zu 
ignorieren. Z.B. wenn du 128 mal incrementen willst waere das ja von 
x"00" bis x"7F". Wuerdest du deinen Zaehler von x"01" bis x"80" laufen 
lassen, dann muesstest du nur das MSB abfragen, also: if hugo (7) = '1' 
then ...

Das spart dann wirklich Logik

von Fetz (Gast)


Lesenswert?

berndl schrieb:
> Der Weise schrieb:
>> Wäre es nicht geschickter, counter zu Anfang auf 100000 zu setzen, nach
>> unten zu zählen, und bei 0 etwas zu tuen? Denn der Vergleich mit 0 ist
>> angeblich platzsparender als größer-gleich.
>
> Kuehne Behauptung, kannst du die belegen?
>
> Was man machen kann ist, auf Zweierpotenzen abzufragen und die LSBs zu
> ignorieren. Z.B. wenn du 128 mal incrementen willst waere das ja von
> x"00" bis x"7F". Wuerdest du deinen Zaehler von x"01" bis x"80" laufen
> lassen, dann muesstest du nur das MSB abfragen, also: if hugo (7) = '1'
> then ...
>
> Das spart dann wirklich Logik

Mooooment ... das ist nicht ganz richtig ...

Wenn der Ausgang nur einen Puls bei "128" erzeugen soll, dann brauchst 
du trotzdem einen Vergleich, der alle Bits berücksichtigt.

In deinem Beispiel hast du einfach die Logik geändert ... Passt nicht 
mehr zum ursprünglichen Beispiel.

von Fetz (Gast)


Lesenswert?

Ahso vlt noch als Beispiel:

Sowas hier geht dann nicht mehr:
1
  process (clk)
2
  begin
3
    if pulse='1' then
4
      ...
5
    end if;
6
  end process;

weil pulse nach deinem Beispiel dann 128 Take '1' wäre ...

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


Lesenswert?

Fetz schrieb:
>> Das spart dann wirklich Logik
> Mooooment ... das ist nicht ganz richtig ...
Doch, das stimmt. Leider ist dein Beispiel am Thema vorbei.

Beschreib den Enable mal so wie hier:
1
signal cnt: unsigned (7 downto 0);
2
3
  process (clk) begin -- Pulserzeugung
4
    if cnt(7)='1' then
5
        pulse <= '1';
6
        cnt   <= to_unsigned(1,8);
7
    else
8
        pulse <= '0';
9
        cnt   <= cnt+1;
10
    end if;
11
  end process;
12
13
  process (clk) begin -- Pulsauswertung
14
    if pulse='1' then
15
      ...
16
    end if;
17
  end process;

von berndl (Gast)


Lesenswert?

Lothar Miller schrieb:

ah, Lothar hat aufgepasst :o)

Man kann auch noch eine Zeile einsparen:
1
process (clk) begin -- Pulserzeugung
2
   pulse <= '0';
3
   cnt   <= cnt+1;
4
   if cnt(7)='1' then
5
      pulse <= '1';
6
      cnt   <= to_unsigned(1,8);
7
   end if;
8
end process;

Uebrigens, weil Lothar auch den 'unsigned' counter verwendet: Da sieht 
man wenigstens, wo Optimierungspotential besteht. Mit Integer kommst du 
da nicht so leicht drauf...

Eine weitere Frage ist auch, ob das 'zuruecksetzen' eines counters auf 
einen krummen Wert mehr Resourcen verbraucht als ein 'reset' auf 0

von berndl (Gast)


Lesenswert?

...ups, da fehlt natuerlich noch ueberall das 'if rising_edge (clk)' 
oder aehnliches...

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


Lesenswert?

berndl schrieb:
> Eine weitere Frage ist auch, ob das 'zuruecksetzen' eines counters auf
> einen krummen Wert mehr Resourcen verbraucht als ein 'reset' auf 0
Nein, tut es nicht, solange nicht ein zusätzlicher "globaler" Reset 
definiert ist. Das hier ist schlecht:
1
  process begin -- Pulserzeugung
2
    wait until rising_edge(clk);
3
    if reset='1' then              -- synchroner Zählerreset Nummer 1 --> alle Bits auf '0'
4
      cnt <= (others=>'0');
5
    else
6
      if cnt(7)='1' then
7
        pulse <= '1';
8
        cnt   <= to_unsigned(1,8); -- synchroner Zählerreset Nummer 2 --> cnt(0) wird anders behandelt...
9
      else
10
        pulse <= '0';
11
        cnt   <= cnt+1;
12
      end if;
13
    end if;
14
  end process;
Wenn es nur 1 Reset/Preset gibt, dann kann das 1:1 auf diese Eingänge am 
Flipflop abgebildet werden. Wenn aber beim 1. Reset das FF zurückgesetzt 
und beim 2. Reset gesetzt werden soll, dann braucht das zusätzliche 
Logik.

von Günter (. (dl4mea)


Lesenswert?

Hallo,
was halten die Spezialisten eigentlich davon das Signal pulse 
kombinatorisch zu erzeugen?

Ich glaub zwar daß das den Pulse einen Clock nach vorn zieht, aber es 
spart ein Register?

Ciao, Günter
1
process (clk) begin -- Pulserzeugung
2
   cnt   <= cnt+1;
3
   if cnt(7)='1' then
4
      cnt   <= to_unsigned(1,8);
5
   end if;
6
end process;
7
8
pulse <= '1' when cnt(7)='1' else '0';

oder gleich
1
process (clk) begin -- Pulserzeugung
2
   cnt   <= cnt+1;
3
   if cnt(7)='1' then
4
      cnt   <= to_unsigned(1,8);
5
   end if;
6
end process;
7
8
pulse <= cnt(7);

von berndl (Gast)


Lesenswert?

Günter (dl4mea) schrieb:
> Ich glaub zwar daß das den Pulse einen Clock nach vorn zieht, aber es
> spart ein Register?

Ja. Sieht man schoen an deinem 2. Beispiel (clock Abfrage fehlt aber 
noch). Beim 1. Beispiel koennte man noch denken, es braeuchte eine LUT 
fuer den Vergleich...

von Fetz (Gast)


Lesenswert?

Lothar Miller schrieb:
> process (clk) begin -- Pulserzeugung
>     if cnt(7)='1' then
>         pulse <= '1';
>         cnt   <= to_unsigned(1,8);
>     else
>         pulse <= '0';
>         cnt   <= cnt+1;
>     end if;
>   end process;


Ja gut, so geht natürlich. Dachte, du lässt den Counter freilaufen und 
nimmst nur das 8te Bit.

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.