Hi, Ich rätsel schon ne ganze Zeit lang an einer Lösung für ein Problem... Ich taste ein einzelnes Signal mit diesen Werten bei 200MHz hab: 00010110111111111111001101000000000 Also ein Rechtecksignal wo nach der Einschalt- und Ausschaltflanke einige Spikes entstehen. Ich möchte daraus ein Signal erzeugen das bei jeder Flanke ein 1 clk langen Impuls erzeugt. Wie stell ich das am besten an?
wie wäre es mit aufsummieren. Eine 0 <> -1 eine 1 <> +1 bei überschreiten einer Tresholdgrenze den Impuls auslösen.
So mach ich das: z.B. 10er Schieberegister, Eingang wird mit clk (hier 200MHz) z.B. von rechts eingetaktet, wenn die 10 Bit = "0000011111" sind => flanke ='1'; (steigend) wenn die 10 Bit = "1111100000" sind => flanke ='1'; (fallend) Kurz in VDHL:
1 | :
|
2 | signal sr : std_logic_vector(9 downto 0); |
3 | signal flanke : std_logic; |
4 | signal pegel : std_logic; |
5 | :
|
6 | process (clk) |
7 | begin
|
8 | if rising_edge(clk) then |
9 | -- Schieberegister
|
10 | sr <= sr(8 downto 0) & eingang; |
11 | -- Flankenerkennung
|
12 | flanke <= '0'; |
13 | if (sr="1111100000") then flanke <= '1' end if; -- fallend |
14 | if (sr="0000011111") then flanke <= '1' end if; -- steigend |
15 | -- Entprellen
|
16 | if (sr="1111111111") then pegel <= '1' end if; -- high |
17 | if (sr="0000000000") then pegel <= '0' end if; -- low |
18 | end if; |
19 | end process; |
20 | :
|
@Michi: Du kannst aufeinanderfolgende Einsen und Nuller zu zählen und diese Zähler jeweils zurückzusetzen, wenn eine 0 resp. eine 1 erkannt wird. Nun weißt du, wenn z.B. der Einser-Zähler über eine festgelegte Schwelle kommt, dass eine Flanke da war. Lothar Miller wrote: > if (sr="1111100000") then flanke <= '1' end if; -- fallend > if (sr="0000011111") then flanke <= '1' end if; -- steigend Damit gehen dir aber einige Flanken verloren, z.B. 11111101000000 wird damit nicht erkannt.
Eigentlich beginnt die Flanke bei ersten wechsel von 0 nach 1 oder von 1 nach 0. Zu diesem Zeitpunkt muss ich auslösen, dabei dürfen aber die darauffolgenden Wechsel für eine gewisse dauer nicht erkannt werden.
Na ganz einfach:
1 | if (edge_switch = '0') then |
2 | if (sr = '1' AND sr_old = '0') then |
3 | flanke <= '1'; |
4 | edge_switch <= '1'; |
5 | else
|
6 | flanke <= '0'; |
7 | end if; |
8 | else
|
9 | edge_counter <= edge_counter +1; |
10 | if (edge_counter = "1111") then |
11 | edge_switch <= '0'; |
12 | end if; |
13 | end if; |
Ggf. könntest du im else-Zweig, wo der edge_counter hochzählt, auch noch die einsen zählen und nach einer bestimmten Anzahl Einsen die Erkennung wieder scharfmachen.
Die Flanke von 1 nach 0 habe ich vergessen, aber ist ja im Prinzip das Gleiche. ;) Ohne Haftung, da nur schnell hingeschmiert.
>Eigentlich beginnt die Flanke bei ersten wechsel von 0 nach 1 oder von 1 >nach 0. Zu diesem Zeitpunkt muss ich auslösen, dabei dürfen aber die >darauffolgenden Wechsel für eine gewisse dauer nicht erkannt werden. Das macht dich aber recht empfindlich auf irgendwelche Spikes oder Störungen... Also, dass ich das richtig sehe: ideales Signal: ooo11111111111111111ooooooooooooooo reales Signal: ooo1o11o111111111111oo11o1ooooooooo Flanke: ooo1oooooooooooooooo1oooooooooooooo Eine Frage, die sich mir stellt, ist dann: wieviele Takte zwischen zwei Flankenwechseln ist das Signal dann auch mindestens definiert 0 oder 1? Mit deinem exemplarischen Signal sind das ooo1o11o111111111111oo11o1ooooooooo 123111211234567890ab121211123456789 9 Takte o bzw. 11 Takte 1 > if (edge_counter = "1111") then sind 16 Takte und würde dann schon mal schiefgehen. Also, nehmen wir mal 8 Takte, und schalten sofort beim 1. Flankenwechsel. (Nur 1 FF lasse ich noch drin, zur Synchronisation ;-), besser is das)
1 | :
|
2 | signal sr : std_logic_vector(7 downto 0); |
3 | signal flanke : std_logic; |
4 | signal pegel : std_logic; |
5 | :
|
6 | process (clk) |
7 | begin
|
8 | if rising_edge(clk) then |
9 | -- Schieberegister
|
10 | sr <= sr(6 downto 0) & eingang; |
11 | -- Flankenerkennung
|
12 | flanke <= '0'; |
13 | if (sr="11111110") then flanke <= '1' end if; -- fallend |
14 | if (sr="00000001") then flanke <= '1' end if; -- steigend |
15 | -- Entprellen
|
16 | if (sr="11111111") then pegel <= '1' end if; -- high |
17 | if (sr="00000000") then pegel <= '0' end if; -- low |
18 | end if; |
19 | end process; |
20 | :
|
Und für Extremisten, die unvorhergesehene Ergebnisee lieben (oder bereits synchronisierte Signale haben), dieser Code:
1 | :
|
2 | signal sr : std_logic_vector(7 downto 0); |
3 | signal flanke : std_logic; |
4 | signal pegel : std_logic; |
5 | :
|
6 | process (clk) |
7 | begin
|
8 | if rising_edge(clk) then |
9 | -- Schieberegister
|
10 | sr <= sr(6 downto 0) & eingang; |
11 | -- Flankenerkennung
|
12 | flanke <= '0'; |
13 | if (sr="11111111" and eingang='0') then flanke <= '1' end if; -- fallend |
14 | if (sr="00000000" and eingang='1') then flanke <= '1' end if; -- steigend |
15 | -- Entprellen
|
16 | if (sr="11111111") then pegel <= '1' end if; -- high |
17 | if (sr="00000000") then pegel <= '0' end if; -- low |
18 | end if; |
19 | end process; |
20 | :
|
Man sieht: fast derselbe Code wie beim ersten Posting, nur die Auswertung ist ein wenig anders. Und ja: ich liebe Schieberegister :-)
Stefan Zimmermann wrote: > Welchen Baustein verwendest du? Das Verfahren ist unabhängig vom FPGA/CPLD. Wobei der Ressourcenverbrauch (Anzahl der verwendeten FF) für ein CPLD unangenehm hoch ist.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.