Forum: FPGA, VHDL & Co. 48Bit BCD Code in Binärcode wandeln


von MemY (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich habe ein kleineres Problem mit einer Konvertierungseinheit. 
Kompilieren lässt sich der Code, jedoch erscheint während der Simulation 
folgende Fehlermeldung:
1
# ** Warning: NUMERIC_STD.TO_UNSIGNED: vector truncated
2
#    Time: 0 ps  Iteration: 1  Instance: /gray_or_bcd_2_binary_tb/dut

Kann mir da jemand weiterhelfen?

Mein Code + TB ist im Anhang.

Vielen Dank schonmal vorab!

Gruß MemY

von Alexander F. (alexf91)


Lesenswert?

Für deinen Fehler habe ich jetzt nichts spezielles, aber ich vermisse 
gray_2_b_out und bcd_2_b_out in der Sensitivity-List vom Prozess 
BCD_OR_GRAY.

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


Lesenswert?

Alexander F. schrieb:
> Für deinen Fehler habe ich jetzt nichts spezielles, aber ich
> vermisse gray_2_b_out und bcd_2_b_out in der Sensitivity-List vom
> Prozess BCD_OR_GRAY.
Und ich vermisse low_bcd und high_bcd (die übrigens völlig 
unnötigerweise im Prozess sind, die wären besser concurrent 
aufgehoben)...

Oder noch besser die sechs Zeilen hier:
1
  low_bcd(11 downto 0) <= l0;
2
  low_bcd(23 downto 12) <= l1;
3
  high_bcd(11 downto 0) <= h0;
4
  high_bcd(23 downto 12) <= h1;
5
6
7
  bcd_2_b_out(23 downto 0) <= low_bcd(23 downto 0);
8
  bcd_2_b_out(47 downto 24) <= high_bcd(23 downto 0);
Durch diese ersetzen:
1
  bcd_2_b_out <= h1 & h0 & l1 & l0;
Stichwort: Concatenation

Aber dein eigentliches Problem dürfte von den arithmetischen Operationen 
(Addition, Multiplikation) kommen, denn das Ergebnis der Rechnungen kann 
ein zusätzliches Übertragsbit ergeben, das dann abgeschnitten wird.

Übrigens glaube ich noch nicht, dass die BCD nach Binär Wandlung 
funktioniert. Es sei denn, du hast es im Vektor GRAY_OR_BCD_IN mit 4 
dreistelligen zusammengefügten BCD-Zahlen zu tun...

: Bearbeitet durch Moderator
von berndl (Gast)


Lesenswert?

was mir noch so aufgefallen ist:
* Du arbeitest z.T. mit nicht initialisierten Signalen und Variablen
* Verwendung von Variablen in nicht getakteten Prozessen: Du bringst da 
sequentielle Abhaengigkeiten (noch mehr als ohnehin im process) rein die 
dich bei komplexeren Sachen einholen werden. Warum nicht 'concurrent' 
und evtl. 'generate' loops?

von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> Übrigens glaube ich noch nicht, dass die BCD nach Binär Wandlung
> funktioniert. Es sei denn, du hast es im Vektor GRAY_OR_BCD_IN mit 4
> dreistelligen zusammengefügten BCD-Zahlen zu tun...

Hm.. im Vektor GRAY_OR_BCD_IN sind 12 BCD Zahlen enthalten:


GRAY_OR_BCD_IN[47..44]: hoechstwertigste BCD Zahl
GRAY_OR_BCD_IN[43..40]
GRAY_OR_BCD_IN[39..36]
.
.
.
GRAY_OR_BCD_IN[3..0]: niederwertigste BCD Zahl


Lothar Miller schrieb:
> Aber dein eigentliches Problem dürfte von den arithmetischen Operationen
> (Addition, Multiplikation) kommen, denn das Ergebnis der Rechnungen kann
> ein zusätzliches Übertragsbit ergeben, das dann abgeschnitten wird.

Glaube ich auch, gibt es da eine geschicktere Methode?

Gruß

von Schlumpf (Gast)


Lesenswert?

die Variablen lO,l1,... müssen doch nur 10 Bit breit sein, da der 
zugewiesene Wert nur maximal 999 werden kann, oder sehe ich das falsch?

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


Lesenswert?

MemY schrieb:
> Hm.. im Vektor GRAY_OR_BCD_IN sind 12 BCD Zahlen enthalten:
Womit dann 1 Wert von 0..999999999999 darstellbar ist, oder womit 4 
unabhängige Werte von 0..999 dargestellt werden?

von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> Womit dann 1 Wert von 0..999999999999 darstellbar ist

Ja, im Prinzip ein Wert 1 BCD Wert aus dem Wertebereich von 
0..FFFFFFFFFFFF

von MemY (Gast)


Lesenswert?

Sorry! Natürlich 1 BCD Wert aus dem Wertebereich von 0..999999999999.

von Lattice User (Gast)


Lesenswert?

MemY schrieb:
> Sorry! Natürlich 1 BCD Wert aus dem Wertebereich von 0..999999999999.

Dafür braucht es dann 37 Bit Ausgabe.
Der einfache parallele Ansatz wird zum Resourcengrab.

Ausserdem programmiere das erst mal zu Fuss (d.h. ohne zuhilfenahme von 
Libraryfunktionen) in C. Aber nein, man kann das C Programm dann nicht 
einfach nach VHDL übersetzen, aber ohne zu verstehen wie man die Aufgabe 
in Teilaufgaben zerlegt hast du in VHDL keinen Chance.

Übrigens für GRAY funktioniert das ohnehin nicht. GRAY_OR_BCD ist also 
falsch.

Wo kommt die Eingabe her, und wie schnell muss es sein?

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


Lesenswert?

MemY schrieb:
> Sorry! Natürlich 1 BCD Wert aus dem Wertebereich von 0..999999999999.
Deshalb kannst du eben nicht einfach 4 mal 3 Zehnerstellen nach binär 
wandeln und die 4 Ergebnisse einfach binär aneinander ketten. Probiere 
das einfach mal mit der BCD Zahl 0000001000 aus (= dezimal 1000). Dein 
Ergebnis ist Hex 000000001000, das richtige wäre Hex 0000000003E8...

: Bearbeitet durch Moderator
von MemY (Gast)


Lesenswert?

Lattice User schrieb:
> Wo kommt die Eingabe her, und wie schnell muss es sein?

Die BCD Daten kommen von einem Sensor. Fuer die Auswertung habe ich 
schon ein paar Takte zeit. Allerdings auch nicht all zu viele ;-)

von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> Dein
> Ergebnis ist Hex 000000001000, das richtige wäre Hex 0000000003E8...

Mit diesem Ansatz ist zumindest in der Theorie die Umwandlung BCD -> 
Binaer korrekt.
1
BCD2Binary: process (GRAY_OR_BCD_IN)
2
variable zwergeb : unsigned(47 downto 0) := (others => '0');
3
begin
4
  zwergeb := unsigned(GRAY_OR_BCD_IN(3 downto 0))*1;  
5
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(7 downto 4))*10;  
6
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(11 downto 8))*100;
7
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(15 downto 12))*1000;
8
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(19 downto 16))*10000;
9
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(23 downto 20))*100000;
10
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(27 downto 24))*1000000;
11
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(31 downto 28))*10000000;
12
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(35 downto 32))*100000000;
13
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(39 downto 36))*1000000000; -- 1000000000: Max. moegl. Wert
14
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(43 downto 40))*10000000000;
15
  zwergeb := zwergeb + unsigned(GRAY_OR_BCD_IN(47 downto 44))*100000000000;
16
  bcd_2_b_out <= zwergeb;
17
end process;

Jedoch sind die letzten beiden Multiplikationen, aufgrund des 
Wertebereichs der Integer, nicht zulaessig. Fehlermeldung:
1
GRAY_OR_BCD_2_BINARY.vhd(62): near "10000000000": (vcom-119) Integer value exceeds INTEGER'high.
2
GRAY_OR_BCD_2_BINARY.vhd(63): near "100000000000": (vcom-119) Integer value exceeds INTEGER'high.

Kann man dies umgehen? Oder muss ein komplett anderer Ansatz gewaehlt 
warden?

von MemY (Gast)


Lesenswert?

Hat keiner eine Idee?

von Hagen R. (hagen)


Lesenswert?

48Bit BCD in 2x24Bit BCD splitten, mit kleineren Konstanten 2x24Bit BCD 
umrechnen in binär, beide Binärwerte am Ende zusammenbauen, dabei den 
einen Wert um X Bits linksshiften. Ist Trivialwissen aus der 
Grundschule.

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


Lesenswert?

MemY schrieb:
> Jedoch sind die letzten beiden Multiplikationen, aufgrund des
> Wertebereichs der Integer, nicht zulaessig.
> Kann man dies umgehen?
Rechne mit unsigned Vektoren. Die kannst du beliebig lang machen...

> Oder muss ein komplett anderer Ansatz gewaehlt warden?
Das schon eher, denn dir wird 1. mit diesen Mosntermultiplizierern das 
FPGA zu klein und 2. das Design insgesamt zu langsam werden...

MemY schrieb:
> Fuer die Auswertung habe ich schon ein paar Takte zeit. Allerdings auch
> nicht all zu viele ;-)
Wenn du 12 Takte Zeit hast, dann könntest du einfach die 12 BCD-Stellen 
nacheinander über 1 Multiplizierer jagen und aufsummieren...

Pseudocode (mit links = BCD12, rechts = BCD0)
1
Sum = BCD(12);
2
Sum *=10;
3
Sum += BCD(11);
4
Sum *=10;
5
Sum += BCD(10);
6
Sum *=10;
7
Sum += BCD(9);
8
:
9
:
10
:
11
Sum *=10;
12
Sum += BCD(0);

Und jetzt kommt der Trick: das Ganze nicht einfach so hintereinander 
schreiben, sondern einen Takt einführen, der dann den Index 
weiterschaltet:
1
Warte_auf_Takt
2
wenn index =12 dann 
3
                summe = bcd(index);
4
                wenn start dann index = 11;
5
                
6
wenn index >0 dann 
7
                summe *=10; 
8
                summe += BCD(index);
9
                index --;
10
11
wenn index =0 dann 
12
                summe += BCD(index);
13
                index = 12;

: Bearbeitet durch Moderator
von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> Wenn du 12 Takte Zeit hast, dann könntest du einfach die 12 BCD-Stellen
> nacheinander über 1 Multiplizierer jagen und aufsummieren...

Ja, 12 Takte haette ich auf jeden Fall zeit! Ich werde mir dein 
Pseudocode anschauen - Danke!

von Schlumpf (Gast)


Lesenswert?

Hagen Re schrieb:
> Ist Trivialwissen aus der
> Grundschule.

Ist das so? Mir erschließt sich dein Vorgehen gerade nicht.

verkürztes Beispiel mit 16 Bit BCD:
BCD: 2073
Zerlegt:
BCD 20 = Hex 14 = Binär 0001 0100
BCD 73 = Hex 49 = Binär 0100 1001

Und wie baust du jetzt die beiden Zahlen zusammen und shiftest, dass das 
korrekte Ergebnis Hex 819 oder Binär 0000 1000 0001 10001 rauskommt?

von P. K. (pek)


Lesenswert?

> Und wie baust du jetzt die beiden Zahlen zusammen und shiftest, dass das
> korrekte Ergebnis Hex 819 oder Binär 0000 1000 0001 1001 rauskommt?

Come on, so schwierig ist es nun auch wieder nicht:

X = 3 *    1 +
    7 *   10 +
    0 *  100 +
    2 * 1000

  = 0x0819

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


Lesenswert?

P. K. schrieb:
>> Und wie baust du jetzt die beiden Zahlen zusammen und shiftest, dass das
>> korrekte Ergebnis Hex 819 oder Binär 0000 1000 0001 1001 rauskommt?
> Come on, so schwierig ist es nun auch wieder nicht:
> X = 3 *    1 +    7 *   10 +   0 *  100 +    2 * 1000  = 0x0819
Das ist mein Verfahren. Aber: eine Addition ist kein Schieben. Mir 
ist das mit dem Schieben auch nicht klar...  ;-)

MemY schrieb:
> Lothar Miller schrieb:
>> Wenn du 12 Takte Zeit hast, dann könntest du einfach die 12 BCD-Stellen
>> nacheinander über 1 Multiplizierer jagen und aufsummieren...
> Ja, 12 Takte haette ich auf jeden Fall zeit! Ich werde mir dein
> Pseudocode anschauen - Danke!
Wenn du deinen Code dann fertig hast, kannst du ja mal mit meinem Code 
vergleichen:
http://www.lothar-miller.de/s9y/archives/89-BCD-nach-Binaer-wandeln.html

von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> http://www.lothar-miller.de/s9y/archives/89-BCD-na...

Dein Code ist natuerlich sehr elegant geloest! Habe nun den „BCD nach 
Binaer Wandler“ für meine Applikation implementiert und anhand deines 
Codes optimiert. Die Simulation bringt korrekte Ergebnisse!

Vielen Dank an dich Lothar, aber auch an die anderen!

Gruß MemY

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


Lesenswert?

MemY schrieb:
> Dein Code ist natuerlich sehr elegant geloest!
Es gibt nichts, was nicht noch besser ginge... ;-)
Die Multiplikation in dieser Zeile:
1
         tmp <= resize(tmp*10 + unsigned(BCD(idx*4-1 downto idx*4-4)),tmp'length);
Kann durch eine zusätzliche Addition ersetzt werden:
1
         tmp <= resize(tmp*8 + tmp*2 + unsigned(BCD(idx*4-1 downto idx*4-4)),tmp'length);
Der Synthesizer erkennt, dass tmp*8 und tmp*2 keine wirklichen 
Multiplikationen sind, und kann diese Operationen durch ein simples 
Umverdrahten erledigen. Kurz: es ist kein Multiplizierer nötig, das 
Design kann schneller getaktet werden...

: Bearbeitet durch Moderator
von MemY (Gast)


Lesenswert?

Lothar Miller schrieb:
> Kurz: es ist kein Multiplizierer nötig, das
> Design kann schneller getaktet werden...

Das ist natuerlich nochmal etwas besser ;-)

von Hagen R. (hagen)


Lesenswert?

Lothar Miller schrieb:
> MemY schrieb:
>> Dein Code ist natuerlich sehr elegant geloest!
> Es gibt nichts, was nicht noch besser ginge... ;-)
> Die Multiplikation in dieser Zeile:
>
1
>          tmp <= resize(tmp*10 + unsigned(BCD(idx*4-1 downto 
2
> idx*4-4)),tmp'length);
3
>
> Kann durch eine zusätzliche Addition ersetzt werden:
>
1
>          tmp <= resize(tmp*8 + tmp*2 + unsigned(BCD(idx*4-1 downto 
2
> idx*4-4)),tmp'length);
3
>
> Der Synthesizer erkennt, dass tmp*8 und tmp*2 keine wirklichen
> Multiplikationen sind, und kann diese Operationen durch ein simples
> Umverdrahten erledigen. Kurz: es ist kein Multiplizierer nötig, das
> Design kann schneller getaktet werden...

simples Umverdrahten -> übertragen in mathe = multplikation zur Potenz 
mit Basis 2 -> shiften.

Du kannst also den 48Bit BCD in zb. 2*24Bit zerlegen, dann so rechnen 
wie oben und beide Zwischenresultate wieder in ein Resulat 
zusammenbauen. Dabei entstehen Additionen und Multiplikationen zur basis 
2, was man im FPGA durch Verdrahtung lössen kann und deine Konstanten 
werden in den Teilberechnungen kleiner, PEK hat es oben schon erkannt.

von Schlumpf (Gast)


Lesenswert?

P. K. schrieb:
> Come on, so schwierig ist es nun auch wieder nicht:
>
> X = 3 *    1 +
>     7 *   10 +
>     0 *  100 +
>     2 * 1000

Aha... dass das so funktioniert, weiss hier glaub jeder. Aber damit hast 
du ja nicht wirklich neue Erkenntnisse herbeigebracht.

Lothar Miller schrieb:
> Das ist mein Verfahren. Aber: eine Addition ist kein Schieben. Mir
> ist das mit dem Schieben auch nicht klar...  ;-)

Mir ist auch nicht klar, was er damit gemeint hat:

Hagen Re schrieb:
> 48Bit BCD in 2x24Bit BCD splitten, mit kleineren Konstanten 2x24Bit BCD
> umrechnen in binär, beide Binärwerte am Ende zusammenbauen, dabei den
> einen Wert um X Bits linksshiften. Ist Trivialwissen aus der
> Grundschule.

von P. K. (pek)


Lesenswert?

Schlumpf schrieb:
>> Come on, so schwierig ist es nun auch wieder nicht:
>>
>> X = 3 *    1 +
>>     7 *   10 +
>>     0 *  100 +
>>     2 * 1000
>
> Aha... dass das so funktioniert, weiss hier glaub jeder. Aber damit hast
> du ja nicht wirklich neue Erkenntnisse herbeigebracht.

Nein, natürlich nicht. Nur hatte weiter oben jemand Mühe mit dem Wissen 
aus der Grundschule:

Schlumpf schrieb:
> Hagen Re schrieb:
>> Ist Trivialwissen aus der
>> Grundschule.
>
> Ist das so? Mir erschließt sich dein Vorgehen gerade nicht.

Und wenn man dieses Wissen geeignet darstellt erschliesst sich manchem 
das vorgehen dann doch, z.B. dass die Multiplikation mit der Konstanten 
10 nicht wirklich eine Multiplikation ist, sondern die noch weiter oben 
erwähnte Shift-Geschichte.

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.