library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.ALL; entity us_detection is Port (sys_clk : in std_ulogic; --Systemtakt 50MHz reset : in std_ulogic; --Reset-Signal clk_wpm : in std_ulogic; --WPM Takt übergabe us_pulses : out std_ulogic; --Übergabe kurzes Ultraschall Signal an press_duration us_data : in std_ulogic; --Dateneingangs-Pin GPIO1_35 (JP2) für Ultraschall-Erkennung, durchgereicht von Top Level Entity (TLE) über press_duration.vhd clk_us_360k : in std_ulogic; --Übergabe der Ultraschall-Abtast-Clock aus dem clock_divider über die TLE nach press_duration und darüber hier hin clk_us_40k : in std_ulogic; --Übergabe der Ultraschall-Akkumulations-Clock aus dem clock_divider über die TLE nach press_duration und darüber hier hin clk_400 : in std_ulogic; --Übergabe der 400Hz clock aus der clock_divider über die TLE us_switch : in std_ulogic); --Umschalten zwischen Button- oder Ultraschall-Eingabe, Switch[13] end us_detection; architecture behavioral of us_detection is signal us_signal_pulse : std_ulogic_vector (8 downto 0); --enthält kompletten 40kHz Scan-Frame mit 360kHz Abtastung, d.h. 9 Einzelwerten signal us_signal_period : std_ulogic; --gibt an, ob Duty Cycle des 40kHz Signals (entspricht hierbei der Signalstärke vor dem Komparator) hoch genug war, um Signal über die Dauer einer Peridode als stabil zu kennzeichnen. signal us_100_periods : std_ulogic_vector (99 downto 0); --akkumulierter Mittelwert der Signalauswertungen einzelner Perioden über (1/400Hz) = 100 Einzelperioden begin scansignalframe: process (reset, clk_us_360k, us_switch) --Der Prozess scansignalframe dient der Erfassung von Pegeln im Signal us_data (GPIO1_35 Port, liegt am Ausgang des Komparators) im Abstand von 1/360kHz begin if reset='0' or us_switch='0' then --Reset gedrückt? Dann alle Variablen zurück setzen. us_signal_pulse <= (others=>'0'); elsif clk_us_360k 'event and clk_us_360k = '1' and clk_us_360k'last_value = '0' then --us_360k clock Event führt zur Ausführung der nächsten Anweisung us_signal_pulse <= us_signal_pulse (7 downto 0) & us_data; --aktueller Pegel am digitalen Eingangspin GPIO1_35 (us_data zugewiesen) wird in das Schieberegister us_signal_pulse gespeist end if; end process; full_40k_period: process (sys_clk, reset, clk_us_40k, us_switch) --Der Prozess ermittelt den Duty Cycle des Signals 40kHz Signals, welches über us_data im Prozess scansignalframe ausgelesen wird variable count_ones : unsigned(4 downto 0) := "00000"; begin if reset='0' or us_switch='0' then --Reset gedrückt oder US-Modus abgeschaltet? Dann alle Variablen zurück setzen. us_signal_period <= '0'; us_100_periods <= (others=>'0'); elsif us_switch='1' then if clk_us_40k 'event and clk_us_40k = '1' and clk_us_40k'last_value = '0' then --us_40k clock Event führt zur Ausführung der nächsten Anweisung count_ones := (others=>'0'); --Zähler count_ones wird zurück gesetzt for i in 0 to 8 loop --Zähler count_ones wird genutzt, um alle mit 360kHz abgetasteten HIGH Level des us_data Signals innerhalb des Vektors us_signal_pulse zu finde, in dem die Signalpegeldurch scansignalframe abgelegt wurden if(us_signal_pulse(i) = '1') then count_ones := count_ones + 1; end if; end loop; if count_ones >= 1 and count_ones <= 5 then --werden mehr als 5 High Level detektiert, d.h. ist in einer 40kHz Periode (=25µs) für mindestens 16,667µs (=6*(1/360kHz)) ein HIGH-Level detektiert und ist kein Dauer-Pegel HIGH detektiert worden (wäre = 9)... us_signal_period <= '1'; --...wird die Signalperiode als OK qualifiziert... us_100_periods <= us_100_periods (98 downto 0) & us_signal_period; --...und diese korrekt übertragene 40kHz Signalperiode in den Speichervektor us_100_periods eingespeist else us_signal_period <= '0'; us_100_periods <= us_100_periods (98 downto 0) & us_signal_period; end if; end if; end if; end process; stable_40k_signal: process (reset, clk_400, us_switch) --der Prozess trifft die Aussage darüber, ob das 40kHz über einen Zeitraum von 1/400Hz ausreichend stabil ist, um an die Verarbeitung weitergeleitet zu werden variable count_ones : unsigned(6 downto 0) := (others=>'0'); begin if reset='0' or us_switch='0' then --Reset gedrückt? Dann alle Variablen zurück setzen. us_pulses <= '0'; elsif clk_400 'event and clk_400 = '1' and clk_400'last_value = '0' then count_ones := (others=>'0'); for i in 0 to 99 loop --Die Schleife zählt alle erfolgreichen Signalperioden innerhalb von 1/400Hz (bei 40kHz Signal entspricht das einer Summe von 100 Perioden) if(us_100_periods(i) = '1') then count_ones := count_ones + 1; end if; end loop; if count_ones >= 50 then --bei mehr als 50% erfolgreich übertragenen Signalperioden innerhalb von 1/400Hz (=2,5ms) gilt das Signal als stabil und setzt das Ausgangssignal us_pluses auf HIGH us_pulses <= '1'; else us_pulses <= '0'; end if; end if; end process; end behavioral;