Forum: FPGA, VHDL & Co. VHDL - Division von Integern zu Float


von Manah (Gast)


Lesenswert?

Hallo alle zusammen,

ich habe folgende Frage: Ich habe als Input 2 Integer und als Output 
will ich ein Float (2 stellen nach dem Koma).

Ich habe mich schon in Internet Erkundigt und hier auch mehrere Foren 
Einträge mir angeschaut.
1
library ieee;
2
use ieee.numeric_std.all;
3
use ieee.float_pkg.all;
4
5
entity integer_by_float_division is
6
    port (
7
        numerator: in signed(15 downto 0);
8
        denominator: in signed(15 downto 0);
9
        result: out float(6 downto -9)
10
   );
11
end;
12
13
architecture rtl of integer_by_float_division is
14
    subtype float16 is float(6 downto -9);
15
    signal numerator_float: float16;
16
    signal denominator_float: float16;
17
begin
18
    numerator_float <= to_float(numerator, numerator_float);
19
    denominator_float <= to_float(denominator, denominator_float);
20
    result <= numerator_float / denominator_float;
21
end;


Ist dies die Einzige Möglichkeit? Also muss man die Zahlen(Integer) 
vorher zu Signed Convertieren oder gibt es eine Möglichkeit direkt 
Integer zu Teilen und da denn Output als Float zuzuweisen?

Convertierung:

signal input_3  : integer;
signal output_3 : signed(3 downto 0);

output_3 <= to_signed(input_3, output_3'length);

Quelle:
https://stackoverflow.com/questions/19161454/division-in-vhdl-int-float?rq=1


Danke!

von VHDL-Polizei (Gast)


Lesenswert?

Ich würde sagen, dass du beides machen kannst:

Fall 1: alles in float convertieren, rechnen lassen float rausbekommen, 
benutzen.

Vorteil: Höchste Genauigkeit bei definierter  Bitbreite
Nachteil: Schweinegross und Langsam

Fall 2: Alles in INT belassen, auf benötigte Genauigkeit aufbohren, 
rechnen lassen, INT erhalten, in float konvertieren

Vorteil: Minimaler Platz- und Rechenbedarf
Nachteil: Berechnungsabhängige Breite der Vektoren und Anforderung an 
Gehirnschmalz

Praktisch rechnet man in FPGAs IMMER in INT, es sei denn man kriegt 
alles in float und muss es auch wieder so abliefern, z.B. an eine CPU.

P.S. Division in Float ist in VHDL wirklich saulangsam und umständlich. 
Binäre DIV nach schriftlichem Dividieren ist hingegen hoch effektiv und 
klein.

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


Lesenswert?

VHDL-Polizei schrieb im Beitrag #6968049:
> P.S. Division in Float ist in VHDL wirklich saulangsam und umständlich.
Wenns nur für den Simulator ist...

Manah schrieb:
> oder gibt es eine Möglichkeit direkt Integer zu Teilen
> und da denn Output als Float zuzuweisen?
Kannst du machen, nach der Integer-Division sind dann aber natürlich die 
Nachkommastellen weg.

> Ich habe als Input 2 Integer und als Output will ich ein Float
Soll das auf Hardware laufen? für eine simple Anzeige? Dann vergiss 
float ganz schnell.
Denn eigentlich willst du nicht in float rechnen, sondern du willst 
lediglich
> (2 stellen nach dem Koma).
Also mach es so: rechne einfach alles in Integer und "um den Faktor 100 
zu groß" und dann denkst du dir zwischen die 10er und die 100er-Stelle 
ein Komma.
Deiser Ansatz nennt sich übrigens "Festkommaarithmetik".

BTW: warum beschreibst du nicht einfach die eigentliche Aufgabe? Mit 
Angaben zu Toolchain und Hardwareplattform undsoweiterundsofort...

: Bearbeitet durch Moderator
von Manah (Gast)


Lesenswert?

Danke für die ganzen Antworten!

ich will eigentlich nur eine Konstante 30/eine sich je Takt Zyklus 
ändernde zahl teilen (die ist in integer). Aber das Ergebnis ist 
höchstwahrscheinlich ein Float.

Ich brauche eine Genauigkeit von 2 nach Komma stellen.

von VHDL-Polizei (Gast)


Lesenswert?

Lothar M. schrieb:
> Kannst du machen, nach der Integer-Division sind dann aber natürlich die
> Nachkommastellen weg.

Die Nachkommastellen sind natürlich in INT so zu bemessen, dass sie 
ausreichend genau sind. Also für A = 16 Bit / B = 16 Bit -> 0...1 , wenn 
B auch kleiner sein kann, als 1, dann hat das Ergebnis z.B. 16 Vorkomma 
und 16-Nachkommastellen ->

Y = ( K * A ) / B mit K =16 -> (15 downto 0).(15 downto 0).

Das Ergebnis ist dann auf 1/32768 genau und muss auf mindestens 32 Bit 
skaliert werden, um es an float zu übergeben. Kann aber auch sein, dass 
die Ergbnisse so aussehen, dass der Wert immer zwischen 0 und 1 liegt, 
gfs reichen dann 24 Bit Nachkommastellen und man hat es direkt in float.

von Manah (Gast)


Lesenswert?

ich will das Ergebnis später in einer 7-Seg anzeige darstellen, ein 
Array eignet sich wunderbar dafür, aber gibt es eine Möglichkeit, wenn 
das Ergebnis als integer vorliegt zb 12545 integer in ein array zu 
packen (1,2,5,4,5)?

Wenn das möglich ist würde ich das machen:

Also mach es so: rechne einfach alles in Integer und "um den Faktor 100
zu groß" und dann denkst du dir zwischen die 10er und die 100er-Stelle
ein Komma.
Deiser Ansatz nennt sich übrigens "Festkommaarithmetik".

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


Lesenswert?

Manah schrieb:
> Aber das Ergebnis ist höchstwahrscheinlich ein Float.
Nein. Die Lösung lässt sich in 99% der Fälle ohne float finden.
Du willst auf realer Hardware (z.B. ein FPGA) solche einfache 
Grundrechnugen sicher nicht in float lösen. Auch wenn das beim Arduino 
(oder sonst einem µC) in einer Hochsprache "so nebenher" geht: in 
Hardware gegossen ist ein float ein richtig großer und schwerer Koffer. 
Den packt man nicht für 2 simple Nachkommastellen raus.

> 30/x
> Ich brauche eine Genauigkeit von 2 nach Komma stellen.
Wie gesagt, dann rechne einfach: 3000/x und dann denk dir zwischen die 
3. und 2. letzte Stelle ein Komma.
Und nochmal das Stichwort: Festkommaarithmetik

So sieht z.B. eine Division in VHDL aus:
http://www.lothar-miller.de/s9y/categories/24-Rechnen

Manah schrieb:
> aber gibt es eine Möglichkeit, wenn das Ergebnis als integer vorliegt
>  zb 12545 integer in ein array zu packen (1,2,5,4,5)?
Du kannst die Integerzahl (also einen binären Vektor) in eine BCD-Zahl 
wandeln und die einzelnen Stellen dann darstellen.
http://www.lothar-miller.de/s9y/categories/44-BCD-Umwandlung

BTW: Du denkst in Software. Das geht schief.

: Bearbeitet durch Moderator
von Manah (Gast)


Lesenswert?

Ich führe eine bestimmte Rechnung aus, dass Funktioniert auch alles.
Das was ich benötige um fertig zu werden ist folgendes:

30/Integer* => erg

erg will ich in ein 7-Segment Display auf ein VHDL Board(DE10-Lite) 
packen, da will ich das Ergebnis als Array, da die 7-Seg Anzeige keinen 
Multiplexer hat und ich jedes einzelne Segment ansprechen muss.



*Integer,denn mir mein vorheriger Code ausgibt.

von Manah (Gast)


Lesenswert?

Lothar M. schrieb:
> BTW: Du denkst in Software. Das geht schief.

hahaha ja da hast du recht, ich schreibe normalerweise in c/c++ und 
python :D

von Manah (Gast)


Lesenswert?

Lothar M. schrieb:
> http://www.lothar-miller.de/s9y/categories/44-BCD-Umwandlung

danke für denn link, ich schaue es mir mal genau an, ich werde dann 
folgendes machen:

1) (Die Berechnung(Division) in Integer)*100

2) Das Ergebnis der Division in STD_Logic_Vector Convertieren

3) dann wie in oben genannten Link die STD_Logic_Vector in hex -> BCD 
->* 7-Seg


* Beim übergeben, denn Blinker der DP immer auf 0

aber mein Ausgabe Vector muss 42 downto 0 lang sein, da kein 
multiplexer.

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


Lesenswert?

Manah schrieb:
> 30/Integer* => erg
>
> erg will ich in ein 7-Segment Display auf ein VHDL Board(DE10-Lite)
> packen, da will ich das Ergebnis als Array, da die 7-Seg Anzeige keinen
> Multiplexer hat und ich jedes einzelne Segment ansprechen muss.
Also rechne einfach 3000/Integer* => erg, stelle das erg auf der Anzeige 
dar und dann nimm einen Lötkolben und löte den Punkt der 
7-Segmentanzeige zwischen der 3. und 2. Stelle von rechts so, dass er 
leuchtet.

Also Beispiel zum Mitrechnen:

30/14 = 2.14

Rechne

3000/14 = 214 --> mach den Punkt rein: 2.14

Fertig.

Manah schrieb:
> aber mein Ausgabe Vector muss 42 downto 0 lang sein
Seltsamer Vektor mit 43 Bits Breite... Naja, seis drum. Vermutlich ist 
der Vektor doch nur (41 downto 0).

Das musst du dann halt passend hinbiegen. Denn von der BCD-Zahl mit 4 
Bit pro Stelle musst du ja auf deine 7 (oder 8) Bits pro Stelle kommen. 
Und eben dann den Punkt an der richtigen Stelle anschalten.

: Bearbeitet durch Moderator
von Manah (Gast)


Lesenswert?

ich habe 6 7-Segmente a 7 Segmente.

6 * 7 = 42

1 für denn DP, der hat auch sein Eigenes Segment = 43

von Manah (Gast)


Lesenswert?

Meine frage, wie sieht denn der std_vector aus?

Wenn ich ein Integer zu std_vector convertiere, kann ich dann jede 
einzelne Zahl einzeln ansprechen?

std_vector(pos5), also kann man da mit indizes arbeiten?

532 integer -> std_vector => (101,11,10) oder ist das (1000010100)?

von Gustl B. (-gb-)


Angehängte Dateien:

Lesenswert?

Manah schrieb:
> Wenn ich ein Integer zu std_vector convertiere, kann ich dann jede
> einzelne Zahl einzeln ansprechen?

Du verwechselst hier Zahl mit Ziffer oder Stelle in einem 
Stellenwertsystem.

Manah schrieb:
> 532 integer -> std_vector => (101,11,10) oder ist das (1000010100)?

532 im Dezimalsystem wird im Binärsystem zu 1000010100. Und genau wie im 
Dezimalsystem kannst du jede Stelle einzeln ansprechen. Nur hat die Zahl 
im Dezimalsystem eben 3 Stellen, im Binärsystem aber 10 Stellen.

Du kannst also nicht mehr die 5, 3 oder 2 "ansprechen", dafür aber die 
1, die 0, die 1 oder auch nochmal die 0.

Der Weg wäre:
532 zerlegen in seine Stellen 5, 3 und 2 und diese dann einzeln in 7 
Segment Vektoren wandeln.

Wie kann man 532 in seine Stellen zerlegen? Wenn man viele Takte Zeit 
hat geht das mit Zählern. Einer für die Einer, einen für die Zehner und 
einen für die Hunderter, jeweils mit Überlauf zum nächsten Zähler. 
Kostet dich bei 532 eben auch 532 Takte.
Am Ende hat du die einzelnen Stellen/Ziffern der Dezimalzahl als 4 Bit 
Binärwert, denn zum Darstellen der Zahlen 0 ... 9 benötigt man 4 Bits.

Und von den 4 Bit Werten nach 7 Segment ist es eine einfache 
Abbildung/Zuordnung, geht aber auch mit ein paar Logikgattern.

Edit:
Die Lösung mit den Zählern ist fertig und im Anhang. Hier jetzt für 3 
Dezimalstellen. Also Zahlen von 0 ... 999.

: Bearbeitet durch User
von Fitzebutze (Gast)


Lesenswert?

Manah schrieb:
> Lothar M. schrieb:
>> BTW: Du denkst in Software. Das geht schief.
>
> hahaha ja da hast du recht, ich schreibe normalerweise in c/c++ und
> python :D

Warum nimmst du nicht gleich eine passende Python HDL?
MyHDL oder hwt z.B. hat eine vernünftige Fixpoint-Arithmetik, wo man 
nicht umständlich in VHDL von Hand rumkodieren muss. Hinten kommt VHDL 
oder Verilog raus. Float-Konversion sollte man nur dann machen, wenn's 
in ein entsprechendes austauschbares Format soll.

von Gustl B. (-gb-)


Lesenswert?

Fixed ist doch auch in VHDL kein Problem.

von Manah (Gast)


Lesenswert?

Danke dir.

ich habe gerade die Integer Zahl fertig bekommen. Jetzt Konvertiere ich 
die in Dual.

Dann werde ich das Split digit drauf anwenden.

Der letzte schritt, dann aufs Board.

Stimmt das, dass man Variablen meiden sollte?

von Markus F. (mfro)


Lesenswert?

Es gibt keinen Grund, Variablen zu vermeiden, wenn man (vollständig) 
verstanden hat, wozu sie gut (und nicht gut) sind.

Im Gegenteil - man kann Code damit deutlich lesbarer gestalten.

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


Lesenswert?

Manah schrieb:
> Stimmt das, dass man Variablen meiden sollte?
Man sollte sie dann meiden, wenn man sich nicht sicher ist, on man sie 
meiden sollte... 😉

Lies dir mal den Beitrag "Variable vs Signal" durch. 
Wenn du das da drin verstanden hast, dann ist es egal was du nimmst.

Manah schrieb:
> ich habe gerade die Integer Zahl fertig bekommen. Jetzt Konvertiere ich
> die in Dual.
Wie sieht diese "Integerzahl" zb. für den Wert 159 denn aus? Etwa so: 
000101011001?

: Bearbeitet durch Moderator
von Okan M. (okan_m)


Angehängte Dateien:

Lesenswert?

Hi,

es wurde doch kein Integer
1
   v : out unsigned (31 downto 0)


ich habe eine Frage zu split_digits.vhd (1,54 KB) | Codeansicht
Warum brauche ich das?
1
 i_start              : in    std_logic;

Ich würde split digits nutzen aber vorher muss ich unsigned zum 
std_logic_vector(9 downto 0); Konvertieren.

von Gustl (Gast)


Lesenswert?

Okan M. schrieb:
> Ich würde split digits nutzen aber vorher muss ich unsigned zum
> std_logic_vector(9 downto 0); Konvertieren.

Nein, casten. Da ändert sich an den Bits nichts. Mit signed oder 
unsigned wird nur mitgeteilt als was der Vektor interpretiert werden 
soll.

Okan M. schrieb:
> Codeansicht
> Warum brauche ich das?

Du hast den Code gelesen?
Das funktioniert über Zähler, der Zähler muss also je nach 
Implementierung zu einem Zeitpunkt geladen oder Zurückgesetzt werden. 
Dafür ist das Start Signal da. Und auch das Busy ist wichtig denn erst 
wenn das wieder low ist, dann liegt das korrekte Ergebnis am Ausgang an.

von Okan M. (okan_m)


Lesenswert?

danke für die schnelle Rückmeldung.

Ja ich habe denn code gelesen, ich bin nicht so die leuchte.... ich fand 
die stelle sehr kompliziert.

 <= '1' when i_start = '1' or s_counter > 0 else '0';


ich habe noch eine frage...
https://www2.cs.sfu.ca/~ggbaker/reference/std_logic/1164/std_logic_vector.html


heißt das, ich kann die einzelnen bits in einem std_logic_vector 
ansprechen?

x("010")

x(0) = ("0")
x(1) = ("1")
x(2) = ("0")

oder geht das nur mit array?

Ich habe in verschiedenen foren gelsen, dass man dies in ein array 
konvertiren muss mit einem for loop und man erst dann die einzellen bits 
ansprechen kann.

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


Lesenswert?

Okan M. schrieb:
> x(0) = ("0")

> x(1) = ("1")

> x(2) = ("0")
Korrekt ist es so:

x(0) = '0'

x(1) = '1'

x(2) = '0'

Denn Achtung:
"0" ist nicht das selbe wie '0'

: Bearbeitet durch Moderator
von Okan M. (okan_m)


Lesenswert?

vielen dank!!!! Ich bin dank eurer Hilfe sehr weit gekommen.

von Duke Scarring (Gast)


Lesenswert?

Okan M. schrieb:
> ich fand
> die stelle sehr kompliziert.
>
>  <= '1' when i_start = '1' or s_counter > 0 else '0';

Das ist nur eine andere Schreibweise für 'if'.
Außerhalb von Prozessen ist 'if' nicht nutzbar.

Im Prozess würde das so aussehen:
1
process
2
begin
3
    if i_start = '1' or s_counter > 0 then
4
        o_busy <= '1';
5
    else
6
        o_busy <= '0';
7
end process;

Duke

von Okan M. (okan_m)


Angehängte Dateien:

Lesenswert?

Hallo alle,

Ich bin auf Ihren Code gestoßen. Könnten Sie mir eventuell ein paar 
stellen erklären?

Division in VHDL - Lothar Miller (lothar-miller.de)


Warum benötige ich ein Start Signal?

Gestartet wird die Division, nachdem der Dividend und der Divisor 
zugewiesen wurden, mit dem Signal start='1'. Es reicht aus, wenn Start 
für einen Taktzyklus aktiv ist

Also wie müsste der ankommen?

Wenn ich eine Division „will“ oder reicht es auf wenn ich da eine clock 
anschließe?

Die selbe frage gilt für Busy.


Ich benötige eine Division, die ein Integer/Konstante(Integer teilt)

Mein Ansatz, ich habe zum Debuggen 2 Konstante benutzt, aber die geben 
mir in der TB auch ein „UUUUUUU…“ als Ergebnis.
1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
entity Division is
5
    port
6
    (
7
        t      : in INTEGER;
8
                 v                          : out unsigned (19 downto 0);
9
                 v_std                   : out std_logic_vector(19 downto 0)
10
                                                     
11
    );
12
end entity;
13
14
ARCHITECTURE rtl OF Division IS
15
signal v_tmp : unsigned (19 downto 0);
16
17
BEGIN
18
19
Division : PROCESS (t)
20
21
VARIABLE t_tmp : unsigned (19 downto 0);
22
VARIABLE t_100 :INTEGER;
23
VARIABLE Durchmesser: INTEGER;
24
VARIABLE Durchmesser_tmp: unsigned (19 downto 0);
25
26
BEGIN
27
Durchmesser := 2199; -- radius = 3.5cm // (r  pi  2)*100
28
t_100 := t * 100;
29
30
Durchmesser_tmp := to_unsigned(Durchmesser, Durchmesser_tmp'length);
31
--t_tmp := to_unsigned(t_100, t_tmp'length);
32
33
t_tmp := to_unsigned(50, t_tmp'length);
34
Durchmesser_tmp := to_unsigned(100, Durchmesser_tmp'length);
35
36
37
v_tmp <= Durchmesser_tmp / t_tmp; -- v = s/t
38
v <= v_tmp;
39
v_std<= (std_logic_vector (v_tmp));
40
41
42
END PROCESS Division;
43
END rtl ;

Liebe Grüße,

Okan

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


Lesenswert?

Okan M. schrieb:
> Warum benötige ich ein Start Signal?
Sieh dir in der Simulation an, was der Code dort macht: es wird eine 
Zahl binär Bit für Bit geteilt wie man es bei den binären 
Grundrechenarten lernt.

Denn ein simples c<=a/b kann in der Hardware nur dann effizient 
umgesetzt werden, wenn b eine Zweierpotenz ist. Sieh dir das Handbuch 
des Synthesizers an. Dort steht drin was der tatsächlich von VHDL in 
Hardware abbilden kann.

von Markus F. (mfro)


Lesenswert?

Lothar M. schrieb:
> Denn ein simples c<=a/b kann in der Hardware nur dann effizient
> umgesetzt werden, wenn b eine Zweierpotenz ist.

Die Aussage ist zwar richtig, führt den TO (vielleicht) auch zur Lösung, 
aber nicht zum Verständnis.

Das ist wie wenn man behaupten würde "die Division kann vom Grundschüler 
nur dann effizient umgesetzt werden, wenn durch 10 geteilt wird".

Tatsächlich ist die Multiplikation/Division einer Zahl in 
Binärdarstellung mit 2 durch Hinzufügen bzw. Weglassen einer Stelle am 
rechten Ende nur eine Abkürzung, die durch die Wahl der 
Zahlendarstellung ermöglicht wird. Beim Rechnen im Zehnersystem machen 
wir das ja genauso:

150 / 10 = 15 (rechts einfach eine Stelle weglassen)

Entsprechende "Abkürzungen" sind auch bei anderen Zahlensystemen 
möglich:
oktal (Teilen durch 8er-Potenzen):

142 (98) / 10 (8) = 14 (12)

sedezimal (Teilen durch 16er-Potenzen):

FE (254) / 10 (16) = F (15)

Wenn wir ein 1,27381er - Zahlensystem hätten, könnten wir also ganz 
einfach und schnell durch 1,27381 teilen (täten uns aber naturgemäss mit 
anderen Teilern schwer).

Die Vorgehensweise ist elementar für das Verständis von 
Zahlendarstellung und mir unverständlich, warum man anscheinend 
teilweise meint, Grundschülern das schriftliche Dividieren nicht mehr 
beibringen zu müssen, weil es ja Taschenrechner gibt. Wir "alten Säcke" 
haben das intensiv gelernt und benutzt, deswegen ist das für uns 
"einfach logisch".
Das ist nicht selbstverständlich.

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


Lesenswert?

Markus F. schrieb:
> das schriftliche Dividieren
Das ist der eigentliche Trick zum Verstehen meines Codes: man muss 
einfach mal die schriftliche Division zweier Binärzahlen auf einem Blatt 
Papier verstanden haben. Dann ist klar, was der Code macht: es wird 
Binärstelle für Binärstelle abgearbeitet. Genauso wie man eben bei de 
schriftlichen Division zweier Dezimalzahlen eben Dezimalstelle für 
Dezimalstelle abarbeitet.

Und genauso wie man eine schriftliche Division auf einem Blatt Papier 
vorbereiten und dann "starten" muss, um nach einigen Berechnungen zum 
"Ende" zu kommen, genauso muss man es in der Hardware machen: Dividend 
und Divisor bereitstellen, die Rechnung "starten" und warten,solange die 
Rechnung noch andauert.

Länger Rede kurzer Sinn: in VHDL einfach nur ein c<=a/b hinzuschreiben 
ist ein berechtigter Kündigungsgrund.


Der Fall hier ist zudem eins Division durch eine Konstante 50, die in 
Hardware (auf 5 Dezimalstellen genau) als Multiplikation mit 41 und 
anschließender "Division" durch 2048 darstellbar ist:
x/50 = x * 1/50 = x * 41/2048, also x * 41 und die unteren 11 Bits 
ignorieren.

Wenn die 5 Dezimalstellen nicht reichen, dann muss man einfach ein paar 
Bit mehr zugeben und so rechnen: X * 5243/262144, also x * 5243 und die 
unteren 18 Bits ignorieren.

: Bearbeitet durch Moderator
von Okan M. (okan_m)


Angehängte Dateien:

Lesenswert?

ich habe versucht die Division von Division in VHDL - Lothar Miller 
(lothar-miller.de) zu benutzen. Bekomme das nicht hin, weil ich 
folgendes Problem habe.

Ich will Seconds in ein std_logic_vector Konvertieren. Habe dafür ein 
Identisches input gebaut.

1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
   
6
entity stopuhr is
7
generic(ClockFrequencyHz : integer);
8
--b  : integer range 4 to 32 := 32 ); -- Breite 
9
port(
10
    Clk     : in std_logic;
11
    nRst    : in std_logic; -- Negative reset
12
   testtime  : in integer;
13
   t      : inout integer;
14
  t_tmp        : inout STD_LOGIC_VECTOR (31 downto 0) := (others => '0');
15
    Seconds : inout integer
16
   );
17
end entity;
18
 
19
architecture rtl of stopuhr is
20
  
21
begin
22
 
23
    process(Clk,testtime) is --, t_time
24
    begin
25
        if (rising_edge(Clk)) then
26
 
27
            -- If the negative reset signal is active
28
            if nRst = '1' then
29
                Seconds <= 0;
30
           t <= 0;
31
            else
32
 
33
                  if testtime = 0 then  
34
                        Seconds <= 0;
35
                t_tmp <= std_logic_vector(to_unsigned((0),t_tmp'length));
36
 
37
                    else
38
                        Seconds <= Seconds + 1;
39
                t_tmp <= std_logic_vector(to_unsigned((t +1),t_tmp'length));
40
                    end if;
41
             end if;
42
        end if;
43
                      
44
45
    end process;
46
 
47
end architecture;

Ich bekomme einen Falschen Wert nach der Konvertierung, und folgende 
Fehlermledung: "** Error: (vsim-86) Argument value -2147483647 is not in 
bounds of subtype NATURAL."

Die Fehlermeldung in TB tritt aber nur an denn Stellen auf, wo ich kein 
Signal mehr bekomme (also nach dem der Durchlauf Fertig war), das ist 
auch gewollt so.
Ich denke also nicht das der Fehler Relevant ist.

Habe versehentlich ein älteren Screenshot angehangen. Der Relevante 
Screenshot ist div.png.

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


Lesenswert?

Okan M. schrieb:
> Ich will Seconds in ein std_logic_vector Konvertieren.
Beschreibe doch einfach mal die eigentliche Aufgabe und eben NICHT wie 
du sie lösen willst.

Also ganz einfach: wie lautet die ursprüngliche Hausaufgabe? Was sollst 
du machen? Eine (Stopp-)Uhr auf 7-Segment-Anzeigen?

Okan M. schrieb:
> Die Fehlermeldung in TB tritt aber nur an denn Stellen auf, wo ich kein
> Signal mehr bekomme
Im echten Leben auf echter Hardware gibt es das eben nicht, dass du 
"kein Signal mehr bekommst", denn die Leitungen im FPGA haben immer 
irgendeinen Signalpegel.

Deine Denkweise ist ganz extrem prozedural, wie z.B. bei einem 
Softwareprogramm. So funktioniert HardwareBESCHREIBUNG nicht! Sondern du 
musst eine Schaltung im Kopf haben und die dann mit der 
HardwareBESCHREIBUNGssprache VHDL so beschreiben, dass der Synthesizer 
aus deiner Beschreibung wieder die von dir ausgedachte Schaltung im FPGA 
erzeugen kann.

Es wird bitter schiefgehen, wenn du mit VHDL programmieren willst.

> Seconds : inout integer
Aus reiner Gedankenlosigkeit oder Schreibfaulheit inout Ports zu 
verwenden, wo eigentlich out oder in korrekt wäre, ist für mich ein 
plausibler Grund für eine fristlose Kündigung.
Zudem bekommt man damit gern mal ganz eigenartige Effekte mit multiplen 
Treibern.

von Okan M. (okan_m)


Lesenswert?

Meine Aufgabe ist es, mit einem Hall-Sensor die Geschwindigkeit zu 
messen. Ich habe ein Magneten und einen Sensor.

Die Geschwindigkeit soll ich dann in kmh auf einer 7-Seg Anzeige 
darstellen.

Ich habe bereits mit Seconds die Zeit, wie lange es für eine Umdrehung 
braucht. denn Umfang habe ich auch. Der ist eine Konstante von 30cm.

Ich will als vorletzten schritt nur noch:

 v = s/t

s die konstante von 30cm

t die zeit die mir meine VHDL - Datei stopuhr zur Verfügung stellt.

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


Lesenswert?

Okan M. schrieb:
> Die Geschwindigkeit soll ich dann
> in kmh auf einer 7-Seg Anzeige darstellen.
Nach kurzem Nachdenken komme ich zur Idee, dass 3333 U/h einer 
Geschwindigkeit von 1km/h = 1km/3600s entsprechen. Man muss also nur die 
Umdrehungsimpulse zählen, die in der Zeit 3333/3600 = 0,926 Sekunden 
hereinkommen und hat damit schon die gewünschte Geschwindigkeit in km/h.

Und durch diese Zählung der sich ändernden Anzahl der Impulse pro 
konstanter Zeit erspare ich mir durch die geschickte Skalierung mit 
926ms 1. jegliche Umrechnung und 2. die Division, die ich brauche, wenn 
ich eine konstante Impulszahl durch eine sich ändernde Zeit teilen muss.

: Bearbeitet durch Moderator
von Okan M. (okan_m)


Lesenswert?

Kannst du das näher Erläutern bitte,
was meinst du mit Umdrehungsimpulse.

Ich habe bereits ein Counter, welche mir als std_logic immer dann eine 1 
liefert, wenn eine Umdrehung durch ist.

von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> Man muss also nur die
> Umdrehungsimpulse zählen, die in der Zeit 3333/3600 = 0,926 Sekunden
> hereinkommen und hat damit schon die gewünschte Geschwindigkeit in km/h.

Ja, aber eben auch extrem ungenau, also ohne Nachkommastellen. Und wenn 
mit dieser Methde von sagen wir 0 bis 100 km/h messen können will, dann 
bekommt er nur alle 92,6 Sekunden einen neuen Messwert.

Aber auch hier im Thread genauso wie bei den eMail mangelt es an 
Details. Welche Frequenz oder welchen Frequenzbereich wird das Signal 
vom Sensor haben? Ist das ein Rechteck? Muss das entprellt werden?

Okan M. schrieb:
> Ich habe bereits mit Seconds die Zeit, wie lange es für eine Umdrehung
> braucht.

Nein, das liefern deine Komponenten nicht. Simuliere die doch einzeln 
und gucke ob die wirklich das tun was du von ihnen erwartest. Sekunden 
ist auch eine Einheit die zu grob ist um Nachkommastellen bei der 
Geschwindigkeit zu bekommen, so wird das eine ungenaue Messung.

Okan M. schrieb:
> was meinst du mit Umdrehungsimpulse.

Die liefert dein Sensor. Weitere Dateils zu deinem Signal S_1 willst du 
ja nicht preisgeben. Aber mehr Details wären wichtig - vor allem für 
dich selbst. Guck das mal mit dem Oszi an (vor allem die Flanken), mach 
eine Abschätzung wie schnell sich das maximal dreht, ...

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


Lesenswert?

Gustl B. schrieb:
> Ja, aber eben auch extrem ungenau, also ohne Nachkommastellen.
Ja, das macht mein Tacho im Auto auch. Und ich sehe keine Forderung, 
dass Nachkommastellen angezeigt werden müssten.

Und (um im Konjunktiv zu bleiben) falls das der Fall wäre, dann würde 
ich dafür sorgen, dass das Rad mehr Impulse pro Sekunde ausgeben würde

> Und wenn mit dieser Methde von sagen wir 0 bis 100 km/h messen können
> will, dann bekommt er nur alle 92,6 Sekunden einen neuen Messwert.
Nein, er bekommt immer nach 926ms einen neuen km/h Wert. Denn wenn sich 
das Rad in diesen 926ms einmal dreht, dann fährt er 1km/h, wenn es sich 
5x dreht, dann sind es 5km/h.

> Und wenn mit dieser Methde von sagen wir 0 bis 100 km/h messen können
> will, dann bekommt er nur alle 92,6 Sekunden einen neuen Messwert.
Wenn er mit diese Methode und nur 1 Impuls pro Umdrehung auf 2 
Nachkommastellen auflösen möchte, dann muss er 100x926ms messen.

Alternativ kann man z.B. ein Zahnrad mit 100 Zähnen als Impulsgeber 
verwenden und kann wieder in 926ms auf 2 Nachkommastellen genau messen.


Und wenn ich die Kehrwertmethode (also Dauer von Impuls zu Impuls 
umrechnen in km/h) nehmen müsste, dann würde ich mit einer Tabelle samt 
Interpolation arbeiten.

von Gustl B. (-gb-)


Lesenswert?

Lothar M. schrieb:
> Nein, er bekommt immer nach 926ms einen neuen km/h Wert. Denn wenn sich
> das Rad in diesen 926ms einmal dreht, dann fährt er 1km/h, wenn es sich
> 5x dreht, dann sind es 5km/h.

Stimmt, das war dumm von mir.

Lothar M. schrieb:
> Alternativ kann man z.B. ein Zahnrad mit 100 Zähnen als Impulsgeber
> verwenden und kann wieder in 926ms auf 2 Nachkommastellen genau messen.

Lothar M. schrieb:
> Und (um im Konjunktiv zu bleiben) falls das der Fall wäre, dann würde
> ich dafür sorgen, dass das Rad mehr Impulse pro Sekunde ausgeben würde

Alles gute Ideen.

von Okan M. (okan_m)


Lesenswert?

Ich habe jedes Detail preis gegeben, es ist ein Hallsensor, der mir eine 
0 oder 1 liefert, sobald er einen Magneten entdeckt.


Board: De10 lite

Der Name des Sensors: Hall Magnetic Field Sensor KY-003

Ich wollte es so simpel wie möglich für mich machen. ich wollte die Zeit 
stoppen zwischen der ersten Entdeckung und der letzten Entdeckung.

Dann über die folgende Formel lösen.

 v = s/t


Was für Details benötigt Ihr noch?

von Gustl B. (-gb-)


Lesenswert?

Okan M. schrieb:
> der mir eine
> 0 oder 1 liefert, sobald er einen Magneten entdeckt.

Und du glaubst dass es da eine harte Grenze gibt zwischen "Magnet da" 
und "kein Magnet da"?

Wenn da der Magnet in die Nähe kommt kann es sehr gut sein, dass der 
Sensor - das ist übrigens der hier 
https://www.elecrow.com/download/A3141-2-3-4-Datasheet.pdf - nicht einen 
schönen 00000000011111111111 Übergang liefert, sondern eher sowas 
0000001001010111011110111111111111. Um das herauszufinden könntest du 
dir das mal mit einem Oszilloskop oder Logikanalysator angucken.

Okan M. schrieb:
> Board: De10 lite

Das macht schonmal das mit den Segmenten einfach, denn die sind alle 
einzeln an das FPGA angeschlossen. Du muss also nicht multiplexen.

Okan M. schrieb:
> ich wollte die Zeit
> stoppen zwischen der ersten Entdeckung und der letzten Entdeckung.

Okan M. schrieb:
> Was für Details benötigt Ihr noch?

Um herauszufinden was denn der einfachste Weg ist wäre es gut zu wissen 
mit welchem Wertebereich du rechnest oder welchen Wertebereich du 
anzeichen können möchtest. Genau danach hatte ich mehrmals gefragt. 
Minimum sind natürlich 0 Pulse. Aber was ist die maximale Pulsrate oder 
die maximale Geschwindigkeit die du messen können willst?
Und was sie die Auflösung mit der du das messen willst? Reicht dir eine 
Anzeige von 0 ... 999999 km/h oder willst du 0 ... 999.999 km/h oder 
sogar 0 ... 9.99999 km/h? Oder noch genauer: Was ist die minimale 
Umdrehungsrate die du messen können willst, was sie maximale 
Umdrehungsrate?

Wie sieht es mit den Ideen von Lothar aus? Willst du mehrere Magnete am 
Rad befestigen? Willst du sonst wie mehr Pulse erzeugen?

Mit diesen ganzen Details entscheidet sich was am Ende der Lösungsweg 
ist.

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


Lesenswert?

Okan M. schrieb:
> Dann über die folgende Formel lösen.
> v = s/t
Ist das dein Plan oder ist das Teil der Aufgabe?

> v = s/t
> s die konstante von 30cm
Du willst aber keine Geschwindigkeit in cm pro irgendwas, sondern in km 
pro h.
Insofern ist die Rechnung mit 30cm nutzlos.

> t die zeit die mir meine VHDL - Datei stopuhr zur Verfügung stellt.
In welchem Format wird diese Zeit "zur Verfügung gestellt"?

> Ich wollte es so simpel wie möglich für mich machen.
Den simpelsten Weg habe ich beschrieben. Auf diese Art könnte ich die 
Aufgabe mit 30 Zeilen VHDL-Code  lösen.

Gustl B. schrieb:
> das war dumm von mir.
Halb so schlimm, du wärst bei erneutem Nachdenken sicher schnell drauf 
gekommen... 😉

: Bearbeitet durch Moderator
von Tippgeber (Gast)


Lesenswert?

Gustl B. schrieb:
> nicht einen
> schönen 00000000011111111111 Übergang liefert, sondern eher sowas
> 0000001001010111011110111111111111. Um das herauszufinden könntest du
> dir das mal mit einem Oszilloskop oder Logikanalysator angucken.

Wenn man das geschickt filtert, kann man das auch nutzen!

von Okan M. (okan_m)


Lesenswert?

ich hab es hinbekommen, danke für eure Hilfe!

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


Lesenswert?

Okan M. schrieb:
> ich hab es hinbekommen
Um anderen zu helfen (wie dir auch geholfen wurde) , wäre es jetzt 
schön, wenn du deine(n) Lösung(sansatz) zeigen würdest.

von Messi (Gast)


Lesenswert?

Hier gibt es einen preisgünstigen Core :
https://www.zipcores.com/pipelined-divider.html

von W.S. (Gast)


Lesenswert?

Manah schrieb:
> Ich führe eine bestimmte Rechnung aus,

Nö. Stattdessen willst du eine Funktionalität, die du dir vorstellst, 
formulieren, um sie schlußendlich in Form von digitalen Gattern, 
Flipflops und E/A-Treibern in Silizium zu gießen. So herum.

Auch hier sieht es so aus, daß gerade VHDL zu schlecht gelehrt wird, so 
daß die Studenten in höheren Sphären schweben (vulgo: den Teppich unter 
den Füßen verloren haben) und sich keine Gedanken machen, ob und wie 
ihre Ideen sich in einem Sack von LUT's und FF's tatsächlich machen 
lassen. Sicherlich lassen sich da Formulierungen finden, die syntaktisch 
OK sind, aber eben leider zu nicht synthetisierbarem Zeugs führen. Und 
dann fragt der Urheber des ganzen Krams, _WIESO??_ Ich habe doch alles 
richtig gemacht, denn der Compiler hat mich nicht angemeckert!

W.S.

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.