Hallo,
ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high
ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der
Counter auf null zurückgesetzt werden.
Weiß aber nicht so recht genau, wie ich das bewerkstelligen kann.
Hier mein Versuch:
1
2
process(clk,reset_internal,flanke,cntMSEC)
3
variablesave_cntMSEC:integer:=0;
4
begin-- process
5
ifclk'eventandclk='1'then-- rising clock edge
6
ifprescaler<49then
7
prescaler<=prescaler+1;
8
else
9
prescaler<=0;
10
ifcntMSEC=50then
11
cntMSEC<=0;
12
else
13
cntMSEC<=cntMSEC+1;--1 us
14
endif;
15
endif;
16
endif;
17
ifreset_internal='1'then
18
prescaler<=0;
19
cntMSEC<=0;
20
endif;
21
ifflanke='1'then
22
save_cntMSEC:=cntMSEC;
23
save_cnt2<=save_cntMSEC;
24
prescaler<=0;
25
cntMSEC<=0;
26
endif;
27
endprocess;
Die Idee war, den wert vor dem Reset in eine Variable zu speichern, da
Variablen ja den Wert sofort annehmen. Um global auf diesen Wert
zugreifen zu koennen, habe ich die Variable in ein Signal gespeichert
und dann erst das ganze resetet...
Synthetisieren laesst es sich... aber die Simulation zeigt, es
funktioniert nicht... schaetze aufgrund der Fehlermeldungen:
Wieso erhalte ich diese Fehlermeldungen?
Und wenn das mit der Variablen keine gute Idee ist, da man sie als
Anfaenger meiden soll... Bin ich gerne offen fuer andere Ideen..
Vielen Dank im voraus..
Hallo,
zuerst solltest du mit save_cnt2 auch noch was machen.
Möchtest du wirklich einen asynchronen kombinatorischen reset?
Wenn überhaupt mach deinen reset_internal asynchron und deine
Flanke(welche höchstwahrscheinlich synchron kommt) synchron.
Und eigentlich sollte auch "save_cnt2 <= cntMSEC;" im synchronen Reset
langen.
Wie sieht den deine simulation aus?
dden schrieb:> Hallo,> zuerst solltest du mit save_cnt2 auch noch was machen.
Was meinst du, ich sollte mit save_cnt2 auch noch etwas machen?
Also ich habe spaeter save_cnt2 verwendet um davon einen konstanten wert
abzziehen. Dieser konstante wert 't' ist groesser als der wert in
save_cnt2 - somit wird der Wert negativ. Dann moechte ich diesen
negativen Wert mit einer anderen konstanten multiplizieren...
dden schrieb:> Möchtest du wirklich einen asynchronen kombinatorischen reset?> Wenn überhaupt mach deinen reset_internal asynchron und deine> Flanke(welche höchstwahrscheinlich synchron kommt) synchron.
Ist das nun so besser? (siehe code)
1
-- Frequenzteiler 1msec
2
process(clk,reset_internal,flanke,cntMSEC)
3
variablesave_cntMSEC:integer:=0;
4
begin-- process
5
ifclk'eventandclk='1'then-- rising clock edge
6
ifprescaler<49then
7
prescaler<=prescaler+1;
8
else
9
prescaler<=0;
10
ifcntMSEC=50then
11
cntMSEC<=0;
12
else
13
cntMSEC<=cntMSEC+1;--1 us
14
endif;
15
endif;
16
ifflanke='1'then
17
save_cntMSEC:=cntMSEC;
18
save_cnt2<=save_cntMSEC;
19
prescaler<=0;
20
cntMSEC<=0;
21
endif;
22
endif;
23
ifreset_internal='1'then
24
prescaler<=0;
25
cntMSEC<=0;
26
endif;
27
28
endprocess;
29
30
31
32
process(inp,clk)--Lothar Miller
33
begin
34
ifrising_edge(clk)then
35
-- Schieberegister
36
sr<=sr(6downto0)&inp;
37
-- Flankenerkennung, 1 Sync-FF, dann sofort reagieren
Irgendwie krieg ich ne Gänsehaut, wenn ich Deinen code betrachte :-)
Mach einfach einen rein getakteten Prozess(nur clk in der SL), definier
save_cntMSEC als Signal und wenn dein Rücksetzt-Signal kommt, setzt Du
halt den Zählerzurück und weist den aktuellen Wert save_cntMSEC zu. Wozu
brauchst Du da eine Variable?
Fellap schrieb:> process (clk, reset_internal,flanke,cntMSEC)
Wo lernst mann den diese seltsame zusammengepackte Kombination von
getaktetem und kombinatorischem Prozess? Und vor allem: der Code ist so
eigenartig formatiert, dass man dieses Gebastel erst beim zweiten Blick
erkennt.
> Ist das nun so besser? (siehe code)
Nein. In einen getakteten Prozess kommt vor oder hinter dem Takt keine
kombinatorische Beschreibung! Niemals!
> process (inp,clk) --Lothar Miller
Nein, das stimmt nicht. Ich hätte in die Sensitivliste nicht das
unnötige Signal inp aufgenommen...
Fellap schrieb:> ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high> ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der> Counter auf null zurückgesetzt werden.
Dann wird in deinem gespeicherten Counterwert immer 0 stehen.
Warum: weil im ersten Augenblick der Counter gespeichert wird, dann wird
der Counter zurückgesetzt und dann gleich der zurückgesetzte Wert wieder
gespeichert...
> ich habe einen Counter und Eingangssignal. Wenn das Eingangssignal high> ist, soll der Counterwert zu diesem Zeitpunkt gespeichert werden und der> Counter auf null zurückgesetzt werden.
Ich würde das so machen:
1
processbegin
2
waituntilrising_edge(clk);
3
ifms_presc<49then-- us erzeugen aus 50MHz
4
ms_presc<=ms_presc+1;
5
else
6
ms_presc<=0;
7
cnt<=cnt+1;-- us zählen
8
endif;
9
10
sr<=sr(1downto0)&inp;-- Einsynchronisieren mit Schieberegister
end process;
Ah achso.. also wird hier nun nur zu dem Zeitpunkt wenn sr = "001" ist
gespeichert? und im naechsten takt, trifft die Bedingung aufgrund sr =
"010" nicht mehr zu und wird deswegen nicht mehr ueberschrieben?!
Ich habe da noch meine Probleme mit der sensitive-Liste... Was kommt
denn nun alles in die sensitvelist? - dachte immer, alles, auf das der
Process reagieren soll... quasi "angestupst" werden soll..?!
Wenn ich nun noch Berechnungen durchfuehren moechte... kann ich dass
dann auch noch in den selben Process mitreinschreiben? Oder lieber einen
neuen Process? bzw Wann einen neuen Process anfangen? Ihr und ich merkt
schon... Hier fehlt es vorne und hinten an Grundlagen :-/
Ein anderes Problem hat sich eben auch noch ergeben...
Wenn ich nun eine Berechnung durchfuehren moechte (siehe Code)...
1
processbegin
2
waituntilrising_edge(clk);
3
ifms_presc<49then-- us erzeugen aus 50MHz
4
ms_presc<=ms_presc+1;
5
else
6
ms_presc<=0;
7
cnt<=cnt+1;-- us zählen
8
endif;
9
10
sr<=sr(1downto0)&inp;-- Einsynchronisieren mit Schieberegister
11
12
if(sr="001")then-- steigende Flanke
13
save_cnt<=cnt;-- Wert speichern
14
cnt<=0;-- und Zähler zurücksetzen
15
calc_d<=save_cnt-t;--t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
16
d<=d+(calc_distance*a);--a = 500
17
endif;
18
endprocess;
d wird hier in Mikrometer berechnet.. aber d wird bis in den
Meterbereich reichen... So wird d riesen gross. Angezeigt werden soll
aber nur Meter und Zentimeter auf 7Segementanzeigen mittels Lothars
Millers Vector -> BCD Converter
Nun war mein erster Gedanke, einfach durch 10000000 teilen..
Jedoch laesst sich das nicht synthetisieren... und von divisionen
generell wird bei VHDL sowieso meistens abgeraten...
Jemand eine Idee?
Aber ich glaube du hast noch nicht verstanden, daß du in VHDL nicht
programmierst sondern Bauteile "erschaffst" und sie danach mit signalen
miteinander verdrahtest. Dort passiert immer alles gleichzeitig (wie in
einer Elektronischen Schaltung halt). Dinge die nacheinander passieren
sollen werden mit verschalteten RS-FlipFlops gemacht (Counter und
Schieberegister zusammen mit kombinatorischer logik -> Statemachines).
Fellap schrieb:> Ich habe da noch meine Probleme mit der sensitive-Liste... Was kommt> denn nun alles in die sensitvelist? -
Alles, was zur Neuberechnung eines Prozesses für die Simulation
wichtig ist. Die Synthese schert sich einen feuchten Kehrricht um die
Sensitivliste...
> Angezeigt werden soll aber nur Meter und Zentimeter auf> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter
Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur
die interessanten aus..
> und von divisionen generell wird bei VHDL sowieso meistens abgeraten...
Warum wohl? Wie ist ein Hardware-Divider aufgebaut?
> d wird hier in Mikrometer berechnet..
Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum
rechnest du dann nicht in mm oder in halben mm?
> Ah achso.. also wird hier nun nur zu dem Zeitpunkt wenn sr = "001" ist> gespeichert? und im naechsten takt, trifft die Bedingung aufgrund sr => "010" nicht mehr zu und wird deswegen nicht mehr ueberschrieben?!
Oder auch wegen "011", das kommt darauf an, wie lange der inp high ist.
Sieh dir einfach mal die Simulation an...
Lothar Miller schrieb:>> Angezeigt werden soll aber nur Meter und Zentimeter auf>> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter> Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur> die interessanten aus..
Ja aber dein Vector2BCD hat "nur" einen Input von 16 Bit, jedoch ist d
20 Bit lang. So kann ich doch nicht alle verarbeiten lassen!???
Lothar Miller schrieb:>> d wird hier in Mikrometer berechnet..> Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum> rechnest du dann nicht in mm oder in halben mm?
Weil ich nicht weiss wie.. am liebsten wuerde ich ja nur in cm rechnen
aber ich habe irgendwie voll die Blockade :-/
Lothar Miller schrieb:>> und von divisionen generell wird bei VHDL sowieso meistens abgeraten...> Warum wohl? Wie ist ein Hardware-Divider aufgebaut?
Ohja.. okay jetzt sehe ich es auch....
Lothar Miller schrieb:>> d wird hier in Mikrometer berechnet..> Warum? Ist doch unnötig, und zudem ist der kleinste Schritt 500um. Warum> rechnest du dann nicht in mm oder in halben mm?
richtig... der kleinste Schritt ist 500um... Stimmt auch mit der
Simulation ueberein...
Aber ich steh so auf dem Schlauch... Ich habe 4 7 Segmentanzeigen... Wie
kann ich denn nun designen, dass der Vector2BCD mir 10er und 1er Meter
und 10er und 1er cm ausgibt... Also klar ist, dass der Vektor2BCD 5
Digits bereit stellt... und ich die oberen 4 anzeigen lassen muss.. aber
wenn ich momentan den vektor d dem Vector2BCD uebergebe (siehe Code)
kommen natuerlich nur im Mikrometerbereich die zahlen raus....
1
vector_sig(15downto0)<=conv_std_logic_vector(d,16);--Uebergabe von d an Vector2BCD (d: integer)
Fellap schrieb:> Lothar Miller schrieb:>>> Angezeigt werden soll aber nur Meter und Zentimeter auf>>> 7Segementanzeigen mittels Lothars Millers Vector -> BCD Converter>> Ja, ist doch kein Problem: wandle alle Stellen des Vektors und gib nur>> die interessanten aus..>> Ja aber dein Vector2BCD hat "nur" einen Input von 16 Bit, jedoch ist d> 20 Bit lang. So kann ich doch nicht alle verarbeiten lassen!???
Sorry das war Schmarn was ich schrieb.. mein d vektor wird noch viel
laenger... ist ja auch klar.. wenn die Entfernung steigt, benoetigt der
Vektor mehr Bits... und wenn es bis in den Meterbereich hineinragt und
der Vektor in Mikrometer dargestellt wird, ist ja klar, das der d-vektor
so ultra lang wird... Aber wie kann ich das verhindern? - Wenn ich nicht
Dividieren kann / soll???
Aber soweit erstmal vielen vielen Dank fuer eure Muehe! :)
Fellap schrieb:> Sorry das war Schmarn was ich schrieb.. mein d vektor wird noch viel> laenger... ist ja auch klar.. wenn die Entfernung steigt, benoetigt der> Vektor mehr Bits... und wenn es bis in den Meterbereich hineinragt und> der Vektor in Mikrometer dargestellt wird, ist ja klar, das der d-vektor> so ultra lang wird... Aber wie kann ich das verhindern? - Wenn ich nicht> Dividieren kann / soll???
Sorry... war wohl noch zu verschlafen... Habe es nun...
digit1<=sig_bcd(7downto4);--1. Zahl anzeigen lassen
13
digit2<=sig_bcd(11downto8);--2. Zahl anzeigen lassen
14
digit3<=sig_bcd(15downto12);--3. Zahl anzeigen lassen
15
digit4<=sig_bcd(19downto16);--4. Zahl anzeigen lassen
Bloss haben sich noch ein paar Probleme herausgestellt.... und zwar
zaehlt der counter nur bis 62375380, als waere er nur 25 Bit breit..
Aber integer hat doch 32 Bit oder?
Sowohl in der Simulation, als auch auf der Hardware besteht dieser
Fehler...
Hat jemand eine Idee?
digit1<=sig_bcd(7downto4);--1. Zahl anzeigen lassen
15
digit2<=sig_bcd(11downto8);--2. Zahl anzeigen lassen
16
digit3<=sig_bcd(15downto12);--3. Zahl anzeigen lassen
17
digit4<=sig_bcd(19downto16);--4. Zahl anzeigen lassen
Was mir auch noch aufgefallen ist... wenn die zeit save_cnt kleiner ist,
als t.. muesste ja d eigentlich kleiner werden... wird es aber nicht..
es steigt einfach weiter an...
1
signalms_presc:integerrange0to49:=0;--Counter for get 1 usec
2
signalcnt:integerrange0to50:=0;--Counter for 1 msec
3
signalsr:std_logic_vector(2downto0);
4
signalsave_cnt:integer:=0;
5
signalcalc_d:integer:=0;
6
signald:integer:=0;
7
signalt:integerrange19to20:=20;--minimal d = 20 mikrometer
8
9
processbegin
10
waituntilrising_edge(clk);
11
ifms_presc<49then-- us erzeugen aus 50MHz
12
ms_presc<=ms_presc+1;
13
else
14
ms_presc<=0;
15
cnt<=cnt+1;-- us zählen
16
endif;
17
18
sr<=sr(1downto0)&inp;-- Einsynchronisieren mit Schieberegister
19
20
if(sr="001")then-- steigende Flanke
21
save_cnt<=cnt;-- Wert speichern
22
cnt<=0;-- und Zähler zurücksetzen
23
calc_d<=save_cnt-t;--t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
24
d<=d+(calc_distance*a);--a = 500
25
endif;
26
endprocess;
Also Problem:
d zaehlt nicht bis 32 bit hoch...
d wird in der hardware nicht runtergezaehlt, wenn t groesser als
save_cnt ist
Fellap schrieb:> signal d: integer := 0;> d zaehlt nicht bis 32 bit hoch...
Sondern wie weit?
Wie war das nochmal mit dem Vorzeichen bei einem integer?
> d wird in der hardware nicht runtergezaehlt, wenn t groesser als> save_cnt ist
1
calc_d<=save_cnt-t;--t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
2
d<=d+(calc_distance*a);--a = 500
Ja, warum denn auch? Das eine hat mit dem Anderen ja nichts zu tun...
> d wird in der hardware nicht runtergezaehlt
Wie sieht es in der Simulation aus?
Nochmal: du brauchst auch gar keine 32 Bit, wenn du den Faktor 500
endlich mal weglässt! Dadurch machst du dir 9 Bits "kaputt" und dem
Optimizer unnötig Arbeit. Denk einfach mal da drüber nach, und dann
reicht dir ein Integer auf einmal locker und luftig ganz ohne das 32.
Bit und Überlauf und Vorzeichen undsonstwasauchimmernoch....
Lothar Miller schrieb:> Fellap schrieb:>> signal d: integer := 0;>> d zaehlt nicht bis 32 bit hoch...> Sondern wie weit?> Wie war das nochmal mit dem Vorzeichen bei einem integer?
In der Simulation zaehlt es nur bis integer 62375380 (bzw. 26 Bit)
hoch...
In der Hardware zaehlt es bis integer 6553xxxx (bzw. 26 Bit) hoch.
(xxxx, da ich in der Hardware nicht die letzten Stellen sehen kann
aufgrund nur der 4x 7Segementanzeigen)...
Also waere ja massig Bits uebrig fuer das Vorzeichenbit...
Lothar Miller schrieb:>> d wird in der hardware nicht runtergezaehlt, wenn t groesser als>> save_cnt ist calc_d <= save_cnt - t; --t = constanter wert (fast gleich> gross wie save_cnt --> ergebnis kleine zahl)> d <= d + (calc_distance * a); --a = 500> Ja, warum denn auch? Das eine hat mit dem Anderen ja nichts zu tun...
Sorry.. sehe gerade, habe mich hier, vertippt.. aber in meinem Code
stimmts... muss heißen:
1
calc_d<=save_cnt-t;--t = constanter wert (fast gleich gross wie save_cnt --> ergebnis kleine zahl)
2
d<=d+(calc_d*a);--a = 500
Lothar Miller schrieb:>> d wird in der hardware nicht runtergezaehlt> Wie sieht es in der Simulation aus?
In der Simulation funktioniert das einwandfrei. - wenn t groeßer als
save_cnt, wird "d" kleiner... Bloß in der Hardware funktioniert das
nicht... Komme da kein stueck voran...
Lothar Miller schrieb:> Nochmal: du brauchst auch gar keine 32 Bit, wenn du den Faktor 500> endlich mal weglässt! Dadurch machst du dir 9 Bits "kaputt" und dem> Optimizer unnötig Arbeit.
Du meinst, das ich den Faktor 100 weglasse und einfach nur mit 5
multipliziere oder? Dann spare ich mir so immerhin 6 Bit... Oder
verstehe ich da gerade etwas falsch?