Forum: FPGA, VHDL & Co. ERROR: (VHDL-1052) 5 definitions of operator "&" match here


von Chris2k (Gast)


Lesenswert?

Hallo,

ich habe mal wieder ein klitzekleines Problem :(

Ich versuche gerade, in VHDL zu dividieren (mit Hilfe von Lothar 
Miller's Radix 2-Routine). Dazu möchte ich nun den dividend und divisor 
ihre jeweiligen Werte zuweisen. Diese sind aus Variablen 
zusammenzubauen:
1
dividend = fr - bin_width/2;
2
divisor = s_sd * sqrt(2);

Die Radix 2-Division ist wohl nur für positive Zahlen geeignet. Ich habe 
vorzeichenbehaftete Zahlen im Dividenden, die ich jedoch vorher in 
positive Zahlen umwandle und mir nur merke, ob der Dividend positiv oder 
negativ war, um das Ergebnis am Ende zu korrigieren (Divisor hier immer 
positiv).

In VHDL sieht das so aus:
1
[...]
2
signal s_sd: unsigned (15 downto 0);
3
signal sdiv_dividend0: std_logic_vector (31 downto 0);
4
signal sdiv_divisor0:  std_logic_vector (sdiv_dividend0'range);
5
signal sdiv_quotient0: std_logic_vector (sdiv_dividend0'range);
6
[...]
7
variable v_fr:      signed (16 downto 0);
8
variable bin_width: signed (11 downto 0);
9
constant sqrt_2:    integer := 724; -- constant of 512*SQRT(2)
10
[...]
11
sdiv_divisor0 <= std_logic_vector(s_sd * to_unsigned(sqrt_2,s_sd'length));
12
13
if ((v_fr - bin_width(bin_width'length-1 downto 1)) < 0) then -- divide routine is valid for unsigned input only
14
  sdiv_dividend0 <= std_logic_vector( ((sdiv_dividend0'length downto v_fr'length+1  => '1' ) & ( not(v_fr - bin_width(bin_width'length-1 downto 1))+1 )) ); -- negative value: invert number
15
  sdiv_sgn0 <= '1';
16
else
17
  sdiv_dividend0 <= std_logic_vector( (sdiv_dividend0'length-1 downto v_fr'length  => '0' ) & (v_fr - bin_width(bin_width'length-1 downto 1)) );
18
  sdiv_sgn0 <= '0';
19
end if;
Die Synthese läuft ohne Fehler (Lattice Diamond mit Synplify Pro) durch, 
es gibt jedoch einige Warnungen, die jedoch nichts mit dem Fehler hier 
zu tun haben sollten. Soweit, so gut. Jetzt möchte ich gern versuchen, 
meinen VHDL-Code zu simulieren. In Diamond klickt man dazu auf 
Design->Generate Hierarchy, um dann eine Testbench erzeugen zu lassen. 
Genau da kommt es dann zu Fehlern.

> ERROR: (VHDL-1052) 5 definitions of operator "&" match here

Als Ursache gelten die Zuweisungen von sdiv_dividend0 oben. Kann mir 
jemand sagen, was dort falsch ist oder was man ändern müsste?

Falls jemandem sonst noch was zu der Art und Weise einfällt, bin ich 
ganz Ohr. Bin Anfänger und es ist das erste Mal, dass ich auch mit 
Attributen arbeite, um den Quelltext einfacher wartbar zu machen.

von Andreas H. (ahz)


Lesenswert?

Chris2k schrieb:
> Kann mir jemand sagen, was dort falsch ist oder was man ändern müsste?

Das '&' wird (hier nur formal) überladen. Formal heisst, das es ein 
Unterschied ist wenn Du <UNSIGNED> & <UNSIGNED> im vergleich zu <SIGNED> 
& <SIGNED> compilierst. Das ist hier zwar das Gleiche, muss es aber 
nicht sein.

Was hat (sdiv_dividend0'length-1 downto v_fr'length  => '0' ) für einen 
Typ ?
Aus dem Code wird irgendwann ja nur (31 downto 17 => '0'), wenn ich mich 
nicht verguckt habe.

'0' kann Std_logic, Std_ulogic, signed, unsigned, 
"Tante_Gertruds_Lieblingsdonut" oder noch etwas anderes sein.

Soll er nun also

   <unsigned> '&' <irgendwas> oder
   <signed>   '&' <irgendwas> oder
   <std_logic_vector> '&' <irgendwas> oder ...

nehmen ? (Er hat ja anscheinend 5 Möglichkeiten gefunden)

U got it ? Probier mal "std_logic_vector( (sdiv_dividend0'length-1 
downto v_fr'length  => '0' ) )

Dann sollte es klappen ;-)

HTH
Andreas

P.S: Das alles während einer (jetzt fertigen) Sim, ohne weitere Prüfung. 
Kann also auch alles falsch sein ;-)

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


Lesenswert?

Welche IEEE Bibliotheken sind denn ganz am Anfang eingebunden?

Und: such mal auf meiner HP nach "Qualifier".

von Chris2k (Gast)


Lesenswert?

Danke Andreas, das hat mich erstmal auf die richtige Fährte geführt, 
denke ich. Gut erklärt :) Aber '0' sollte doch immer ein std_logic 
werden, oder nicht? Hinter die Typen bin ich noch nicht so wirklich 
gestiegen. Ich finde auch, solche grundlegenden Dinge werden an kaum 
einer Stelle erklärt, und nach sowas lässt sich auch eher schwerlich im 
Internet suchen.

Nun bekomme ich jedoch

> Type mismatch of arguments in concatenation

für die dividend-Zuweisung.

Den rechten Teil der Gleichung noch gecasted und den äußeren 
std_logic_vector-Cast entfernt:
1
sdiv_dividend0 <= std_logic_vector( (sdiv_dividend0'length-1 downto v_fr'length  => '1' ) ) & std_logic_vector( not(v_fr - bin_width(bin_width'length-1 downto 1))+1 ) ;
und ich bekomme
> Expression has ambiguous type
für den linken Term, also eine Mehrdeutigkeit. Aber ich habs 
hinbekommen, siehe unten.

Lothar:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
use ieee.math_real.ceil;
5
use ieee.math_real.log2;
6
7
use work.pkg_sqrt.all;
sind eingebunden.

Die Seite mit den Qualifiern hab ich mir jetzt schon parallel 
angeschaut, und erstmal Folgendes gemacht:
1
sdiv_dividend0 <= std_logic_vector'(sdiv_dividend0'length-1 downto v_fr'length  => '1') & std_logic_vector( not(v_fr - bin_width(bin_width'length-1 downto 1))+1 );

Und voilà, es funktioniert. Also hatte ich zwei Fehler: Einerseits waren 
die Datentypen für die Concatenation zueinander nicht passend, und 
zweitens war der zurückgegebene Datentyp des linken Terms nicht 
eindeutig identifizierbar. Komisch, in meinem Buch "The Designer's Guide 
to VHDL" findet man nichts zum Thema Qualifier im Stichwortverzeichnis, 
gibt's da noch eine andere Bezeichnung?

Die Fehlermeldungen von der Division sind nun verschwunden. Aber :) Ich 
meinte, ich hatte es verstanden, da poppt die gleiche Fehlermeldung in 
einem anderen Teil auf:
> ERROR: (VHDL-1052) 2 definitions of operator "&" match here
1
signal s_sd: unsigned (15 downto 0);
2
[...]
3
variable v_sum: signed (31 downto 0);
4
constant cnt_size: integer := 9;
5
[...]
6
s_sd <= sqrt( unsigned( std_logic_vector'(cnt_size-2 downto 0 => '0') & (std_logic_vector(v_sum(v_sum'length-1 downto cnt_size))) ) ); -- divide by 512, sign can be ignored as value is always positive
Das ist ein Funktionsaufruf für SQRT 
(http://vhdlguru.blogspot.de/2010/03/vhdl-function-for-finding-square-root.html). 
Die Funktion erwartet als Parameter einen 32 Bit unsigned Wert und gibt 
einen 16 Bit unsigned zurück.

Wie können hier bitte zwei Definitionen vom Operator vorkommen? Ist doch 
nun alles eindeutig, oder nicht?

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


Lesenswert?

Was passiert, wenn du nicht alles im Funktionsaufruf machst, sondern 
ein Hilfssignal verwendest und das der Funktions übergibst?

Und warum machst du da den Umweg über std_logic, wenn sowieso alles 
unsigned ist? Mein erster Ansatz wäre so:
1
s_sd <= sqrt( unsigned'(cnt_size-2 downto 0 => '0') & v_sum(v_sum'length-1 downto cnt_size) );
Oder einfach so:
1
s_sd <= sqrt( v_sum/512 );
Denn diese 512er Division kann der Synthesizer von allein, das ist ja 
nur ein Umverdrahten...

von Chris2k (Gast)


Lesenswert?

Erstmal habe ich jetzt v_sum als unsigned Variable definiert (war vorher 
signed, was aber nicht nötig war).

Ich meine, ganz zu Anfang hätte ich es auch einfach so probiert, wie du 
es am Ende vorschlägst mit der Division durch 512:
1
s_sd <= sqrt( v_sum / 512 );

Wenn ich das jetzt so mache, kommt

> Width mismatch, variable a has width 32, value 33

Wie kann ich nun am einfachsten die Bitbreite um ein Bit reduzieren? Und 
wieso erhöht sich bei einer Division die Breite überhaupt?

von Chris2k (Gast)


Lesenswert?

Okay ich hab den Fehler nun wohl gefunden. Mein v_sum war wohl 33 Bit 
breit (sic!). Dadurch passte die Variable nicht in die Funktion....

Danke!

von Andreas H. (ahz)


Lesenswert?

Chris2k schrieb:
> Aber '0' sollte doch immer ein std_logic
> werden, oder nicht?

NEIN (!!!), eben nicht.

Std_logic ist nur ein Datentyp von Vielen.

Und Du kannst beliebig viele neue Typen basteln, die auch'0' enthalten, 
z.B signed und unsigned.

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


Lesenswert?

Andreas H. schrieb:
> Und Du kannst beliebig viele neue Typen basteln, die auch '0' enthalten,
> z.B signed und unsigned.
Es reichen die bereits definierten Typen schon locker aus. Der 
einfachste ist z.B. das bit mit den Werten '0' und '1'...

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.