Forum: FPGA, VHDL & Co. VHDL unsigned(slv & slv) geht nicht?


von Gustl B. (-gb-)


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.

von Markus F. (mfro)


Lesenswert?

Gustl B. schrieb:
> [Synth 8-944] 5 definitions of operator "&" match here
> ["D:/vhdl/Spartan7_revc/Spartan7_revc.srcs/sources_1/AD9747.vhd":203]
>

zeig' mal deine 'use' clauses.

von Gustl B. (-gb-)


Lesenswert?

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
use ieee.math_real.all;
Library UNISIM;
use UNISIM.vcomponents.all;

von Tobias B. (Firma: www.elpra.de) (ttobsen) Benutzerseite


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. :-(

: Bearbeitet durch User
von Gustl B. (gustl_b)


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.

von Daniel M. (daniel__m)


Lesenswert?

Gustl B. schrieb:
> STEP <= unsigned(DAC_Regs(18) & DAC_Regs(17) & DAC_Regs(16));

Ich bin mir nicht sicher, aber ich denke, das hat was mit dem Array zu 
tun. Er weiß nicht, ob es ein 24 Bit Vector werden soll, oder 1 Array 
aus 3x 8 Bit.

Gustl B. schrieb:
> [Synth 8-944] 5 definitions of operator "&" match here

Welche sind es denn?

grüße

von Gustl B. (-gb-)


Lesenswert?

Daniel M. schrieb:
> Er weiß nicht, ob es ein 24 Bit Vector werden soll, oder 1 Array
> aus 3x 8 Bit.

OK, ja sehe ich ein. Wobei ja Array() ein SLV zurückliefert(?) und SLV & 
SLV wieder ein SLV wird.

Daniel M. schrieb:
> Welche sind es denn?

Wie kann ich das sehen/herausfinden?

von Da D. (dieter)


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".

von Daniel M. (daniel__m)


Lesenswert?

Gustl B. schrieb:
> Wie kann ich das sehen/herausfinden?

Modelsim z.B. müsste das mitteilen. Keine Ahnung, welchen Simulator du 
nutzt. Die Student-Edition würde dafür z.B. funktionieren.

von Daniel M. (daniel__m)


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).

: Bearbeitet durch User
von Gustl B. (gustl_b)


Lesenswert?

OK, vielen Dank! Welchen Typ hat dann ein Element des Arrays? Ich hatte 
vermutet, das wäre ein SLV. Ist das nicht so?

von Da D. (dieter)


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.

: Bearbeitet durch User
von Gustl B. (-gb-)


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?

von Da D. (dieter)


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)

von Gustl B. (-gb-)


Lesenswert?

Wow, vielen Dank für diese lehrreichen Antworten!

von Markus F. (mfro)


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 ;)

von Markus F. (mfro)


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.

: Bearbeitet durch User
von Gustl B. (-gb-)


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.

von Markus F. (mfro)


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.

von Gustl B. (-gb-)


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.

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.