logo elektroda
logo elektroda
X
logo elektroda
REKLAMA
REKLAMA
Adblock/uBlockOrigin/AdGuard mogą powodować znikanie niektórych postów z powodu nowej reguły.

Moduł eliminacji drgań przycisku w VHDL - jak napisać poprawnie?

Latek 03 Gru 2005 13:19 3077 14
REKLAMA
  • #1 2049408
    Latek
    Poziom 11  
    Posty: 7
    Witam. Mam zrobić taki projekt w VHDL:

    http://www.ue.eti.pg.gda.pl/~wujek/lab_prog/zadania/zad_stoper.html

    i mam problem z napisaniem modułu zapobiegającego drganiu przycisku. Może mi ktoś pomóc go napisać? Oto moj kod kótry napisałem, pomiar działa ale niestety nie bardzo zapobiega temu drganiu i nie zawsze działa poprawnie:
    --{{ Section below this comment is automatically maintained
    --   and may be overwritten
    --{entity {pomiar} architecture {pomiar}}
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.all;
    
    entity dzielnik is
    	 generic (n : positive := 3000000);
    	 port(
    		 clk_in_dzielnik : in STD_LOGIC;
    		 rst_dzielnik : in STD_LOGIC;
    		 wyj: out STD_LOGIC
    	     );
    end dzielnik;
    
    --}} End of automatically maintained section
    
    architecture dzielnik of dzielnik is 
    
    begin
    	process(clk_in_dzielnik, rst_dzielnik)
     	variable Q1 : INTEGER RANGE 0 to n;
     	variable Q2 : INTEGER RANGE 0 to n;
     	begin
    	 	if (rst_dzielnik = '0') then
    		 
    		 	if clk_in_dzielnik'event and clk_in_dzielnik='1' then
    			if Q1 < n then
    				Q1 := Q1 + 1;
    				wyj <= '1';
    				Q2 := n;
            	else	  
              		Q2 := Q2 - 1;
    				wyj <= '0';
    				if Q2 = 0 then 
    					Q1 := 0;
    				end if;
            	end if; 
    		end if;
    
    	 else 
    		 wyj <= '0';	 
    	 end if;
    		
    end process;
    end dzielnik;
    
    
    
    library IEEE;
    use IEEE.STD_LOGIC_1164.all;
    
    
    -- Syntax for Synopsys FPGA Express
    -- pragma translate_off
    library unisim;
    use unisim.vcomponents.all;
    -- pragma translate_on
    
    entity czas is
    	 port(
    		 clk_in : in STD_LOGIC;
    		 data_out : out STD_LOGIC_VECTOR (6 downto 0);
    		 cpu_rst : out STD_LOGIC;
    		 ram_cs : out STD_LOGIC;
    		 rst : in STD_LOGIC;
    		 start_stop_button : in STD_LOGIC
    	     );
    end czas;
    
    
    
    architecture czas of czas is
        type Stan_Matrix is array(0 to 10) of std_logic_vector(6 downto 0);
    
    	signal filtr_out : STD_LOGIC;
    	signal liczStany_out : STD_LOGIC;
    	signal liczba_przycisniec : STD_LOGIC_VECTOR(1 downto 0);
    	
    	signal clk_d: std_logic;
    	signal clk_in2,clk_in3 : std_logic;
    	signal rst_buf,ram_cs_buf,cpu_rst_buf : std_logic;
    	signal wy : std_logic_vector(6 downto 0);
    
    
    
    	constant Stan:Stan_Matrix:=(
                "1110111", --0
                "0010010", --1
                "1011101", --2
                "1011011", --3
                "0111010", --4
                "1101011", --5
                "1101111", --6
                "1010010", --7
                "1111111", --8
                "1111011", --9
    	    "1101101"  --E
        );
    	
    	component dzielnik is
        port(
          clk_in_dzielnik, rst_dzielnik : in std_logic;
          wyj : out std_logic
          );
      end component;
    
    
    component BUFG
        port(
          O : out STD_ULOGIC;
          I : in STD_ULOGIC);
    end component;
    
    component IBUF is
        port(
          O : out STD_ULOGIC;
          I : in STD_ULOGIC);
    end component;
    
    component OBUF is
        port(
          O : out STD_ULOGIC;
          I : in STD_ULOGIC);
    end component;
    
    
    
    
    
    	
    	
    begin
    
    ibuf_1: ibuf port map (I => clk_in, O => clk_in3);
    bufg_1: bufg port map (I => clk_in3,O => clk_in2);
    ibuf_2: ibuf port map (I => rst, O => rst_buf);	
    dziel: dzielnik port map (clk_in_dzielnik => clk_in2, rst_dzielnik => rst_buf, wyj => clk_d );
    	
    
    		
        filtr: process(start_stop_button, clk_in2) is
        variable tlum: INTEGER range 0 to 3 := 0;
    	begin
    	if (clk_in2'event and clk_in2 = '1') then
    
            if (tlum = 3) then
                   if (start_stop_button = '0') then
                      filtr_out <= '1';
                   else
                      filtr_out <= '0';
                   end if;
    	if (start_stop_button = '1') then
    			      tlum := 0;
    	end if;
            
    
    	else
    			   if (start_stop_button = '0') then
    				   if (tlum = 3) then
    					   tlum := 3;
    				   else
                           tlum := tlum + 1;
    				   end if;
                   end if;
            end if;
        end if;
    	end process filtr;
    	
    	
    	liczStany: process(filtr_out, rst_buf) is
    	begin
    		if (rst_buf='1') then
          		liczba_przycisniec <= "01";
    		elsif (filtr_out'event and filtr_out='1') then
    			if liczba_przycisniec = "01" then
    				liczba_przycisniec <= "10";
    			elsif liczba_przycisniec = "10" then
    				liczba_przycisniec <= "11";
    			else 
    				liczba_przycisniec <= "01";
    			end if;
    		end if;
    	end process liczStany;
    	
    	liczCzas: process(clk_d, liczba_przycisniec) is
    	variable count: INTEGER range 0 to 10;
    	begin
    		if (clk_d'event and clk_d='1') then
    			if (liczba_przycisniec = "10") then
    				if count = 0 then
    					count := 1;
    					wy <= Stan(count);
    				elsif count = 1 then
    					count := 2;
    					wy <= Stan(count);
    				elsif count = 2 then
    					count := 3;
    					wy <= Stan(count);
    				elsif count = 3 then
    					count := 4;	
    					wy <= Stan(count);
    				elsif count = 4 then
    					count := 5;	
    					wy <= Stan(count);
    				elsif count = 5 then
    					count := 6;	
    					wy <= Stan(count);
    				elsif count = 6 then
    					count := 7;	
    					wy <= Stan(count);
    				elsif count = 7 then
    					count := 8;	 
    					wy <= Stan(count);
    				elsif count = 8 then
    					count := 9;	 
    					wy <= Stan(count);
    				else 
    					count := 10; 
    					wy <= Stan(count);
    				end if;
    			elsif (liczba_przycisniec = "11") then
    				wy <= Stan(count);
    			else
    				wy <= Stan(0);				
    				count := 0;
    			end if;
    		end if;
    	end process liczCzas;
    	
    	ram_cs_buf <= '1';
    	cpu_rst_buf <= '1';
    
    obuf_1: obuf port map (I => ram_cs_buf, O => ram_cs);
    obuf_2: obuf port map (I => cpu_rst_buf, O => cpu_rst);
    
    obuf_3: obuf port map (I => wy(0), O => data_out(0));
    obuf_4: obuf port map (I => wy(1), O => data_out(1));
    obuf_5: obuf port map (I => wy(2), O => data_out(2));
    obuf_6: obuf port map (I => wy(3), O => data_out(3));
    obuf_7: obuf port map (I => wy(4), O => data_out(4));
    obuf_8: obuf port map (I => wy(5), O => data_out(5));  
    obuf_9: obuf port map (I => wy(6), O => data_out(6));	 
    	 
    end czas;
    
  • REKLAMA
  • #2 2049665
    bolek
    Poziom 35  
    Posty: 4098
    Pomógł: 86
    Ocena: 298
    Nie znam sie na twoim VHDLu, ale jesli tyle kodu jest tylko do obsługi klawiszy to jużgo nie lubie. Ja wyznaje taką zasade, że co określony czas sprawdzam stan klawiszy, i jesli odczyta że naciśniety to sprawdzam jego poprzeni stan, jesli poprzednio nie był naciśniety to uznaje dany klawisz został naciśniety, zapamiętuje aktualny stan (do następnego sprawdzenia). Można powiedzieć że czas miedzy pomiarami to czułość na drgania styków.
  • Pomocny post
    #3 2049809
    sepher
    Poziom 19  
    Posty: 301
    Pomógł: 21
    Ocena: 4
    
    signal Q1, Q2, Q3 : std_logic;
     
    process(clock, RESET)
    begin
      if (RESET = '1') then
        Q1 <= '0';
        Q2 <= '0';
        Q3 <= '0';
      elsif (clock'event and clock = '1') then
        Q1 <= D_IN;
        Q2 <= Q1;
        Q3 <= Q2;
      end if;
    end process;
     
    Q_OUT <= Q1 and Q2 and (not Q3);
    


    D_IN to wejście, na którym chcesz wyeliminować drgania. Kod zaczerpnięty z przykładów ISE 7.1, u mnie działał :).
  • REKLAMA
  • #4 2050139
    Latek
    Poziom 11  
    Posty: 7
    a Q_OUT to zabezpieczone wyjście?
  • REKLAMA
  • #5 2050383
    sepher
    Poziom 19  
    Posty: 301
    Pomógł: 21
    Ocena: 4
    Tak jest :).
  • #6 2051527
    Latek
    Poziom 11  
    Posty: 7
    no to sorki ale z tego wynika ze Q_OUT nigdy nie będzie jedynką, chyba że ja czegoś nie rozumiem :/
  • #7 2052175
    Zbych_
    Poziom 25  
    Posty: 456
    Pomógł: 81
    Ocena: 6
    Latek napisał:
    no to sorki ale z tego wynika ze Q_OUT nigdy nie będzie jedynką, chyba że ja czegoś nie rozumiem :/


    Nie wiem czemu tak uważasz. Ten kawałek kodu to najzwyklejszy rejestr przesuwny (3-bitowy). Wyjście jest iloczynem tych trzech bitów (ostatni zanegowany), więc na wyjściu otrzymasz jedynkę, pod warunkiem, że wykryto dwa stany wysokie i jeden niski, czyli zbocze. Całość należałoby jeszcze napędzać zegarem o okresie dłuższym niż typowy czas drgań styków (1kHz, może 100Hz).
  • #8 2052316
    Latek
    Poziom 11  
    Posty: 7
    ja mam do dyspozycji zegar zewnętrzyny o 12MHZ, może być? :D ale mam wbudowany dzielnik częstotliwości który powodujeże ukłąd działa z F= 1Hz.

    ale w sumie nie przekonałeś mnie bo nie kumam czemu tam musi być zanegowany ostatni bit w tym rejestrze :?:
  • Pomocny post
    #9 2052453
    yego666
    Poziom 33  
    Posty: 2175
    Pomógł: 239
    Ocena: 564
    1HZ to troche za wolno, nawet dla flegmatyka :). Podziel te swoje 12MHz tak bys dostal okres okolo 10ms. Tyle mniej wiecej wynosi okres drgania kiepskich zestykow.
    Typowo wejsie styku robi sie tak, ze w stanie nieaktywnym na wejsciu masz logiczna '1'. Gdy przycisniesz przycisk, wejscie to zwierane jest do poziomu '0'. zatem by wykryc ze przez okres trzech cykli klawisz jest wcisniety, musisz albo negowac stan wejscia i uzyc iloczynu logicznego wyjsc przerzutnikow, albo nie negowac, ale wykrywac trzy zerowki, czyli uzyc sumy logicznej. na jedno wychodzi, tyle, ze w pierwszym przypadku aktywny odklocony sygnal przycisniecia klawisza bedzie mial poziom '1', a w drugim '0'. Mozesz to sobie zanegowac w prosty sposob, ale filozofii dzialania ukladu to nijak nie zmienia. przez trzy kolejne okresy sygnal musi byc stabilnie wcisniety by stan ten zostal wykryty. Dla pewnosci zobacz sobie jeszcze ten post : https://www.elektroda.pl/rtvforum/topic188396.html#922066 .

    pozdrawiam, yego
  • #10 2052475
    elektryk
    Poziom 42  
    Posty: 11029
    Pomógł: 439
    Ocena: 240
    Latek napisał:
    ale w sumie nie przekonałeś mnie bo nie kumam czemu tam musi być zanegowany ostatni bit w tym rejestrze :?:
    Po to żeby wykryć koniec impulsu, chociaż mnie też ten zapis się zbytnio nie podoba, ja bym to zrobić używając wektora. Dodatkowo trzeba dobreć liczbe przerzutników do częstotliwości zegara.
  • #11 2052839
    Latek
    Poziom 11  
    Posty: 7
    elektryk napisał:
    Dodatkowo trzeba dobreć liczbe przerzutników do częstotliwości zegara.

    jak mam F = 12MHZ to ile powinienem użyć przerzutników?
  • REKLAMA
  • Pomocny post
    #12 2053067
    yego666
    Poziom 33  
    Posty: 2175
    Pomógł: 239
    Ocena: 564
    Jesli jeszcze nie miales dzielenia w szkole, kup sobie jakis kalkulator.
    Jesli podzielisz za jego pomoca 12000000 przez wymagane 100 to powinno Ci wyjsc dziesietna wartosc potrzebnego wspolczynnika przez ktory trzeba dzielic owe 12 MHz . Nastepnie zamien ten wspolczynnik na wartosc dwojkowa i dobierz wartosc bliska wymaganej i zrob sobie dzielnik dwojkowy. Nie ma wielkiej roznicy czy bedziesz dzielil przez wieksza wartosc czy tez dasz wiecej przerzutnikow w ukladzie debouncingu. Mozesz tez zrobic dzielnik przez dokladna wartosc calkowita wyliczonego wspolczynnika, ale to moze kosztowac troche wiecej hardware'u.
    Na przyszlosc zastanow sie zanim zadasz pytanie ile to jest 12000000 / 100 .
  • #13 2053355
    Latek
    Poziom 11  
    Posty: 7
    no kaktycznie nie popisałem się. dzięki yego, Twoj poprzedni post dał mi do myslenia i juzzakumałem o co chodzi. to jest projekt laboratoryjny na studiach więc jak zaliczę to znaczy ze miałeś rację :)
  • #14 2063142
    Latek
    Poziom 11  
    Posty: 7
    no chłopaki, dzięki, układ zadziałał, najwiękse podziękowania dla yego666 !!!
  • #15 4336811
    Nefliqs
    Poziom 11  
    Posty: 25
    Ocena: 2
    I kto by pomyślał, że dwuletni temat może się do czegoś przydać:D

Podsumowanie tematu

✨ Dyskusja dotyczy problemu eliminacji drgań styków przycisku w projekcie VHDL, realizowanym na bazie stopera. Zaproponowano podejście polegające na okresowym próbkowaniu stanu przycisku i porównywaniu go z poprzednim stanem, co pozwala wykryć stabilne naciśnięcie. Przedstawiono przykładowy kod z rejestrem przesuwnym 3-bitowym, który filtruje drgania poprzez analizę kolejnych próbek sygnału wejściowego. Omówiono konieczność dostosowania częstotliwości zegara do czasu drgań styków – sugerowano okres około 10 ms, co odpowiada częstotliwości około 100 Hz. Wskazano, że zbyt wolny zegar (np. 1 Hz) jest nieefektywny. Podkreślono, że sygnał wejściowy przycisku zwykle jest aktywny niskim poziomem (0), a w stanie spoczynku wysoki (1), co wpływa na sposób detekcji i negację sygnału w logice eliminacji drgań. Zaproponowano użycie dzielnika częstotliwości do obniżenia sygnału zegarowego 12 MHz do odpowiedniej wartości. Dyskusja zakończyła się potwierdzeniem poprawności działania układu i wdzięcznością za pomoc.
Wygenerowane przez model językowy.
REKLAMA