[英]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 的樣本m1
和m2
都評估為 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.