VHDL unsigned(slv & slv) geht nicht?

OP #6110705
Moin,

ich habe ein Array aus SLVs:
1
type Rom20x1Byte is array (0 to 19) of std_logic_vector(7 downto 0);
2
signal DAC_Regs: Rom20x1Byte:=(others => x"00");

Und ich habe ein Signal, das soll unsigned sein:
1
signal STEP: unsigned(23 downto 0):=(others => '0');

Jetzt wollte ich das so zuweisen:
1
STEP <= unsigned(DAC_Regs(18) & DAC_Regs(17) & DAC_Regs(16));

Aber das bringt mir den Fehler:
[Synth 8-944] 5 definitions of operator "&" match here 
["D:/vhdl/Spartan7_revc/Spartan7_revc.srcs/sources_1/AD9747.vhd":203]

Verstehe ich nicht und bitte um Erklärung.
Für mich ist das eigentlich klar, & verkettet die drei SLVs und 
unsigned() macht daraus ein Unsigned.

Zusätzliche Klammern helfen auch nicht.
1
STEP <= unsigned((DAC_Regs(18) & DAC_Regs(17) & DAC_Regs(16)));

Ich habe es jetzt gelöst indem ich STEP auch als SLV angelegt habe. Aber 
interessieren würde mich der Fehler trotzdem.
(Firma: www.elpra.de) Persönliche Seite #6110901
Probier mal:
1
STEP <= unsigned(DAC_Regs(18)(DAC_Regs(0)'range) & DAC_Regs(17)(DAC_Regs(0)'range) & DAC_Regs(16)(DAC_Regs(0)'range));

Edit:

Neee klappt auch nicht. Was geht ist
1
STEP <= unsigned(DAC_Regs(18)) & unsigned(DAC_Regs(17)) & unsigned(DAC_Regs(16));

Was da jetzt aber genau die Begruendung kann ich nicht sagen. Muesste 
man sich mal die Casting Regeln anschauen, aber dazu bin ich jetzt echt 
etwas zu faul. :-(
#6110953
Ich finde ehrlich gesagt sogar deine Version mit den drei Unsigneds 
unlogischer. Denn das sind ja dann Zahlen und da finde ich das komisch 
dass man die überhaupt verketten kann. Was ist denn 7 & 9? Ja, hier geht 
das weil noch klar ist wie viele Bits das sind und so, aber das 
Verketten von SLVs und die nachträgliche Interpretation als Unsigned 
macht für mich mehr Sinn.
#6111152
Dein &-Operator ist einfach mehrdeutig. Das Ergebnis kann ein längerer 
std_logic_vector sein, oder ein array von std_logic_vector 
(Rom20x1Byte).

Du kannst VHDL auf die Spünge helfen, welchen Ergebnistyp du haben 
möchtest:

STEP <= unsigned(std_logic_vector'(DAC_Regs(18) & DAC_Regs(17) & 
DAC_Regs(16)));

Das Stichwort heißt "type qualifier".
#6111171
GHDL sagt z.B.:

> error: can't resolve overload for operator "&"
> error: possible interpretations are:
> error: array type "rom20x1byte"

und Modelsim

> ** Error: test.vhd(17): Ambiguous type in infix expression; Rom20x1Byte or
> ieee.std_logic_1164.STD_LOGIC_VECTOR.
> ** Error: test.vhd(17): (vcom-1583) Illegal type converson from 'unknown' to
> 'ieee.NUMERIC_STD.UNSIGNED' (operand type is not known).
#6111190
Doch das ist richtig. Dein Problem ist unabhängig davon, dass du sowas 
wie 'DAC_Regs(18) & DAC_Regs(17)' als Input an den & Operator gibt. Du 
kannst das gleiche Phänomen erzeugen wenn du richtige 
std_logic_vectoren, wie "10" & "01" an der Stelle versuchst.

Man muss dazu wissen, dass bei VHDL ein Array immer implizit zwei & 
Operatoren mit bekommt. Also zu jedem Array-Typ der deklariert wird, 
gibt es implizit 2 & Operatoren dazu. Einer nimmt einzelne Elemente und 
baut daraus das Array zusammen. Der andere nimmt 2 Arrays und baut 
daraus ein größeres Array des gleichen Typs. Nehmen wir deinen Fall mal 
genauer auseinander:

Du hast 2 Arraytypen in deiner Datei verfügbar.
1) Im Package ieee.std_logic_1164 ist std_logic_vector deklariert, und 
zwar als array von std_logic.
2) Du hast Rom20x1Byte deklariert als array von std_logic_vector.

Damit Ergeben sich die folgenden Operatoren:
Aus 1):
- std_logic & std_logic = std_logic_vector
- std_logic_vector & std_logic_vector = std_logic_vector

Aus 2)
- std_logic_vector & std_logic_vector = Rom20x1Byte
- Rom20x1Byte & Rom20x1Byte  = Rom20x1Byte

Nun siehst du, dass es 2 Operatoren gibt die std_logic_vector als Input 
bekommen, aber unterschiedliche Typen zurück geben. Und genau das ist 
das Problem. VHDL versucht dann anhand des erwarteten Ergebnisses den 
richtigen Operator auszuwälen. Wenn du also das Ergebniss von 
DAC_Regs(18) & DAC_Regs(17) direkt einem Signal zuweist, wird der Typ 
des Signals genommen. Da du das Ergebniss aber weiterreichst an 
unsigned(), funktioniert das nicht. Mit dem Type Qualifier gibst du dem 
Compiler dann den expliziten Hinweis, welchen Typen du an unsigned 
übergeben möchtest.
OP #6111196
Vielen Dank!

Wenn ich
STEP <= unsigned(x"000" & x"111");
schreibe bekomme ich
[Synth 8-1731] cannot convert type bit_vector to type unsigned 
["D:/vhdl/Spartan7_revc/Spartan7_revc.srcs/sources_1/AD9747.vhd":203]
als Fehler.

Da D. schrieb:
> 2) Du hast Rom20x1Byte deklariert als array von std_logic_vector.

Bedeutet das, dass sobald ich ein Array aus SLV deklariere in meinem 
Code keine SLV mehr verketten kann ohne explitzit einen type qualifier 
zu verwenden?
#6111251
Oh, sorry, das mit dem Bitvector hab ich übersehen.

Doch, du kannst du std_logic_vector noch verketten. Nur nicht 
gleichzeitig mit der Umwandlung nach nach unsigned. Wenn der Compiler 
anhand der Zuweisung zu einem signal erkennen kann, welcher Typ benötigt 
wird, geht es ohne Type Qualitfier.

1
signal in1 : std_logic_vector;
2
signal in2 : std_logic_vector;
3

4
signal a : std_logic_vector;
5
signal b : Rom20x1Byte;
6
signal c : unsigned;
7

8
-- das geht, der Operator mit dem Ergebniss std_logic_vector wird verwendet
9
a <= in1 & in1;
10

11
-- das geht, der Operator mit dem Ergebniss Rom20x1Byte wird verwendet
12
b <= in1 & in1;
13

14
-- das geht nicht, da der Compiler hier nicht aus der Zuweisung erkennen kann, welcher Typ als Ergebniss vom & erwartet wird. 
15
c <= unsigned(in1 & in1);
16

17
-- so weiß der Compiler es wieder
18
c <= unsigned(std_logic_vector'(in1 & in2));

(ich hab der Einfachheit halber die Ranges weggelassen)
#6111323
nur der Vollständigkeit halber: es gibt noch eine weitere Möglichkeit, 
dem Compiler bezüglich des gewünschten Verkettungs-Operators auf die 
Sprünge zu helfen.

Binäre Operatoren sind in VHDL ja als Funktionen mit zwei Parametern 
definiert, deshalb kann man auch (ohne cast) explizit den 
Concat-Operator aus ieee.std_logic_1164 rufen (den wollen wir ja):
1
  step <= unsigned(ieee.std_logic_1164."&"(
2
                   ieee.std_logic_1164."&"(dac_regs(18), dac_regs(17)),
3
                   dac_regs(16)));

Zugegeben, ist auch nicht schöner ;)
#6111327
... und wenn wir schon mal dabei sind. Man kann den Sermon auch noch 
einem anderen (noch nicht mehrdeutig belegten) Operator als 
Function-Alias aufprägen:
1
alias "+" is ieee.std_logic_1164."&"[std_logic_vector, std_logic_vector return std_logic_vector];

Dann kann man wieder ganz einfach schreiben:
1
step <= unsigned(dac_regs(18) + dac_regs(17) + dac_regs(16));

Ob das "schöner" ist, überlasse ich jedem selbst. Mit so was kann man 
sich auch leicht selbst ins Knie schiessen.
OP #6111486
Markus F. schrieb:
> Zugegeben, ist auch nicht schöner ;)

(-:

Markus F. schrieb:
> Man kann den Sermon auch noch
> einem anderen (noch nicht mehrdeutig belegten) Operator als
> Function-Alias aufprägen:

Den man hiermit mehrdeutig belegt. Ich finde das generell nicht gut wenn 
Operatoren unterschiedliche mehrdeutige Dinge tun. Wir haben doch sehr 
viele mögliche Zeichen und wenn die ausgehen könnte man doch auch einen 
Namen vergeben. Da finde ich dann ieee.std_logic_1164."&"() besser weil 
eindeutig wobei ich das dann kürzer benennen würde, &slv z. B.
#6111696
Gustl B. schrieb:
> Wir haben doch sehr
> viele mögliche Zeichen und wenn die ausgehen könnte man doch auch einen
> Namen vergeben

In VHDL kannst Du Funktionen und (existierende) Operatoren (als 
Funktionen) überladen. Man kann aber keine neuen Operatoren definieren 
(muß also für so was das nehmen, was da ist).

Natürlich kann man den Cast nach unsigned noch mit in der Funktion 
verstecken (der "&"-Concat-Operator, der zwei std_logic_vector-Variablen 
aneinanderhängt und ein unsigned zurückgibt, ist noch frei):
1
function "&"(a : std_logic_vector; b : std_logic_vector) return unsigned is
2
begin
3
    return unsigned(ieee.std_logic_1164."&"(a, b));
4
end function "&";
5

6
...
7

8
step <= dac_regs(18) & dac_regs(17) & dac_regs(16);

Damit hat man wieder eine eindeutige Überladung. Würde ich aber auch nur 
lokal in der architecture machen, wo ich das brauche.
OP #6114071
Ja, ne, vielen Dank, aber sowas lass ich lieber bleiben. Meine 
Einstellung ist, dass Code lesbar sein soll. Und zwar lieber lesbar als 
kurz. Wenn ich also immer ieee.std_logic_1164."&"(a, b) schreiben muss 
ist mir das lieber weil für mich schneller verstehbar als eine eigene 
Definition von & zu verwenden.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 6 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [vhdl]VHDL-Code[/vhdl]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.