Hallo,
ich habe eine Frage: Ich habe ein 12bit Eingangssignal vom AD Wandler.
Wie mache ich am besten den VHDL code um die fallende Flanke vom Signal
zu erkennen?
Ich dachte an zwischenstellen wo ich quasi ein Vergleich erstelle und wo
ein max. wert erreicht wird und wenn er unterschritten wird fängt die
fallende flanke an?
Hat da jemand ein besseren vorschlag?
Gruß
M.
> Wie mache ich am besten den VHDL code um die fallende Flanke vom Signal> zu erkennen?
Du machst die erste Ableitung des Signals. Wenn diese eine bestimmte
negative Schwelle überschreitet hast du eine fallende Flanke.
Also: vorherigen Wert speichern, eine bestimmte Zeit abwarten, dann den
vorigen Wert vom aktuellen abziehen. Wenn das Ergebnis negativ ist und
eine bestimmte Größe überschreitet, dann hast du die fallende Flanke.
Nicht ganz uninteressant sind natürlich auch Daten wie:
wie steil ist deine fallende Flanke?
welche Frequenz hat dein Signal?
ist es ein Signalgemisch?
wie definierst du eine fallende Flanke bei einem analogen Signal?
Hallo,
danke für den Tipp. Ich werde ein Impuls mit der breite von ca. 20 ms
draufgeben. Der AD wandler tastet mit 20 Mhz ab.
Ich probier mal dein tipp in meine Logik reinzubekommen.
DANKE DANKE
Gruß
> Ich werde ein Impuls mit der breite von ca. 20 ms> draufgeben. Der AD wandler tastet mit 20 Mhz ab.
Da reicht doch evtl. ein einfacher Schmitt-Trigger.
Ich gehe mal davon aus, dass du High- und Low-Pegel des Impulses kennst.
Dann könntest du dir zwei Grenzwerte definieren, die ein internes Signal
entweder setzen oder löschen.
> Was haltet ihr davon?
Was sagt die Simulation?
Welche Frequenz hat der REGISTER_CLK? 20MHz, also 50ns?
Das wäre arg schnell verglichen mit einem
>>> Impuls mit der breite von ca. 20 ms
Immerhin sind da 6 Zehenerpotenzen dazwischen... :-o
M. schrieb:
Hallo,
wenn du mitten in einer fallenden Flanke bist, ist üblicherweise x(n -
1) < x(n). Aber darauf kannst du dich nicht verlassen. Schon die
AD-Wandler-Kennlinie muss nicht monoton sein, abgesehen vom Rauschen.
Daher kann es passieren, dass x(n - 1) > x(n) in einer fallenden Flanke
vorkommt.
Dann liefert einer deiner Vergleiche hier
> if ((SAVE1 - SAVE0)>0 ) or ((SAVE2 - SAVE1)>0) or ((SAVE3 -> SAVE2)>0) or ((SAVE4 - SAVE3))>0 or ((SAVE5 - SAVE4)>0) or ((SAVE6 -> SAVE5)>0) or ((SAVE7 - SAVE6)>0) then
größer 0, damit erhälst du eine steigende Flanke. Das Ergebnis läuft
dann durch deine Register und erzeugt dir für sieben Takte eine
steigende Flanke.
Dies Problem hast du bei einer hohen Sampling-Frequenz, deine 20 MHz.
Falls du das nicht ändern kannst, ist es am einfachsten, du
programmierst einen Schmitt-Trigger. Eine andere Möglichkeit beseht
darin, einen Tiefpass (arithmetischer Mittelwert) zu verwenden oder eine
Flanke muss mehr als 128 Takte aktiv sein, erst dann schaltest du um.
Oder reduziere die Samplingfrequenz.
Tom
Hi,
das mit dem (arithmetischer Mittelwert) hab ich mir auch schon überlegt,
nur weiß ich nicht wie ich am besten das machen soll... die 7
Zwischensspeicherungen addieren und duch 7 teilen?? Aber das mit dem
Teilen ist so ein ding mit dem std_logic_vectoren..... gibt es was
fertiges im coregeneartor zu finden? Oder wie programmier ich am besten
den Teifpass oder Schmitt- Trigger?
Gruß
Keine Ahnung ob die mittelwerte wirklich zielführend sind, aber am
einfachsten wäre es in dem Fall einfach 8 werte zu addieren und dann die
hinteren 3 bits abzuschneiden, was einer division durch 8 entspricht.
Eine division durch 7 dafür zu verbauen wäre völlig mit Kanonen auf
Spatzen geschossen.
Hi,
da ich noch in paar dingen noch sehr als Anfäger bin, wie würd ich denn
das machen die letzten 3 bits abzuschneiden?
Bzw. ich versteh es nicht ganz mit der division...?
Vielleicht ein zahlenbeispiel? :)
Gruß
Hallo M.
Iulius schrieb:
> Eine division durch 7 dafür zu verbauen wäre völlig mit Kanonen auf> Spatzen geschossen.
Eine Division durch Sieben ist eine Multiplikation mit
1/7 = 0.142857 = (0.142857 * 1024) / 1024 = 146/1024
Also, du addierst deine Eingangswerte, multiplizierst mit 146 und
schneidest die letzten 10 Bit ab. Das geht auch mit anderen
Zweierpotenzen.
Ich bezweifle, ob bei deinem Verhältnis (1/400000) von Signalfrequenz zu
Samplingfrequenz ein Mittelwert über sieben Werte ausreicht. Das wäre
ein FIR-Filter 6. Ordnung.
Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz
einfach mit einer FSM programmieren.
Du kannst auch nur jedes 1024 Sample verwenden, damit hast du deine
Samplingfrequnez auf rund 20kS/s reduziert.
Tom
Anstatt einen Zähler zu nehmen der so weit zählt kann man aber auch
gleich mehrere Takte lang auswerten, das ist zum einen sicherer bzgl
einzelnen Ausreißern und verbraucht auch nicht viel mehr Ressourcen.
Wo soll denn nun der Vorteil von z.b. 7 Samples ggü 8 sein, so das man
das auf Biegen und Brechen nutzen will (div, mul, etc) ?
Das erschließt sich mir nicht.
@ Lothar :
ich wusste doch das da ein Haken ist ;)
Verwende lenght praktisch nie, sondern wenn die Länge nicht feststeht
meist direkt das entsprechende generic.
Das mit left werde ich mir aber merken, klingt gut.
Es kommt folgender fehler: ""Left bound value <12> of slice is out of
range [11:0] of array <summe>
Netlist EINGANGS_REGISTER(Behavioral) remains a blackbox, due to errors
in its contents""
@ Thomas :
> Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz
einfach mit einer FSM programmieren.
FSM = ? :)
Gruß
FSM = finite state machine oder einfacher "Zustandautomat"
ansonsten hatte Lothar schon recht, lenght ist eins zu viel.
summe_div_8 <= summe(summe'length downto 3);
ist also entweder
summe_div_8 <= summe(summe'length-1 downto 3);
oder
summe_div_8 <= summe(summe'left downto 3);
aber eigentlich sagt das der Fehler auch ;)
Scheinbar hast du aber noch ein paar mehr Denkfehler, wenn ich mir das
ungetaktete Addieren sowie Auswerten von 8 Werten mit Signalen ansehe...
Hast du schonmal etwas einfacheres geschrieben ?
Mit ein paar Leds kann für den anfang super ausprobiern wie man das mit
den shiftoperationen usw richtig macht.
Siehe Beitrag "Re: Flanke vom Signal erkennen"
EDIT:
Also gut, ich hätte gleich auf Absenden drücken müssen ;-)
Wenn SAVE0 ..7 jeweils 12 Bit breit sind, dann ist die Summe davon 3 Bit
breiter.
Ergo: Das Signal summe als std_logic_vector(11 downto 0) ist zu kurz.
Du solltest nicht mit std_logic Vektoren rechnen, nimm besser die in der
numeric_std definierten Datentypen signed und unsigned für solche
Aufgaben.
Hallo, also danke erstmal an euch alle!!!
Hier mal der Code, ich wollte für den Anfang einfach mal sagen wenn der
Mittelwert der Zwischenstellen (SAVE0...7) kleiner als "100000000000"
dann soll am Ausgang ne 1 kommen ansonsten ne null . Aber klappt nicht
so ganz..
Am AD wandler liegt ein Rechtecksignal an!
Hier mal der Code:
Was sagt denn die Simulation?
> if summe_div_8 < ("100000000000") then --
Sieh dir mal die Warnungen des Synthesizers an.
Deine summe_div_8 ist nur 9 Bits breit, das ist dir klar?
> if summe_div_8 < ("100000000000") then --
Welche Libs verwendest du denn?
igor schrieb:
> @ Thomas :>> Am Besten du verwendest einen Schmitt-Trigger, den kannst du ganz> einfach mit einer FSM programmieren.>> FSM = ? :)
Diese Frage habe ich erwartet. Was bist du von Beruf, wie alt.
FSM heißt Finite State Machine auf Deutsch Zustandsmaschine, Endlicher
Automat
http://de.wikipedia.org/wiki/Finite_State_Machine
Eine FSM beschreibt ein Verhalten, bei dem die Ausgangssignale nicht nur
von den Eingangssignalen abhängen, sondern auch von einem internen
Zustand. Jeder Zähler ist eine FSM.
Tom
Hallo,
@ Thomas : Bin Student und vom Zustandsautomaten habe ich natürlich
gehört, kannte es lediglich unter FSM nicht! Es wurde auch behandelt,
nur nicht so intensiv!
@Lothar Miller ; Jetzt hat es mich total verwirrt... ich möchte doch nur
einen Mittelwert bilden.
Mal ein Beispiel:
A= 1111, B = 1011, C = 1000-- Mittelwert davon wäre laut der
Beschreibung von obem mit dem "left downto"
1111 -- 15
+ 1011 -- 11
+ 1000 -- 8
------------
100010 -- 34
/ 3 -- 3
------------------------
summe'left downto ? -- 11,3 (1011)
Hier verplannt es mich, ich soll die letzten stellen weg schneiden? Es
müsste ja 1011 rauskommen, wenn ich auch nur eine stelle wegschneide
dann kommt da nie 1011 raus? Oder hab ich das vollkomen falsch
verstanden.
Ich habe jetzt mal rumprobiert. und hab mir gedacht Schwellen zu
definieren, und zwar ist vom AD wandler max. Spannung bei "111111111111"
was der 4095 quantisierungsstufe entspricht und min. bei "000000000000",
was der 0 quantisierungsstufe entspricht.
Ich hab einfach gesagt wenn der Letzte zustand kleiner als
"100110011001" (60% von Maximum) und die ersten 6 Zustände über der
"100110011001" dann fängt da meine fallende Flanke an!
naja, das mit dem /3 is genauso ungünstig wie mit /7. am besten halt
durch eine zweierpotenz teilen wie 2,4,8,16,32 ...
das hat den vorteil das man für die division nur shiften muss.
also 6/2=3
wodurch binär durch abschneiden der letzten stelle 110 -> 11(0) = 3 wird
und das funktioniert natürlich auch bei der 4
also 20/4 = 5
durch abschneiden der letzten beiden stellen sieht es dann so aus
10100 -> 101(00) = 5
ich hoffe, das prinzip ist verständlich dargestellt
HI,
ok jetzt hab ich es kapiert! :) Danke nochmal für das Beispiel. Jetzt
habe ich aber dazu eine Frage. Angenommen ich möchte aus 8 Zuständen den
Mittelwert rechnen und dem dann meinem Ausgang zuweisen, wie mach ich
das da der Ausgang ja std_logic_vector 11 downto 0 und mein Mittelwert
ja dann nur noch aus 7 downto 0 besteht. (Teile duch 8 letzten 4 bits
gehen verloren ). Kann ich da irgendwie die restlichen Bits mit Null
füllen... oder geht es überhaupt nicht. Weil für mich wäre dies ein
Filter dann, der mir ausreiser weg rechnet...
Geht das ?
Gruß
Vergiss zum Rechnen mal die std_logic Vektoren... :-/
Nimm die NUMERIC_STD statt der alten STD_LOGIC_ARITH +
STD_LOGIC_UNSIGNED.
Und dann verwende konsequent die Datentypen unsigned und signed
sowie zum Rechnen am besten integer.
Statt
1
summe:unsigned(11downto0);
2
ergebnis:unsigned(7downto0);
3
:
4
ergebnis<=summe(11downto4);-- teilen durch 16
und
1
summe:unsigned(12downto0);
2
ergebnis:unsigned(7downto0);
3
:
4
ergebnis<=summe(12downto5);-- teilen durch 32
kannst du mit Integer einfach so schreiben
1
summe:integerrange0to2**12-1;
2
ergebnis:unsigned(7downto0);
3
:
4
ergebnis<=to_unsigned(summe/16,ergebins'length);-- teilen nur durch Zweierpotenzen!!
Dein interner Akkumulator wird dann, wie Lother schon mehrfach erwähnt
hat, breiter sein um auch die Überträge aufzunehmen.
Bsp : akku von 15 bit länge und ausgeben tust du nur die höherwertigen
12 Bit.
Du verlierst übrigens bei Division durch 8 nur 3 stellen ;)
Ansonsten verabscheide dich bitte endlich von dem Gedanken solche Späße
:
- "SAVE7 and not SAVE6 and not SAVE5 and not SAVE4 and not SAVE3 and not
SAVE2 and not SAVE1 < "100110011001"
- summe <= (SAVE0 + SAVE1 + SAVE2 + SAVE3+ SAVE4+ SAVE5+ SAVE6+ SAVE7);
in einem Takt zu berechnen. Sieh dir bitte an wie FPGAs funktionieren
und du wirst festellen das das was du da baust extrem lange Laufzeiten
entwickelt.
Bei einem 4er LUT FPGA brauchst du dafür 12 Logikebenen, wenn ich mich
nicht verzählt habe. Das wird jämmerlich langsam.
> as wird jämmerlich langsam.
Zudem wird dir eine einfachere Mittelwertbildung vollkommen reichen.
Sowas etwa: http://www.lothar-miller.de/s9y/archives/25-Filter-in-C.html
Das ist zwar C, aber die Idee dürfte klar werden: ein Speicherregister
(avgsum), in das jeweils 1 neuer Wert dazuaddiert wird, und der
Mittelwert der alten Werte abgezogen wird.
Oder eben die Methode wie von mir oben beschrieben.
In jedem Fall sollte man nicht alle Werte in einem Takt addieren, denn
man bekommt sie ja schließlich ohnehin zu verschiedenen Zeitpunkten
rein.
Noch eine simple Möglichkeit mit möglichst wenig Ressourcenverbrauch bei
halbwegs kurzer Betrachtungsdauer(1 FF pro Takt Glättung + ~1/3 LUT pro
Eingangsvektorbreite + ~1/3 LUT pro Takt Glättung) :
Hallo,
puh ich hab mir gestern das zig mal durchgelesen..:) bin ein bischen, ne
eigentlich total verwirrt. Ok, ich danke euch herzlich für euere Hilfe,
ich weiß dies zu schätzen!
Aber kommen wir zum signed, unsigend....Ok ab sofort verwende ich zum
rechnen nicht mehr std_logic_vectoren sondern nur noch signed und
unsigend und integer!
Zum Verständis, heißt es das man die Signale als std_logic_vector
benutzten soll/kann, aber die Hilfssignale in signed und unsigned zum
rechnen benutzen soll? Und später mit to_.... umkonventiert bzw.
zuweist?
Zu meinem Beispiel: Ist den das schieberegister wennigstens vom Prinzip
ok?
Für mich heißt es mit jedem Takt wird das Signal weitergegeben... was
eigentlich auch gefunzt hatte oder habe ich selbst da ein denkfehler?
Jetzt würd ich als nächten schritt mit jedem Takt ein Mittelwert von
diesem sieben Zwischenständen am Ausgang ausgeben..... und dazu werde
ich jetzt mit signed und unsigned rechnen bzw. versuchen.
@ Iulius
>Du verlierst übrigens bei Division durch 8 nur 3 stellen ;)
Wieso drei ich dachte .....2^4 2^3 2^2 2^1 2^0
16 8 4 2 1
Ist doch die 4 Stelle ? oder ?
Gruß
> Wieso drei ich dachte .....2^4 2^3 2^2 2^1 2^0> 16 8 4 2 1> Ist doch die 4 Stelle ? oder ?
Was ist 13 geteilt durch 1? Oder 12785 geteilt durch 2^0?
Kurz: bei einer Division durch 1 mußt du nicht schieben... :-o
Also mußt du bei einer Division durch 2 um 1 Stelle schieben,
bei einer Division durch 4 um 2 Stellen,
bei einer Division durch 8 dann um ... wieviele Stellen?
> Für mich heißt es mit jedem Takt wird das Signal weitergegeben... was> eigentlich auch gefunzt hatte oder habe ich selbst da ein denkfehler?
Nein, das passt, ist aber enorm ineffizient, weil du so viel
Speicherplatz (= Fliflops) verbrauchst...
Hallo,
also mit den Stellen habe ich es jetzt verstanden und mit dem
>Kurz: bei einer Division durch 1 mußt du nicht schieben... :-o
sag ich nur: Klar, Shame on me! :)
Zu dem Signed und Unsigned... ich hab mir auf der Seite von Lothar
Miller dieses Diagram von std_logic_vector => signed=>integer=>unsigned
und dann wieder zu std_logic_vector.
Ich wollte jetzt fürs Üben, nach dem Schieberegister immer den
Mittelwert von den letzt 2 zustanden ausgeben (SAVE7,SAVE6). Dazu habe
ich sie in signed und dann in integer und dann wieder zurück gewandelt.
1
libraryIEEE;
2
useIEEE.STD_LOGIC_1164.ALL;
3
USEieee.std_logic_unsigned.all;
4
useIEEE.NUMERIC_STD.ALL;
5
6
7
---- Uncomment the following library declaration if instantiating
Abgesehen davon das man das nicht in einem Takt rechnen soll wegen
Recourcen verbrauch... was haltet ihr davon? Ist die denkweiße jetzt
richtig?
Ich habe schon jetzt Angst vor eueren Antworten :)
Gruß
Es fehlen alle die Signale, die hinter den --- stehen :-o
Das wird dir die Simulation sauber zerhageln. Denn bei jeder Änderung
eines dieser Signale müsste der Prozess neu berechnet werden.
Was du wolltest war wahrscheinlich sowas:
Hi,
DANKE!!
hm... ja stimmt mit dem unsigned, hab mir noch mal die Definiton vom
Wertebereich angeschaut. So aber jetzt, ist es jetzt eingermaßen ok was
ich mache?
-> Das ich von std_logic_vector über unsigned auf integer wandle damit
rechne und dann wieder zurückwandle??
-> Und wie ist es jetzt mit dem Teilen und den bits wegschneiden,
angenommen ich würde ja mit 4 Teilen also müsste ich die letzten 2 bits
wegschneiden...
Da mein Ausgang 12 bit breit ist, und mit dem Wegschneiden ja 2 bzw. 3
bits fehlen?
Oder da ich ja mit Integerwerten teile, kriege ich auch ein Integerwert
der diesen dann in ein std_logic_umwandelt und muss somit am ergebnis
nichts wegschneiden?
Gruß
> Und wie ist es jetzt mit dem Teilen und den bits wegschneiden,
Die Bits schneidest du schon mit /4 bzw. /8 weg.
>>> summe : integer range 0 to 2**12-1;
Die summe sollte natürlich um diese 2 bzw. 3 Bits breiter sein:
summe : integer range 0 to 2**15-1;
> Das ich von std_logic_vector über unsigned auf integer wandle damit> rechne und dann wieder zurückwandle??
Das passt. Nur über die Wertebereiche mußt du dir (wie gesagt) Gedanken
machen. Wenn du das nicht willst, dann schreibst du einfach mal:
summe : integer;
Dann darf der Synthesizer selber rausfinden, was er braucht. Du hast
aber in der simulation keine Kontrolle, wenn die Zahl mal überläuft...
ergebnis<=to_unsigned(summe/2,ergebnis'length);-- teilen nur durch Zweierpotenzen!!
51
REG_AUSGANG<=std_logic_vector(ergebnis);
52
53
endBehavioral;
Was mich jetzt stuzig macht ist wenn ich das so eingebe dann kommt am
Ausgang(Oszi) für ein rechtecksignal ein sagen wir mal ein abgestutzes
rechtecksignal.
Wenn ich aber statt
1
ergebnis<=to_unsigned(summe/2,ergebnis'length);
2
..
3
ergebnis<=to_unsigned(summe,ergebnis'length);
und dafür oben die
1
((I2+I1)/2);
mache kommt dann ein schöner gegläteter Rechteckraus ...
Ich dacht ich hätte es verstanden aber... :(
Ich mein wenn ich das bei dem integerwerten mache und sie addiere und
dann durch 2 teile bekomme ich ja ein integerwert der dann wieder in ein
std_logic_vector gewandelt wird => und das mach ja sinn für mich...
aber wenn ich das so mache das ich dann summe/2 oder 4 mache also laut
der Erklärung so die bits wegschneide... kommt da was komsiches raus...
hm...
M. schrieb:
> Ich dacht ich hätte es verstanden aber... :(
Das wird das Problem sein:
summe : integer range 0 to 2**12-1;
Du schneidest führende Stellen deiner Summe ab.
Mach daraus:
summe : integer;
Hallo,
danke danke für die Tipps die ganze Zeit!
Ich hab jetzt mal den Code abgespeckt und hab auf euere Tipps gehört und
hab die Zwischenstände reduziert und den Mittelwert über ein counter
gemacht. Was haltet ihr davon?
@ Über integer range 0 to 2** 12-1 hab ich nochmal nachgedacht, also
wenn ich durch 8 teile müsen 3 stellen von meinem vector weg.Somit muss
ich den hilfsvector um diese 3 stellen erweitern so das nur die unteren
BITS (LSB) weggeschnitten werden und am ende die summe trotzdem 12
ergibt oder? . wenn ich durch 2 teile => 13-1, druch 4 teile => 14-1
durch 8 teile =>16-1 ... oder ?
Hier mal der Code
ergebnis<=to_unsigned(summe_max/4,ergebnis'length);-- teilen nur durch Zweierpotenzen!!
43
44
REG_AUSGANG<=std_logic_vector(ergebnis);
45
46
endBehavioral;
Zum eigentlichen Problem der Flankenerkennung, hatte ich ja erwähnt das
ich das eventuell über schwellen mach wollte. Dies hatte auch geklappt
aber in dem Bereich der Schwelle ist nicht nur die fallende Flanke, die
haben will, sondern auch die Steigenede. Somit wurde mir 2 mal ein
Signal ausgegben, ich will aber das er die steigende ignoriert und nur
auf die fallende reagiert. Deshalb hatte ich auch mit
1
not
gearbeitet da nur einmal eine Bedingung vorkommen kann in dem die
fallende Flanke anfängt.
Jetzt wurde mir nahegelegt das damit nicht arbeiten soll... und weiß
jetzt nicht wie ich die steigende ignorieren soll...
M. schrieb:
> Zum eigentlichen Problem der Flankenerkennung, hatte ich ja erwähnt das> ich das eventuell über schwellen mach wollte.
Also doch ein Schmitt-Trigger?
1
process(CLK)
2
begin
3
iffalling_edge(CLK)then
4
5
fallende_flanke<='0';
6
7
ifREG_IN>schwelle_obenthen
8
zustand<='1';
9
endif;
10
ifREG_IN<schwelle_untenthen
11
zustand<='0';
12
ifzustand='1'then
13
fallende_flanke<='1';
14
endif;
15
endif;
16
17
endif;
18
endprocess;
Damit bekommst du einen Impuls, wenn die fallende Flanke kam.
Die Grenzen legst du so weit entfernt, dass Rauschen den Schmitt-Trigger
nicht beeinflusst bzw. schalten lässt.
Danke, für den Tipp, hat auch geklappt, wobei ich denke das er mir die
steigende Flanke erkennt, aber da muss ich noch mit den Grenzen spielen!
Vielen Dank!
Gruß
Zusätzliche Frage:
Wenn ich auf die Flanke aber nur in bestimmten Zeitintervallen reagieren
will, also ich erkenne vom Signal die Flanke und dann soll er für z.B
500us nichts machen auch wenn sgignale kommen und dann erst wieder
erkennen.
Ich hab mir gedacht es über ein Counter zu machen der quasi jedes mal
hochgezahlt wird wenn eine fallende flanke vorliegt, und dann nur wenn
der counter einen bestimmten wert hat gibt ich ein Signal am Ausgang.
Was hlatet ihr von der Idee?
Gruß
> in bestimmten Zeitintervallen ...> ... es über ein Counter zu machen ...
Richtig: Zeiten werden in FPGAs mit Zählern gemacht.
Ich würde einen (sättigenden) Zähler nehmen, den bei einer erkannten
Analogsignalflanke zurücksetzen und dann mit jeder Taktflanke des
Mastertakts um 1 hochzählen. Wenn der Endwert erreicht ist, dann ist die
Flankenerkennung wieder scharf. Und mit der nächsten erkannten
Analogsognalflanke ghet das Spiel von vorne los.
> Wenn ich auf die Flanke aber nur in bestimmten ...> ... jedes mal hochgezahlt wird wenn eine fallende flanke vorliegt
Du mußt aufpassen, dass du die Flanke nicht mit der Flanke verwechselst.
Für mich ist eine Flanke die Taktflanke innerhalb des FPGAs. Such mal
nach einem geeigneten Namen für die Änderung des Analogsignals (z.B.
Sprung).
if(S0>"101001100101")then-- OBERE SCHWELLE HIER 65% VOM AD BEREICH
7
zustand<='1';
8
endif;
9
if(S0<"011001100110")then-- UNTERE SCHWELLE HIER 40% VOM AD BEREICH
10
zustand<='0';
11
ifzustand='1'then
12
sprung<='1';
13
endif;
14
endif;
15
elsifsprung='1'then
16
cnt<=0;
17
else
18
cnt<=cnt+1;
19
endif;
20
endif;
21
endprocessTrigger;
> ...(sättigenden) Zähler nehmen, den bei einer erkannten>Analogsignalflanke zurücksetzen ...
mit zurücksetzen meintest du schon den counter auf null wieder zu setzen
und nicht um eins ab zu ziehen.
ifcnt<5then-- den Zähler einfach mal laufen lassen
5
cnt<=cnt+1;
6
endif;
7
ifcnt=5then
8
if(S0>"101001100101")then-- OBERE SCHWELLE HIER 65% VOM AD BEREICH
9
zustand<='1';
10
endif;
11
if(S0<"011001100110")then-- UNTERE SCHWELLE HIER 40% VOM AD BEREICH
12
ifzustand='1'then-- fallende Analogflanke
13
cnt<=0;-- Zähler zurücksetzen
14
endif;
15
zustand<='0';
16
endif;
17
endif;
18
endif;
19
endprocessTrigger;
> mit zurücksetzen meintest du schon den counter auf null wieder> zu setzen und nicht um eins ab zu ziehen.
Es gibt Zurücksetzen (auf 0), Laden (mit einem bestimmten Wert),
Inkrement (+1) und Dekrement (-1).
Hallo,
ok hier mal der engültige code der auch soweit funktioniert
1
Trigger:process(REGISTER_CLK)
2
begin
3
iffalling_edge(REGISTER_CLK)then
4
ifcnt<8399then
5
cnt<=cnt+1;
6
endif;
7
ifcnt=8399then
8
if(S0>"101001100101")then-- OBERE SCHWELLE HIER 65% VOM AD BEREICH
9
zustand<='1';
10
endif;
11
if(S0<"011001100110")then-- UNTERE SCHWELLE HIER 40% VOM AD BEREICH
12
ifzustand='1'then-- FALLENDE ANALOFFLANKE
13
cnt<=0;
14
endif;
15
zustand<='0';
16
endif;
17
endif;
18
endif;
19
endprocessTrigger;
20
21
Aus:process(REGISTER_CLK)
22
begin
23
iffalling_edge(REGISTER_CLK)then
24
ifcnt>0andcnt<100then
25
REG_AUSGANG<="000000000000";
26
else
27
REG_AUSGANG<="111111111111";
28
endif;
29
endif;
30
endprocessAUS;
ABER:( Ein kleiner Problem hab ich: Ich möchte nach einer erkannten
Flanke das Signal für genau 420us nicht anschauen. Also ich hab ein
clocksignal mit 20 MHZ, also hab ich alle 0,05 us ein Takt, 420/0,05
sind 8400 werte und deswegen der counter bis 8399. Wenn ich es aber am
Oszzi messe sind es genau 440us und somit 20us zu viel also 400
Taktwerte zu viel... wieso? :(
Was genau hast du gemessen?
Dein Code wartet 420us, dannach wartest du auf die nächste fallende
Flanke am ADC, dannach wartest du wieder 420us usw...
Ich nehme an, du hast an REGISTER_OUT gemessen, da eine Periodendauer
von 420 us zu messen wäre quasi Zufall, denn dann müsste die ADC Flanke
jedesmal genau dann kommen, wenn der Trigger gerade wieder scharf
geworden ist.
M. schrieb:
> if cnt < 8399 then> cnt <= cnt+1;> end if;> if cnt = 8399 then> ...
Warum so kompliziert? Schmeiss' doch das Signal 'zustand' komplett raus
und mache anstelle der beiden 'if cnt <' bzw. 'if cnt =' daraus ein
normales 'if'-'else'-'end if'. Und dann den reset des counters in den
Zweig wo dein Maximalwert erreicht ist. Macht den Code um 50% kuerzer
und besser lesbar
Hallo,
sorry mein Fehler, ne des passt schon so. Mein denkfehler war, dass er
innerhalb von den 420us auf nichts reagiern soll. So und nach den 420us
kamm die nächte flanke erst nach 20us und daher kam ich auf 440us. :)
Danke
Gruß
berndl schrieb:
> Schmeiss' doch das Signal 'zustand' komplett raus
Wie unterscheidet man dann zwischen einer fallenden Flanke (vom ADC) und
einem statischen Low-Pegel?
na, also ich verstehe den Code oben so, dass nach einem vom Counter
vorgegebenen Warteintervall wenn dann die Schwelle groesser als
haumichblau ist der Counter von neuem los laeuft. Und das 'if schwelle >
xxx' kann man ja in den else-Zweig reinschreiben (counter also auf
Endwert und bleibt da auch).
So wie der Code jetzt ist, werden im selben Prozess FFs generiert, d.h.
die Abarbeitung der folgenden Zustaende wird immer um einen Clock
verzoegert. Macht es meiner Meinung nach schwerer lesbar/verstehbar. Da
sind fuer meinen Geschmack halt ein paar Sachen vermantscht die
eigentlich nicht zusammen gehoeren...
berndl schrieb:
> ich verstehe den Code oben so, dass nach einem vom Counter> vorgegebenen Warteintervall wenn dann die Schwelle groesser als> haumichblau ist der Counter von neuem los laeuft.
Nicht ganz:
Nach einer Wartezeit wird auf die nächste fallende Flanke gewartet.
Das Signal "zustand" speichert den Wert eines Schmitt-Triggers.
Wichtig ist denke ich, dass auf die fallende Flanke gewartet wird und
bei konstantem Pegel nicht getriggert wird.
Den 2. Vorschlag find ich aber auch gut, man kann wirklich ein
if-then-else draus machen :)
ok, hab' ich jetzt auch bemerkt...
Aber dann wuerde ich den Schmitt-Trigger in einen eingenen Prozess
verpacken. So ist es m.M. wirklich unuebersichtlich...
M. schrieb:
> Zusätzliche Frage:>> Wenn ich auf die Flanke aber nur in bestimmten Zeitintervallen reagieren> will, also ich erkenne vom Signal die Flanke und dann soll er für z.B> 500us nichts machen auch wenn sgignale kommen und dann erst wieder> erkennen.>> Ich hab mir gedacht es über ein Counter zu machen der quasi jedes mal> hochgezahlt wird wenn eine fallende flanke vorliegt,
Ich würde nicht den Haupttakt nehmen. Für solche Fälle habe ich in
meinen Designs immer einen 1µs Tick. Also ein Enable-Signal, dass einmal
pro µs aktiv wird.
> und dann nur wenn> der counter einen bestimmten wert hat gibt ich ein Signal am Ausgang.> Was hlatet ihr von der Idee?
Dann musst du hier nur bis 500 zählen und nicht bis 20*500.
Tom
Hallo,
ja den code muss ich wirklich noch etwas netter umgestalten, da er aber
funktioniert reicht mir das mal für Testzwecke.
Was mich aber noch stört ist folgendes. Ich möchte als nächstem Schritt
wenn eine Fallende Flanke erkannt wurde , als Antwort eine z.B
E-kunktion fahren. Die E-Funktion habe ich mir im coregenerator als
12bit breit und auf 1023 stellen mittels .coe file erstellt und als
componente implementiert.
Zum test hab ich mal die Efunktion direkt ohne was dazwischen auf dem
Ausgang gegeben um zu schauen obs auch passt.
So dann wollte ich wie oben schon erwähnt als Antwort auf mein Signal
geben.
Dazu
1
Aus:process(REGISTER_CLK)
2
begin
3
iffalling_edge(REGISTER_CLK)then
4
ifcnt>0andcnt<1023then
5
REG_AUSGANG<=Efunk;
6
else
7
REG_AUSGANG<="111111111111";
8
endif;
9
endif;
10
endprocessAUS;
so umgeschrieben. Wenn ich mich auf den cnt beziehe dann habe ich
festgestellt das ich auch ein Wertebereich von 1023 definieren muss um
die Efunktion darzustellen. Meine Frage ist, kann das so sein? Ist meine
process für Ausgabe korrekt.
Zur Efunktion : 12 bit, 1023 tief und lass es mit jedem Takt ausgeben
M. schrieb:
> wie würde ich vor der fallenden Flanke die maximale Amplitude auch noch> dazu erkennen, die ich dann mit meiner Antwort mulitpliziere?
????
Hallo,
ich meine ich gebe ja ein Impuls. Dieser Impuls ist in der Amplitude
variabel, diese Ampliutde möchte ich auch noch erkennen, also die
Fallende Flanke vom Impuls, (was ja schon geht) und auch noch die
maximale Amplitude von diesem Signal bzw. Impuls... irgendwie denk ich
an das Schieberegister (was ihr nicht so effektiv findet) und irgendwie
ein Vergleich machen...aber es fällt mir so keine Idee ein.
Und noch mals zum Ausgang, passt es so mit dem cnt als quasi Enable
signal?
Gruß
Hallo,
eine Frage hätte ich zur Flankenerkennung und zwar :
1
ifREG_IN>schwelle_obenthen
2
zustand<='1';
3
endif;
4
ifREG_IN<schwelle_untenthen
5
zustand<='0';
Wieso wird hier nur die fallende Flanke erkannt und nicht auch noch die
steigende Flanke? Denn REG_IN > schwelle_oben trifft doch 2 mal zu bei
einem rechteck-Impuls? genaus so wie REG_IN < schwelle_unten 2 mal
zutrifft oder wie soll man das verstehen?