VHDL unsigned(slv & slv) geht nicht?

OP #6110705
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

... 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
Lesenswert?

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
Lesenswert?

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
Lesenswert?

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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren