> Deine Seite ist übrigens sehr informativ,
Dort sammle ich genau das Zeug, das ich selber von überall her immer
wieder brauche ;-)
> werde ich gleich am Wochenende mal durcharbeiten ;)
dann wirst du auch die Einsynchronisierung und Flankenerkennung finden.
> wait until rising_edge(clk)
> ... bei rising_edge von sig ...
Nein, du hast im Idealfall (und davon solltest du nicht unnötig
weggehen) nur einen Master-Takt im FPGA (so im Bereich 10-100MHz). Zu
diesem ist dein Design synchron. Alle Signale, die von aussen kommen,
werden erst über 2 FF-Stufen einsynchronisiert (Stichwort
Metastabilität) und dann intern verwendet. Am einfachsten geht das über
ein Schieberegister:
1 | signal sigsr : std_logic_vector(1 downto 0);
|
2 | :
|
3 | process begin -- Einsynchronisieren
|
4 | wait until rising_edge(clk);
|
5 | -- Schieberegister
|
6 | sigsr <= sigsr(0) & sig;
|
7 | end process;
|
sigsr(1) ist hier synchron zum FPGA-Takt.
Hier die kompakteste Variante für die Flankenauswertung:
1 | signal sigsr : std_logic_vector(2 downto 0);
|
2 | :
|
3 | process begin
|
4 | wait until rising_edge(clk);
|
5 | -- Schieberegister
|
6 | sigsr <= sigsr(1 downto 0) & sig;
|
7 | if (sigsr="100") then
|
8 | -- fallende Flanke von sig
|
9 | end if;
|
10 | if (sigsr="011") then
|
11 | -- steigende Flanke von sig
|
12 | end if;
|
13 | end process;
|
Hier kommt 1 FF als Pegelmerker dazu.
sigsr(2) merkt sich den alten Pegel vom einsynchronisierten sigsr(1),
und wenn z.B. das sigsr(2) = '1' ist und zudem sigsr(1) = '0', dann hat
sich der Pegel des Eingangssignals von 1 nach 0 gewechselt.
Ein fallende Flanke würde demnach mit
1 | if (sigsr(2)='1' and sigsr(1)='0') then
|
erkannt. Schöner liest und schreibt sich aber
Diese DCF-Geschichte könnte ich mir etwa so vorstellen:
- Mastertakt z.B. 50HMz
- Einsynchronisieren von sig
- einen sättigenden Zähler für 1 Sekunde
(wegen Erkennung von Sekunde 59)
- bei der steigenden Flanke von sig wird der Zähler zurückgesetzt
und der Index entweder auf 0 gesetzt (wenn der Zähler aufgelaufen ist)
oder hochgezählt
- bei der fallenden Flanke von sig wird geschaut,
wie weit der Zähler gelaufen ist und dementsprechend eine 0 oder 1
an den Index eingetragen
1 | -- Takt clk = 50MHz
|
2 | signal sigsr : std_logic_vector(2 downto 0);
|
3 | signal cnt : integer range 0 to 50000000 := 0;
|
4 | signal idx : integer range 0 to 58 := 0;
|
5 | signal bits : std_logic_vector(58 downto 0);
|
6 | signal bitsout : std_logic_vector(58 downto 0);
|
7 | :
|
8 | process begin
|
9 | wait until rising_edge(clk);
|
10 | -- Einsynchronisieren
|
11 | sigsr <= sigsr(1 downto 0) & sig;
|
12 |
|
13 | -- steigende Flanke von sig
|
14 | if (sigsr="011") then
|
15 | cnt <= 0;
|
16 | if (cnt=50000000) then -- Sekunde 59 war da?
|
17 | idx <= 0; -- ja: wieder von vorn
|
18 | bitsout <= bits; -- die gesammelten Daten uebergeben
|
19 | else
|
20 | if (idx<58) then -- nein: Index hochzaehlen
|
21 | idx <= idx+1;
|
22 | end if;
|
23 | end if;
|
24 | end if;
|
25 |
|
26 | -- fallende Flanke von sig
|
27 | if (sigsr="100") then
|
28 | if (cnt<7500000) then -- kurzer Impuls? Grenze 150ms
|
29 | bits(idx) <= '0'; -- ja: 0 eintragen
|
30 | else
|
31 | bits(idx) <= '1'; -- nein: 1 eintragen
|
32 | end if;
|
33 | end if;
|
34 |
|
35 | -- Zaehler hochzzaehlen (sättigend bei 50000000)
|
36 | if (cnt<50000000) then
|
37 | cnt <= cnt+1;
|
38 | end if;
|
39 | end process;
|
Das kann man durch den Multiplexer bits(idx) schön lesen, ich würde aber
zu Ressourcenschonung eher eine Schieberegisterlösung vorziehen:
1 | -- Takt clk = 50MHz
|
2 | signal sigsr : std_logic_vector(2 downto 0);
|
3 | signal cnt : integer range 0 to 50000000 := 0;
|
4 | signal bits : std_logic_vector(58 downto 0);
|
5 | signal bitsout : std_logic_vector(58 downto 0);
|
6 | :
|
7 | process begin
|
8 | wait until rising_edge(clk);
|
9 | -- Einsynchronisieren
|
10 | sigsr <= sigsr(1 downto 0) & sig;
|
11 |
|
12 | -- steigende Flanke von sig
|
13 | if (sigsr="011") then
|
14 | cnt <= 0;
|
15 | if (cnt=7500000) then -- Sekunde 59 war da?
|
16 | bitsout <= bits; -- die gesammelten Daten uebergeben
|
17 | bits <= (others=>'0'); -- Bit-Schiebegregister zuruecksetzen
|
18 | else
|
19 | end if;
|
20 | end if;
|
21 |
|
22 | -- fallende Flanke von sig
|
23 | if (sigsr="100") then
|
24 | if (cnt<20000000) then -- kurzer Impuls?
|
25 | bits <= '0'&bits(58 dowto 1); -- ja: 0 von links einschieben
|
26 | else
|
27 | bits <= '1'&bits(58 dowto 1); -- nein: 1 von links einschieben
|
28 | end if;
|
29 | end if;
|
30 |
|
31 | -- Zaehler hochzzaehlen (sättigend bei 50000000)
|
32 | if (cnt<50000000) then
|
33 | cnt <= cnt+1;
|
34 | end if;
|
35 | end process;
|
Was jetzt noch fehlt ist z.B. eine Fehlerbehandlung bei Bitfehler...
Aber da kannst du auf dem bits-Vektor leicht machen.