Wie kann man in VHDL eine mehrstellige Zahl in einzelne Ziffern aufteilen?

Ich habe die Methode für die Sprache c gefunden . Aber ich weiß nicht, wie ich dies in VHDL ausführen soll. Lassen Sie eine Festkommazahl (12 bis -19) wie 3456.478396 Ich muss diese Zahl vollständig in separate Zahlen 3456.478396 aufteilen --> 3, 4, 5, 6, (Punkt) , 4, 7, 8, 3, 9, 6. .. in 11 Integer-Variablen. Wie führt man das in VHDL durch?

signal example : sfixed(4 downto -4);
--'example' contains 9.75 then it is storage as "01001.1100".
--simply example ="10011100".
--10011100 --> integer 156

Wie bekomme ich die ursprüngliche 9,75 -Nummer von 156 zurück , um sie in einzelne Ziffern zu trennen?

ICH BENUTZTE,

library ieee;
library ieee_proposed;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee_proposed.float_pkg.ALL;
use ieee_proposed.fixed_pkg.ALL;
use ieee_proposed.fixed_float_types.ALL;
Wie wird die ursprüngliche Zahl dargestellt? Wie soll es dargestellt werden, wenn es einmal "kaputt" ist?
hängt davon ab, wie die Nummer gehalten wird. Wenn in BCD, dann ist es einfach. Wenn es binär ist, müssen Sie zuerst in Dezimalzahlen umwandeln.
@Eugene Sh in der Frage habe ich erwähnt, dass ich diese Nummer vollständig in separate Nummern 3456,478396 aufteilen muss --> 3, 4, 5, 6, (Punkt) , 4, 7, 8, 3, 9, 6 ... in 11 Integer-Variablen.
Siehe hier: stackoverflow.com/questions/23871792/… Sobald Ihre binäre Ganzzahl in BCD konvertiert ist, ist jede Ziffer separat ...
@Mishyoshi Das löst nicht die rechte Seite des Problems. Die Dezimalwerte.
@Harry Svensson Entschuldigung, ich habe das gerade wiederhergestellt, ich dachte, das ist eine Dummy-Frage.
Ich denke, es ist eine gute Frage, obwohl ich mich nicht nach Duplikaten umgesehen habe.

Antworten (1)

Hier ist etwas Pseudocode.

Nehmen wir zuerst die links von der Dezimalstelle, die maximale Zahl ist 15 10 => 2 Dezimalstellen.

signal ex : sfixed(4 downto -4);

temp <= ex(4 downto 0);
L_0 <= temp mod 10;
temp <= temp/10;
L_1 <= temp mod 10;

Beispiel:
ex= 12 10 = 1100 2

temp <= 12
L_0 <= 12 mod 10 = 2
temp <= 12/10    = 1
L_1 <= 1 mod 10  = 1

Und dann die rechts, kleinste Zahl => 0,0625 => 4 Dezimalstellen. Gleiche Methode wie zuvor, nur mit multiplizieren 625 10 bevor du anfängst. Weil 0001 2 in binär übersetzt zu .0625 10 in dezimal. So sollte die Bitbreite von temp sein C e ich l ( l Ö G 2 ( 625 × 15 ) ) = 14 Bit weil 15 10 Ist 1111 2 was dein höchster Wert ist.

signal ex : sfixed(4 downto -4);

temp <= ex(0 downto -4);
temp <= temp*625

R_3 <= temp mod 10;
temp <= temp/10;
R_2 <= temp mod 10;
temp <= temp/10;
R_1 <= temp mod 10;
temp <= temp/10;
R_0 <= temp mod 10;

Beispiel:
ex= 0,1875 10 = 0011 2

temp <= 3 = 0011
temp <= 3*625 = 11101010011        = 1875

R_3 <= 1875 mod 10                 = 5
temp <= 1875/10                    = 187
R_2 <= 187 mod 10                  = 7
temp <= 187/10                     = 18
R_1 <= 18 mod 10                   = 8
temp <= 18/10                      = 1
R_0 <= 1 mod 10                    = 1

Und es sollte so angezeigt werden:

L 1 L 0 . R 0 R 1 R 2 R 3

Alle konstanten Divisionen durch 10 können durch eine Multiplikation mit ersetzt werden 1 10 . Es ist also nicht zu ineffizient zu implementieren. Ich bin mir ziemlich sicher, dass der Modulo-Operator in der Standardbibliothek enthalten ist.

Wenn Sie 6 Bits für die rechte Seite des Dezimalpunkts verwenden. Dann sollte die Bitbreite für temp sein C e ich l ( l Ö G 2 ( 63 × 15625 ) ) = 20 Bit . Dies ist wahrscheinlich nicht der effizienteste Weg, es ist ein Weg, den ich mir gerade selbst ausgedacht habe. Es sollte ohne größere Probleme funktionieren.

Da dies auf einem FPGA erfolgt, können Sie die Multiplikation parallelisieren, für R3, R2, R1 und R0 ihre Temperatur mit 1 multiplizieren, 1 10 , 1 100 Und 1 1000 So erhalten Sie die Werte sofort statt seriell. Und dann benutze den Mod 10 auf ihnen.


BEARBEITEN

Mishyoshi gab mir eine Idee, wie dies auf andere Weise gelöst werden könnte. L 0 Und L 1 werden wie zuvor gelöst, aber die R 0..3 kann auf andere, effizientere Weise erfolgen.

signal ex : sfixed(4 downto -4);

signal temp : sfixed(4 downto -4); 
//We need 4 to the left of the decimal point because then we can capture
//all the single digits

temp <= "0000" & ex(0 downto -4);
temp <= temp*10;

R_0 <= temp(3 downto 0); //Copy the 4 MSB bits 
temp <= "0000" & temp(-1 downto -4); //Delete the 4 MSB bits
temp <= temp*10;
R_1 <= temp(3 downto 0);
temp <= "0000" & temp(-1 downto -4);
temp <= temp*10;
R_2 <= temp(3 downto 0);
temp <= "0000" & temp(-1 downto -4);
temp <= temp*10;
R_3 <= temp(3 downto 0);

Beispiel:
ex= 0,1875 10 = 0011 2

signal temp : sfixed(4 downto -4);

temp <= "0000" & "0011"                     = 0000.0011 = 3
temp <= 3*10                           = 30 = 0001.1110 
R_0 <= "0001.1110"(3 downto 0)              = 0001 = 1
temp <= "0000" & temp(-1 downto -4)         = 0000.1110
temp <= 14*10                         = 140 = 1000.1100
R_1 <= "1000.1100"(3 downto 0)              = 1000 = 8
temp <= "0000" & "1100"                     = 0000.1100
temp <= 12*10                         = 120 = 0111.1000
R_2 <= "0111.1000"(3 downto 0)              = 0111 = 7
temp <= "0000" & "1000"                     = 0000.1000
temp <= 8*10                           = 80 = 0101.0000
R_3 <= "0101.0000"(3 downto 0)              = 0101 = 5

Wie Sie sehen können, dreht sich alles darum, die Bits an die "Einer"-Stelle zu bringen, die 4 Bits links vom Dezimalkomma.

Dafür werden viel weniger Bits benötigt. In dieser anderen Lösung können Sie sie, wie Mishyoshi sagte, in eine Pipeline stecken.

Ich verstehe nicht, was ist, und wie kommt diese kleinste Zahl => 0,0625 => 4 Dezimalstellen . die Nummer 625
Wenn Sie 1/16 in den Rechner eingeben, zeigt er 0,0625, wenn Sie sich nur die Nicht-Null-Zahlen ansehen, steht dort 625. Das bedeutet, dass eine 0000,0001 in Binärform 0,0625 in Dezimalzahl ist. Das "Gewicht" der 1 ist also 1/16. Aber da wir auf der "rechten Seite" sind, können wir den Dezimalpunkt einfach ignorieren und ihn als 0625 behandeln. Mit anderen Worten, multiplizieren Sie einfach mit 625. Da wir nur in BCD konvertieren, tun wir nichts schick.
Wenn es 6 Bit wären, würden Sie mit 15625 multiplizieren, da 0000,000001 in Binär 0,015625 in Dezimal ist. Entfernen Sie die Dezimalstelle und Sie erhalten 000001 ist 015625. Multiplizieren Sie also die 1 mit 015625 und fangen Sie dann an, die Ziffern herauszuschneiden.
Ich könnte mich irren, aber für einen 4-Bit-Festkomma-Bruchwert können Sie eine binäre Multiplikation von 10000 durchführen, da er einen Wert von 0,0625 hat (4 Ziffern => 10 ^ 4). Konvertieren Sie das dann mit dem von mir bereitgestellten Link in BCD. Der Wert wird 10000-mal zu groß sein, berücksichtigen Sie also die Position des Dezimalpunkts 4 links. Es gäbe nur einen einzigen Multiplizierer mit leicht verfügbarem Multiplizierer und eine Reihe von Addierern, die in einer Pipeline angeordnet werden könnten.
Hmm, du bist auf etwas @Mishyoshi. Sie müssen etwas mehr tun, als nur mit multiplizieren 10 4 obwohl.
@Harry Svensson in der obigen Berechnungstemp ist ein Vektor. Muss es nicht in eine Ganzzahl konvertiert werden, bevor Sie die Schritte mod 10 und ** / 10 ** ausführen ? Ich verwende das Fixpunktpaket von David Bishop .
@Oppo Ich sagte, dass es Pseudocode ist, was bedeutet, dass ich 90% der gesamten Semantik ignoriere und nur Code wie einen Algorithmus schreibe. Der Grund dafür ist, dass ich nicht tief in die VHDL-Sprache eintauchen möchte, weil A , ich habe keine Zeit, den Code zu überprüfen, B , ich habe Quartus nicht installiert, C , dieser Algorithmus sollte ausreichen bringen Sie in die richtige Richtung.
@Harry Svensson Ich habe die genaue Methode oben für eine feste Zahl (19 bis -19) befolgt, aber ich bekomme 3 74334.738277 für den Wert 2 74334.738295 Bruchteil ist in Ordnung, der linke Wert hat sich geändert .
Ich weiß nicht, was ich dir sagen soll, ohne Code oder Wissen, wie du es gemacht hast, gibt es nichts, was ich dir sagen kann. Ich weiß nur, dass es funktionieren sollte, wenn etwas mit dem letzten Bit nicht stimmt, dann haben Sie bei jeder Zahl etwas richtig gemacht, außer bei der letzten. sfixed steht für signierte Festnetznummer oder? Vielleicht passiert beim letzten Bit etwas Buggy, weil es ein Zeichenbit ist.
@Harry Svensson ja, das letzte Bit ist 1, wenn es eine negative Zahl ist, und es ist 0, wenn es eine positive Zahl für sfixed ist (david Bishop's lib) -9,75 = "10110010" und 9,75 = "01001110"
Nun, es gibt die Antwort darauf, warum es nicht funktioniert.
@Harry Svensson Ich verstehe nicht, was getan werden muss?
@oppo Wie erwartest du, die Zahl 374334 mit 18 Bit zu machen? - Du nicht . das 19. Bit ist das Vorzeichenbit. Was auch immer Sie tun, stellen Sie sich vor, Sie wären 1 Bit weniger und kümmern Sie sich besonders um das 19. Bit. Wie ... wenn es eine 1 ist, dann gib ein "-" aus, wenn es eine 0 ist, gib kein "-" aus.