Forum: FPGA, VHDL & Co. Mal wieder: Rechnen in VHDL


von Christian (Gast)


Lesenswert?

Hallo Community,

ich habe ein Problem beim einfachen Addieren in VHDL. Ich vermute, dass 
es an falschen/fehlenden Bibliotheken liegt.

Ich habe ein Eingangssignal :
1
data          : IN  std_logic_vector (63 DOWNTO 0);

in dem die obersten 8 Bit einen Wert darstellen, den ich mit einem 
Integer addiere.
1
variable v_next_check    : integer := 0;
2
variable v_header_words  : integer := 0;



Die Operation dazu ist folgende:
1
v_header_words := to_integer(unsigned((v_data(63 downto 56))));               
2
v_next_check :=  (v_next_check + v_header_words );


Bis hier hin funktioniert die Sache auch ganz gut.

Wenn ich jetzt aber
1
v_next_check :=  (v_next_check + v_header_words ) + 1;


rechne, funktioniert die Sache nicht mehr.
Ich habe folgende Bibliotheken eingebunden:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
use IEEE.STD_LOGIC_UNSIGNED.ALL;
4
use ieee.std_logic_1164.all;
5
use ieee.numeric_std.all;
6
7
LIBRARY altera_mf;
8
USE altera_mf.all;

von Cihan K. (lazoboy61)


Lesenswert?

Christian schrieb:
> LIBRARY ieee;
> USE ieee.std_logic_1164.all;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
>
> LIBRARY altera_mf;
> USE altera_mf.all;

Nimm mal die "IEEE.STD_LOGIC_UNSIGNED.ALL" raus, die vertragen sich 
nämlich nicht mit "ieee.numeric_std.all". Und nimm auch das doppelt 
gemoppelte "ieee.std_logic_1164.all" raus.

Versuch mal evtl. den integern eine Range zuzuordnen, wie Integer range 
0 to ...

Cihan

von Christian (Gast)


Lesenswert?

Hallo Cihan,

habe deine Tipps befolgt, hat leider nicht geholfen... Folgender Stand:
1
LIBRARY ieee;
2
USE ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
LIBRARY altera_mf;
6
USE altera_mf.all;
1
data          : IN  std_logic_vector (63 DOWNTO 0);
2
 
3
4
5
variable v_next_check    : integer range 0 to 100 := 0;
6
variable v_header_words  : integer range 0 to 100 := 0;
funktioniert:
1
v_header_words := to_integer(unsigned((v_data(63 downto 56))));               
2
v_next_check :=  (v_next_check + v_header_words );

funktioniert nicht:
1
v_header_words := to_integer(unsigned((v_data(63 downto 56))));               
2
v_next_check :=  (v_next_check + v_header_words )+1;

von M. D. (wpmd)


Lesenswert?

Christian schrieb:
> Wenn ich jetzt aberv_next_check :=  (v_next_check + v_header_words ) + 1;
>
> rechne, funktioniert die Sache nicht mehr.
> Ich habe folgende Bibliotheken eingebunden:

Was heist hier denn "funktioniert nicht mehr"?
Kommt ein falsches Ergebnis raus oder wie zeigt sich der Fehler?

Ich gehe davon aus dass in deinen zu verrechnenden 8Bit eine Zahl <99 
drin steht... (variable v_next_check    : integer range 0 to 100 := 0;)

von Christian (Gast)


Lesenswert?

M. D. schrieb:
> as heist hier denn "funktioniert nicht mehr"?
>
> Kommt ein falsches Ergebnis raus oder wie zeigt sich der Fehler?

richtig, falsches Ergebnis.

M. D. schrieb:
> Ich gehe davon aus dass in deinen zu verrechnenden 8Bit eine Zahl <99
>
> drin steht... (variable v_next_check    : integer range 0 to 100 := 0;)

auch richtig. Die Zahl wird sich im Bereich 0 bis 100 bewegen. 
Spezifiziert ist es natürlich für den ganzen Bereich. Für den Test hab 
ich es auch erstmal mit Zahlen im Bereich von 1-3 gemacht.

Kurz zur Aufklärung.

Die Zahl in
1
 v_header_words
 lässt meinen counter
1
v_next_check
 um eben genau seinen Wert weiter springen.

Wenn
v_next_check = 1
v_header_words = 2

dann wird v_next_check = v_next_check + v_header words = 3... wie 
erwartet.

Wenn

v_next_check = 1
v_header_words = 3

dann wird v_next_check = v_next_check + v_header words = 4... wie 
erwartet.

Wenn

v_next_check = 1
v_header_words = 2

dann wird v_next_check = v_next_check + v_header words + 2 = ???

--> Problem!

von Christian (Gast)


Lesenswert?

Christian schrieb:
> v_next_check = 1
>
> v_header_words = 2
>
>
>
> dann wird v_next_check = v_next_check + v_header words + 2 = ???
>
>
>
> --> Problem!

Wenn

v_next_check = 1
v_header_words = 2

dann wird v_next_check = v_next_check + v_header words + 1 = ???

--> Problem!

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


Lesenswert?

Christian schrieb:
> falsches Ergebnis.
Und welches?
Was erwartest du wo und was bekommst du?

von Christian (Gast)


Lesenswert?

Lothar Miller schrieb:
> Und welches?
>
> Was erwartest du wo und was bekommst du?

v_next_check = 1
v_header_words = 2

dann wird v_next_check = v_next_check + v_header words + 1 = ???

--> Ich erwarte eine 4 bekomme aber irgendetwas.

ÄÄhhhmmm...

http://www.gstitt.ece.ufl.edu/vhdl/refs/vhdl_math_tricks_mapld_2003.pdf

D_uv <= B_uv + 1 ; -- Unsigned + Integer = Unsigned

Was bedeutet das für mich?

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


Lesenswert?

Christian schrieb:
> --> Ich erwarte eine 4 bekomme aber irgendetwas.
> Die Zahl in
>  v_header_words
> lässt meinen counter
>  v_next_check
Eine Variable als Zähler?

> D_uv <= B_uv + 1 ; -- Unsigned + Integer = Unsigned
Wo ist in deinem geposteten Code ein Usigned Vektor?

> Was bedeutet das für mich?
Poste mal die ganze Beschreibung als *.vhdl Anhang.

von Christian (Gast)


Lesenswert?

erledigt... Der Fehler lag woanders. Das Rechnen hat korrekt 
funktioniert. Danke dir Lothar, dass du mich "gezwungen" hast, meine 
Variable mal nach "draussen" zu legen, damit ich sie mir anschauen kann.

von Christian (Gast)


Lesenswert?

Lothar Miller schrieb:
> Eine Variable als Zähler?

Was ist daran verkehrt?`

Das Problem lag eher woanders. Nach meiner alten Beschreibung wurde die 
Variable bei jedem Takt um eins erhöht... Das will ich nicht.
1
else              
2
v_header_words := to_integer(unsigned((v_data(63 downto 56)))); 
3
              v_next_check := v_next_check + v_header_words + 1 ;

Nach der neuen Beschreibung wird die Variable nur noch um den 8-Bit Wert 
+ 1 erhöht, wenn auch wirklich ein 8-Bit Wert da ist...
1
elsif (v_data(63 downto 56) /= x"00") then
2
              v_header_words := to_integer(unsigned((v_data(63 downto 56)))); 
3
              v_next_check := v_next_check + v_header_words + 1 ;

von Duke Scarring (Gast)


Lesenswert?

Christian schrieb:
> Nach der neuen Beschreibung wird die Variable nur noch um den 8-Bit Wert
> + 1 erhöht, wenn auch wirklich ein 8-Bit Wert da ist...
Und was ist, wenn Dein 8-Bit Wert mal Null ist?

Ich baue mir an jede Zahl ein enable dran. Und nur wenn das '1' ist 
wird auch weitergerechnet.

Duke

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


Lesenswert?

Christian schrieb:
>> Eine Variable als Zähler?
> Was ist daran verkehrt?
Es ist gefährlich. Besonders, wenn man diese Frage stellt... ;-)
Siehe den Beitrag "Variable vs Signal"
Wegen der extensiven Verwendung von Variablen vermute ich stark, dass du 
"sonst" z.B. in C programmierst. Dir muss aber unbedingt bewusst sein, 
dass du mit VHDL Hardware beschreibst. Das sind zwei komplett 
unterschiedliche Paar Stiefel.

Christian schrieb:
> Ich habe folgende Bibliotheken eingebunden:LIBRARY ieee;
> USE ieee.std_logic_1164.all;
> use IEEE.STD_LOGIC_UNSIGNED.ALL;
> use ieee.std_logic_1164.all;
> use ieee.numeric_std.all;
Dazu noch den Beitrag "IEEE.STD_LOGIC_ARITH.ALL obsolete" incl. der 
darin enthaltenen Links...

von Christian (Gast)


Lesenswert?

Hallo Lothar,

ich kenne den Unterschied zwischen Variable und Signal. Ich brauche den 
Wert der Berechnung allerdings sofort. Deswegen eine Variable.

Den zweiten Beitrag habe ich auch bereits gelesen ;)

@Duke

Das ist genau das, was ich will. Wenn in den 8Bit nichts drin ist, soll 
auch keine Berechnung ausgeführt werden... ;)

von FPGA-Progger (Gast)


Lesenswert?

Duke Scarring schrieb:
> Ich baue mir an jede Zahl ein enable dran. Und nur wenn das '1' ist
> wird auch weitergerechnet.
Könntest Du mir bitte erklären, wie das gemeint ist?

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


Lesenswert?

Christian schrieb:
> ich kenne den Unterschied zwischen Variable und Signal.
Gut.
Oder vielleicht doch nicht?
> Ich brauche den Wert der Berechnung allerdings sofort.
> Deswegen eine Variable.
In der Hardware wirst/kannst du keinen Unterschied zwischen Variable und 
Signal erkennen können. Lediglich im logischen Beschreibungsablauf 
ändert sich der Wert einer Variable "sofort", mitten im Prozess. Weil 
aber ein Prozess in der realen Zeit 0 "abgearbeitet" wird, müssen 2 
Hardwarepfade realisiert werden: einer mit dem Wert der Variablen vor 
der Änderung und einer mit dem Wert nach der Änderung...

Nehmen wir mal diese kleine Beschreibung:
1
process (a,b,c,d) 
2
variable x : integer;
3
begin
4
  x := a;
5
  if (x=3) then
6
    ...
7
    x := x+b;
8
  end if;
9
  if (x>10) then
10
    ...
11
  end if;
12
  x := x-5;
13
  if (x<c) then
14
    ...
15
    erg <= x+d;
16
  else
17
    x := x-d;
18
    erg <= x+x+a;
19
  end if;
20
end process;
Alles schön logisch und klar, wenn es einfach nur der Reihe nach 
abgearbeitet wird. Aber extrem aufwendig, wenn es gleichzeitig 
abgearbeitet werden muss, weil dann ja alle Berechnungen und alle if's 
in Kombinatorik umgesetzt werden müssen.

Und das ist das Problem, das Software-Programmierer verfallen: sie 
möchten die bequeme Seite von Variablen "nutzen", wundern sich dann, 
dass die resultierende Hardware "nur noch" 10MHz schafft...

von Duke Scarring (Gast)


Lesenswert?

FPGA-Progger schrieb im Beitrag #3149157:
> Duke Scarring schrieb:
>> Ich baue mir an jede Zahl ein enable dran. Und nur wenn das '1' ist
>> wird auch weitergerechnet.
> Könntest Du mir bitte erklären, wie das gemeint ist?

Z.B. so (ungetestet):
1
entity accu is
2
  port (
3
    clk         : in  std_ulogic;
4
    data_in     : in  unsigned(...);
5
    data_in_en  : in  std_ulogic;
6
    data_out    : out unsigned(...);
7
    data_out_en : out std_ulogic
8
  );
9
end entity accu;
10
11
architecture rtl of accu is
12
13
  signal count : integer range 0 to 127 := 0;
14
  signal sum   : unsigned(...) := (others =>'0');
15
16
begin
17
18
  process
19
  begin
20
    wait until rising_edge( clk);
21
22
    data_out_en <= '0';
23
24
    if data_in_en = '1' then
25
26
      if count = 127 then
27
        data_out    <= sum;
28
        data_out_en <= '1';
29
        sum         <= data_in;
30
      else
31
        sum         <= data_in + sum;
32
      end if;
33
34
      if count = 127 then
35
        count <= 0;
36
      else
37
        count <= count + 1;
38
      end if;
39
40
    end if;
41
  end process;
42
43
end architecture rtl;

D.h. immer wenn das zugehörige enable auf '1' passiert was mit den 
Daten. Genauso wir nur bei gültigen Ausgangsdaten das entsprechende 
enable gesetzt.

Wenn Du eine mehrstufige Berechnung hast, kannst Du so einfach alle 
Stufen hintereinander schalten. Die nächste Stufen rennt erst dann los, 
wenn die vorhergehende fertig ist.

Duke

von Hans (Gast)


Lesenswert?

ungewöhnlicher stil

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.