Forum: FPGA, VHDL & Co. Addition von std_logic_vector?


von Tobias (bandchef)


Lesenswert?

Hi Leute,

ich hab ein Problem mit der Addition von zwei std_logic_vectors. Hier 
erstmal der Code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
6
entity addSubUnit is
7
8
  Generic( n : integer := 8);
9
  Port (  ctrl : in  STD_LOGIC;
10
        data1_in : in  STD_LOGIC_VECTOR (n-1 downto 0);
11
        data2_in : in  STD_LOGIC_VECTOR (n-1 downto 0);
12
        data_out : out  STD_LOGIC_VECTOR (n-1 downto 0));
13
        
14
end addSubUnit;
15
16
architecture Behavioral of addSubUnit is
17
18
begin
19
  
20
  
21
  With ctrl select
22
    data_out <= data1_in + data2_i) when 0,
23
    data1_in - data2_in when others;
24
25
end Behavioral;

Die Fehlermeldung lautet: "+ can not have such operands in this 
context." und "- can not have such operands in this context."

Das Problem in meinem Code ist nun wohl, dass sich std_logic_vectors 
nicht so einfach addieren lassen, bzw. in IEEE.NUMERIC_STD.ALL keine 
dafür passende Operation integriert ist.
Wie kann ich das Problem nun lösen? Irgendwie muss es ja gehen, oder?

Danke!

Edit: Ich benutze Xilinx ISE 14.7.

: Bearbeitet durch User
von J. S. (engineer) Benutzerseite


Lesenswert?

In der Tat, weil Vektoren dimensionslos sind und die Synthese da mehrere 
Optionen hätte, das auszuführen. Du musst die Vektoren vorher "casten" 
und mit z.B. signed umsetzen. Dabei kommt es aber darauf an, welches 
Datenformat Deine Zahlen haben.

In Deinem Fall meinst Du wahrscheinlich:

data_out <= std_logic_vector (unsigned(data1_in) + unsigned(data2_i));

Bei Brüchen (fractional) sieht es aber anders aus und auch, wenn eine 
der beiden Zahlen im Zweierkomplement vorliegt.

Wenn du keine fractions verwendest, kannst du das einfacher machen, 
indem Du direkt mit den (Ganz-)Zahlen rechnest, z.B. Integer.

Solche Rechnungen mit Vektoroperationen macht man eigentlich nur in 
Sonderfällen, bei Rohdaten und wenn es praktisch nichts zu rechnen gibt.

: Bearbeitet durch User
von Tobias (bandchef)


Lesenswert?

Danke, so funktioniert das nun! Ich habe es mir ja schon gedacht, dass 
es mit den Vektoren zusammenhängen muss.

Ich hab nun gleich ein weiteres Problem. Ich möchte einen Multiplexer 
erstellen, der abhängig von einer beliebigen Anzahl an Eingängen ist. 
Kann man diese Aufgabe durch eine for-loop lösen?

Wenn ich hier nun den Programm-Rahmen kurz skizziere, dann sieht das nun 
so aus:
1
entity multiplexer is
2
3
  Generic(n : Integer := 8);
4
  --Ist diese for-loop überhaupt in der Entity richtig platziert und wo muss ich das x vorher deklarieren?
5
  for n in x-1 downto 0 generate
6
    Port(...)
7
  end loop;
8
9
end multiplexer;
10
11
12
13
architecture Behavioral of multiplexer is
14
15
begin
16
17
18
end Behavioral;

Meine Probleme die ich nun mit dem Multiplexer habe sind, dass ich nicht 
recht weiß, ob die Definition der for-loop in der Entity richtig ist und 
ob ich das x richtig instantiiert habe...

Danke für die etwaigen Antworten!

von Achim S. (Gast)


Lesenswert?

Tob Ias schrieb:
> Ich möchte einen Multiplexer
> erstellen, der abhängig von einer beliebigen Anzahl an Eingängen ist.

du wolltest wahrscheinlich schreiben:
   for i in n-1 downto 0 generate...

funktionieren würde stattdessen:

  Generic(n : Integer := 8);
  Port (
   eingaenge: in std_logic_vector(n-1 downto 0);
   ....

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


Lesenswert?

Jürgen Schuhmacher schrieb:
> Du musst die Vektoren vorher "casten"
> und mit z.B. signed umsetzen. Dabei kommt es aber darauf an, welches
> Datenformat Deine Zahlen haben.
Siehe auch dort:
http://www.lothar-miller.de/s9y/categories/16-Numeric_Std

von Tobias (bandchef)


Lesenswert?

Achim S. schrieb:
> Tob Ias schrieb:
>> Ich möchte einen Multiplexer
>> erstellen, der abhängig von einer beliebigen Anzahl an Eingängen ist.
>
> du wolltest wahrscheinlich schreiben:
>    for i in n-1 downto 0 generate...
>
> funktionieren würde stattdessen:
>
>   Generic(n : Integer := 8);
>   Port (
>    eingaenge: in std_logic_vector(n-1 downto 0);
>    ....

Vielen Dank für deine Antwort. Ich hab nun versucht einen Multiplexer zu 
erstellen. Mit der von dir angegebenen Portmap (ohne Umweg über eine 
for-loop) gibt's auch keine Probleme, wenn ich den Syntax durch die IDE 
checken lassen will.

Aber in der Architecture des Multiplexers gibt es ein Problem. Hier hat 
dies wohl wieder irgendwie mit den verwendeten Vektoren zu tun.
Die Fehlermeldung lautet: "AND can not have such operands in this 
context."



Hier noch mein VHDL-Code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.NUMERIC_STD.ALL;
4
5
entity multiplexer is
6
7
  Generic(n : Integer := 8);
8
  Port(  inputs_A  : in STD_LOGIC_VECTOR (n-1 downto 0);
9
      inputs_B  : in STD_LOGIC_VECTOR (n-1 downto 0);
10
      SEL    : in BIT;
11
      nE      : in BIT;
12
      C_out    : in STD_LOGIC_VECTOR (n-1 downto 0));
13
14
end multiplexer;
15
16
17
18
architecture Behavioral of multiplexer is
19
20
begin
21
  
22
  --unbedingte Signalzuweisung für Multiplexer
23
  C_out <= (inputs_A AND NOT(SEL)) OR (inputs_B AND SEL) or nE;
24
25
end Behavioral;



Was muss ich an dieser unbedingten Signalzuweisung ändern, dass der 
Multiplexer korrekt erstellt wird? Ein einfaches
1
std_logic_vector(unsigned(inputs_A))
, wie in der Frage vorher, tut's jedenfalls nicht. Da bekomme ich gleich 
noch mehr Fehler: "AND can not have such operands in this context." und 
"type conversion std_logic_vector is not an array index prefix.".

Vielleicht kann mir ja nochmal jemand weiterhelfen! Danke!

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


Lesenswert?

Der AND Operator kann nicht einen Vektor mit einen einzelnen Bit 
vergleichen/verUNDen. Wie auch?

Wenn du einen Vektor zusammenhängen willst,vdann brauchst du den & 
Operator (Concatenation)...

von Tobias (bandchef)


Lesenswert?

Lothar Miller schrieb:
> Der AND Operator kann nicht einen Vektor mit einen einzelnen Bit
> vergleichen/verUNDen. Wie auch?
>
> Wenn du einen Vektor zusammenhängen willst,vdann brauchst du den &
> Operator (Concatenation)...

Wäre es auch eine Möglichkeit den Select- und notEnable-Eingang vom 
STD_LOGIC_VECTOR anzugeben?
Dann verschenke ich zwar "Speicherplatz", aber wenn man mal davon 
absieht, sollte es funktionieren, oder? Der Syntax Check läuft 
jedenfalls durch.

Dann noch kurz eine Frage zum Concatenation-Operator:
Ich will ja nicht einfach an einen Vektor ein Bit konkatenieren, sondern 
logisch miteinander verknüpfen! Wie stellst du dir das dann vor?

von Optimus (Gast)


Lesenswert?

Um deine bisherige Struktur zu erhalten und keine if Anweisungen zu 
benutzen, würde ich folgenden Vorschlag machen:
1
architecture Behavioral of multiplexer is
2
signal temp_sel, temp_nE : std_logic_vector(inputs_A'length);
3
begin
4
  
5
  temp_SEL <= (others => SEL);
6
  temp_nE <= (others => nE);
7
  --unbedingte Signalzuweisung für Multiplexer
8
  C_out <= (inputs_A AND NOT(TEMP_SEL)) OR (inputs_B AND temp_SEL) or temp_nE;
9
10
end Behavioral;

Ohne Gewähr auf Richtigkeit ;). Das Problem ist wie bereits von Lothar 
erwähnt, dass du versuchst, einen Vektor mit nur einem Bit zu verunden. 
In meinem Code-Schnipsel "skaliere" ich das Select- sowie das nE-Signal 
auf einen Vektor hoch um dann diese in die Logik einzuführen.

Achja, könnte sein, dass er wegen Bit und STD_LOGIC meckert. Ich würde 
SEL und nE auch als STD_LOGIC deklarieren. Sowohl Bit als auch STD_LOGIC 
in einer Entity zu benutzen ist meiner Meinung unsauber.

von berndl (Gast)


Lesenswert?

du koenntest auch einfach ein
1
for i in 0 to n-1 generate
2
...
3
end generate
 drumlegen (falls im process: dann loop anstatt generate).

Ausserdem: Die numeric.std brauchst du nicht (mal darin nachlesen was 
die macht). Und noch: Warum zum Geier 'bit' als input? Da nimmt man 
'std_logic'...

Sieht mal wieder sehr nach Vorlesung aus mit Profs, die auf einem Niveau 
von vor 15 Jahren stehengeblieben sind und noch nie wirklich was mit 
VHDL gemacht haben...

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.