簡體   English   中英

fpga 中的彈跳效果 vhdl

[英]Boucing effect vhdl in a fpga

我正在實習,我的公司希望我為 fpga 學習 vhdl。 我正在使用 lattice diamond 來編碼和編譯我的項目並使用 questasim 進行模擬。 我還有一個用於訓練的小板:Lattice 的 MachXO3LF。

我做了一個項目:當我按下一個按鈕時,一個 LED 燈亮了 2 秒然后變暗。 (在模擬中工作,但由於彈跳效果而使用卡片。

我的導師給了我一個新項目:編寫代碼和測試台以避免彈跳效應,當我按下按鈕時,LED 點亮 2 秒,當我再次按下按鈕時,10 秒內沒有任何動作。

我不知道如何用我的起始代碼避免彈跳效果....彈跳效果是錯誤觸發或多次觸發的結果,例如多次按下按鈕

這是我的代碼

use ieee.std_logic_1164.ALL;
use ieee.numeric_std.ALL;


entity bouton_led_debounce is 
    Port    (btn    : in std_logic;
             reset  : in std_logic;
             clock  : in std_logic;
             led    : out std_logic
             );
end bouton_led_debounce;

architecture Behavioral of bouton_led_debounce is

signal m1       : std_logic := '1';
signal m2       : std_logic:= '1';
signal int      : std_logic:= '1';
signal buffer_led   : std_logic := '1';
signal cptr     : std_logic_vector (27 downto 0) := (others => '0');

begin   

    process(clock,reset)
    begin
        if(reset = '0') then
            buffer_led  <= '1';
            m1      <= '1';
            m2      <= '1';
            int     <= '1';
            cptr        <= (others => '0');
        elsif rising_edge(clock) then
        
            buffer_led <= '1';
            
            m1  <= btn;
            m2  <= m1;
            int <= m2;
            
            if( (int = '1') and (m2 = '0') ) then
                cptr <= (others => '0');
                cptr(0) <= '1';
                buffer_led <= '0';
            end if;
                    
            if( unsigned(cptr) /= 0) then
                cptr <= std_logic_vector(unsigned(cptr)+1);
                buffer_led  <= '0';
            end if;

            if( unsigned (cptr) = (24000000-1) )then
                cptr <= (others => '0');
            end if;
        end if;
    end process;
    
    led <= buffer_led;

end Behavioral;

還有我的測試台:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;


entity bouton_led_debounce_tb is
end bouton_led_debounce_tb;

architecture Behavioral of bouton_led_debounce_tb is

    component bouton_led_debounce is
        port(   btn     : in STD_LOGIC;
            reset   : in STD_LOGIC;
            clock   : in STD_LOGIC;
            led     : out STD_LOGIC);
    end component;


    signal btn : STD_LOGIC := '1' ;
    signal led : STD_LOGIC;
    signal reset : STD_LOGIC := '1';
    signal clock : STD_LOGIC := '0';

begin
    uut: bouton_led_debounce
        port map(
        btn => btn,
        led => led,
        clock => clock,
        reset => reset);
        

btn_sti : process
begin
    btn <= '1'; 
    wait for 500 ns;
    btn <= '0'; 
    wait for 50 ns;
    btn <= '1'; 
    wait for 30 ns;
    btn <= '0'; 
    wait for 50 ns;
    btn <= '1'; 
    wait for 30 ns;
    btn <= '0'; 
    wait for 30 ns;
    btn <= '1';
    wait;
end process btn_sti;

rst_sti : process
begin
    reset <= '1'; 
    wait for 1 us;
    reset <= '0'; 
    wait for 1 us;
    reset <= '1'; 
    wait;
end process rst_sti;


clock_sti : process
begin
    clock <= '0'; 
    wait for 83.33 ns;
    clock <= '1'; 
    wait for 83.33 ns;
end process clock_sti;
    
end Behavioral;

對您的設計的一些評論

buffer_led  <= '1';

我假設你的 LED 是低電平有效驅動的? 盡管如此,對於曾經閱讀過您的代碼的人來說,這可能並不明顯,應該進行相應的處理。 在你的情況下,因為你從來沒有讀過buffer_led我會用這個信號作為邏輯信號的表示並做

led <= not(buffer_led);

反而。

我在您的剪輯中沒有看到任何按鈕反彈。 你做什么

m1  <= btn;
m2  <= m1;
int <= m2;

輸入同步完全沒問題,但與去抖動無關。 正如評論中提到的,去抖有不同的 forms,一個相當簡單的方法是降低按鈕的采樣率。 例如,創建一個頻率為 1kHz 的啟用脈沖並僅在啟用時檢查,您可以在您的過程中執行此操作。

if clken_1kHz then
  m1 <= btn;
  m2 <= m1;
  if m1 = '1' and m2 = '1' then
    int <= '1';
  else
    int <= '0';
  end if;
end if;

使用上面的代碼片段,如果相隔 1ms 的樣本m1m2都評估為 1 ,則int信號只會變為1 當然,這遠非完美,還有更復雜的去抖動變體,但它肯定會改善你的情況。 您還可以調整采樣率,將 1kHz 降低到例如 10Hz 以獲得更多去抖動。

此外,使用最有意義的信號類型,大量轉換沒有附加價值,如果你有一個計數器,直接使用unsigned而不是來回轉換。 使用如上定義的int信號,您的代碼的 rest 將類似於

if int = '1' and cptr(cptr'left) = '0' then 
  led_buffer <= '1';
  cptr <= cptr-1;
else
  led_buffer <= '0';
  if int = '0' then
    cptr <= to_unsigned(24000000-1, cptr'length);
  end if;
end if;

通過向下計數而不是向上計數,我們可以簡單地檢查下溢,注意我們需要一個帶有一個額外位的計數器,但比較也只是 1 位而不是全尺寸。 因此,只要按下按鈕並且計數器沒有下溢,就會設置led_buffer ,一旦釋放按鈕或計數器已經過去,我們關閉 LED,如果按鈕也已釋放,我們可以安全地重置櫃台。

免責聲明:沒有測試過,只是頭腦編譯

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM