我已经阅读了其他文章,但似乎无法解决我的问题。我是VHDL的新手,所以我确定这是一个简单的修复。
简而言之,该按钮没有抖动。代码进行编译并生成位流程序。在测试台中,按下按钮即可工作,但输出LED不会改变。在板上,按一个按钮会使随机的LED点亮(我想是因为弹跳)。根据原理图,输入通过去抖动器。
任何人都可以识别问题吗?和任何其他提示和技巧总是很感激:)
谢谢!
编辑1:添加了riseing_edge(clk)。另请注意,当我按下任一按钮时,按下该按钮时,所有LED都会亮起。
button_counter.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity button_counter is
port( clk : in std_logic;
btnU : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (15 downto 0));
end button_counter;
architecture behavioral of button_counter is
component debouncer is
port( clk : in std_logic;
btn : in std_logic;
btn_clr : out std_logic);
end component;
signal btnU_clr : std_logic;
signal btnD_clr : std_logic;
begin
debouncer_btnU : debouncer port map (clk => clk, btn => btnU, btn_clr => btnU_clr);
debouncer_btnD : debouncer port map (clk => clk, btn => btnD, btn_clr => btnD_clr);
process(clk)
variable count : integer := 0;
begin
if (rising_edge(clk)) then
if(btnU_clr = '1') then count := count + 1;
elsif(btnD_clr = '1') then count := count - 1;
end if;
led <= std_logic_vector(to_unsigned(count, led'length));
end if;
end process;
end behavioral;
Debouncer.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity debouncer is
port( clk : in std_logic;
btn : in std_logic;
btn_clr : out std_logic);
end debouncer;
architecture behavioural of debouncer is
constant delay : integer := 650000; -- 6.5ms
signal count : integer := 0;
signal btn_tmp : std_logic := '0';
begin
process(clk)
begin
if rising_edge(clk) then
if (btn /= btn_tmp) then
btn_tmp <= btn;
count <= 0;
elsif (count = delay) then
btn_clr <= btn_tmp;
else
count <= count + 1;
end if;
end if;
end process;
end behavioural;
button_counter_tb.vhd
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
entity button_counter_tb is
end button_counter_tb;
architecture behavioral of button_counter_tb is
signal clk_tb : std_logic;
signal btnU_tb : std_logic;
signal btnD_tb : std_logic;
signal led_tb : std_logic_vector (15 downto 0);
component button_counter
port(clk : in std_logic;
btnU : in std_logic;
btnD : in std_logic;
led : out std_logic_vector (15 downto 0));
end component;
begin
UUT: button_counter port map (clk => clk_tb, btnU => btnU_tb, btnD => btnD_tb, led => led_tb);
process
begin
btnU_tb <= '0';
btnD_tb <= '0';
wait for 100ns;
btnU_tb <= '1';
wait for 100ns;
btnU_tb <= '0';
wait for 100ns;
btnU_tb <= '1';
wait for 100ns;
btnD_tb <= '1';
wait for 100ns;
btnU_tb <= '0';
wait for 100ns;
btnD_tb <= '0';
end process;
end behavioral;
刺激(按钮按下)在测试台中的时间不足
去抖动器不会为单个时钟产生
为了简化仿真进行设计
验证,您的设计已被修改为允许使用较慢的时钟(看来您实际上是在使用100 MHz时钟)。目的是减少计算需求并显示波形存储。
前两点在测试平台中解决:library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity button_counter_tb is
end entity button_counter_tb;
architecture behavioral of button_counter_tb is
-- NOTE: suffix _tb has been removed, it's annoying to type over and over
signal clk: std_logic := '0'; -- ADDED default value '0'
signal btnU: std_logic;
signal btnD: std_logic;
signal led: std_logic_vector (15 downto 0);
component button_counter
generic ( -- ADDED generic
CLKP: time := 10 ns;
DEBT: time := 6.5 ms -- debounce time supports different
); -- mechanical buttons/switches
port (
clk: in std_logic;
btnU: in std_logic;
btnD: in std_logic;
led: out std_logic_vector (15 downto 0)
);
end component;
constant CLKP: time := 12.5 us; -- ADDED just long enough to show debounce
constant DEBT: time := 6.5 ms; -- ADDED
begin
CLOCK: -- ADDED clock process
process
begin
wait for CLKP/2;
clk <= not clk;
if now > 2 sec then -- stop simulation
wait;
end if;
end process;
UUT:
button_counter
generic map ( -- ADDED generic map
CLKP => CLKP,
DEBT => DEBT
)
port map (
clk => clk,
btnU => btnU,
btnD => btnD,
led => led
);
-- STIMULI:
-- process
-- begin
-- btnU_tb <= '0';
-- btnD_tb <= '0';
-- wait for 100 ns;
-- btnU_tb <= '1';
-- wait for 100 ns;
-- btnU_tb <= '0';
-- wait for 100 ns;
-- btnU_tb <= '1';
-- wait for 100 ns;
-- btnD_tb <= '1';
-- wait for 100 ns;
-- btnU_tb <= '0';
-- wait for 100 ns;
-- btnD_tb <= '0';
-- wait; -- ADDED -- stops simulation
-- end process;
UP_BUTTON:
process
begin
btnU <= '0';
wait for 2 ms;
btnU <= '1'; -- first button press
wait for 0.5 ms;
btnU <= '0';
wait for 0.25 ms;
btnU <= '1';
wait for 7 ms;
btnU <= '0';
wait for 100 us;
btnU <= '1';
wait for 20 us;
btnU <= '0';
wait for 200 ms;
btnU <= '1'; -- second button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 250 ms;
btnU <= '1'; -- third button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 200 ms;
btnU <= '1'; -- second button press
wait for 20 us;
btnU <= '0';
wait for 20 us;
btnU <= '1';
wait for 6.6 ms;
btnU <= '0';
wait for 50 us;
btnU <= '1';
wait for 1 ms;
btnU <= '0';
wait;
end process;
DOWN_BUTTON:
process
begin
btnD <= '0';
wait for 800 ms;
btnD <= '1'; -- first button press
wait for 0.5 ms;
btnD <= '0';
wait for 0.25 ms;
btnD <= '1';
wait for 0.5 ms;
btnD <= '0';
wait for 1 ms;
btnD <= '1';
wait for 7 ms;
btnD <= '0';
wait for 100 us;
btnD <= '1';
wait for 20 us;
btnD <= '0';
wait for 200 ms;
btnD <= '1'; -- second button press
wait for 20 us;
btnD <= '0';
wait for 20 us;
btnD <= '1';
wait for 6.6 ms;
btnD <= '0';
wait for 250 ms;
wait;
end process;
end architecture behavioral;
信号名称的_tb
后缀已被删除(重复输入很麻烦)。>>
选择了一个时钟周期,并保证了反弹周期与时钟周期的比率,以允许“反弹”下降。刺激按钮的按下可以扩展,模拟可以任意扩展。请注意,确保按钮按下值跨越一个或多个时钟间隔。这些应允许通过修改
CLKP
来更改时钟周期。防抖动间隔DEBT可以修改以反映不同开关或按钮的使用,包括严重老化的薄膜开关。防抖动间隔是特定开关或按钮的机械特性的结果。传递这些通用常量可以实现一定程度的平台独立性。
第三点通过更改去抖动器来解决:
library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity debouncer is generic ( -- ADDED GENERICS to speed up simulation CLKP: time := 10 ns; DEBT: time := 6.5 ms ); port ( clk: in std_logic; btn: in std_logic; btn_clr: out std_logic ); end entity debouncer; architecture behavioural of debouncer is -- constant delay: integer := 650000; -- 6.5ms constant DELAY: integer := DEBT/CLKP; signal count: integer := 0; signal b_enab: std_logic := '0'; -- RENAMED, WAS btn_tmp signal btnd0: std_logic; -- ADDED for clock domain crossing signal btnd1: std_logic; -- DITTO begin CLK_DOMAIN_CROSS: -- ADDED process process (clk) begin if rising_edge(clk) then btnd0 <= btn; btnd1 <= btnd0; end if; end process; DEBOUNCE_COUNTER: -- ADDED LABEL process (clk) begin if rising_edge(clk) then -- if btn /= btn_tmp then -- REWRITTEN -- btn_tmp <= btn; -- count <= 0; -- elsif count = DELAY then -- btn_clr <= btn_tmp; -- else -- count <= count + 1; -- end if; btn_clr <= '0'; -- btn_clr for only one clock, used as enable if btnd1 = '0' then -- test for btn inactive state count <= 0; elsif count < DELAY then -- while btn remains in active state count <= count + 1; end if; if count = DELAY - 1 then -- why btn_clr '1' or 1 clock btn_clr <= '1'; end if; end if; end process; end architecture behavioural;
防抖器已修改为获得时钟域按钮值,该值用于重置和启用计数器
count
。输出btn_clr
名称保留不变,仅在一个时钟内为true,可以用作启用。
[CLKP
和DEBT
一起使用可允许更快的仿真执行,同时经过相同的仿真时间。注意,按钮输入的激活状态是硬编码的。它们将连接到可以指定输入极性的设备引脚。
对button_counter的修改将通用常量
CLKP
和DEBT
传递给去抖动器:
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity button_counter is generic ( CLKP: time := 10 ns; -- GENERIC CONSTANTS for faster simulation DEBT: time := 6.5 ms -- supports diffeent switches/buttons ); port ( clk: in std_logic; btnU: in std_logic; btnD: in std_logic; led: out std_logic_vector (15 downto 0) ); end entity button_counter; architecture behavioral of button_counter is component debouncer is generic ( CLKP: time := 10 ns; DEBT: time := 6.5 ms ); port ( clk: in std_logic; btn: in std_logic; btn_clr: out std_logic ); end component; signal btnU_clr: std_logic; signal btnD_clr: std_logic; begin debouncer_btnU: debouncer generic map ( CLKP => CLKP, DEBT => DEBT ) port map ( clk => clk, btn => btnU, btn_clr => btnU_clr ); debouncer_btnD: debouncer generic map ( CLKP => CLKP, DEBT => DEBT ) port map ( clk => clk, btn => btnD, btn_clr => btnD_clr ); process (clk) variable count: integer := 0; begin if rising_edge(clk) then if btnU_clr = '1' then count := count + 1; elsif btnD_clr = '1'then count := count - 1; end if; led <= std_logic_vector(to_unsigned(count, led'length)); end if; end process; end architecture behavioral;
运行测试台并显示各种波形将允许“放大”以显示两个去抖动器中的毛刺处理。通过时钟时钟周期和去抖动间隔通过设计层次结构的修改不是严格必要的。它们有助于仿真,此处将其用于设计验证。 (测试台中显示的刺激不能完全验证设计)。
通过使用通用默认设置(时钟频率为100MHz),该设计很有可能在目标平台上实施时能够正常工作。 (在去抖动器中选择了按钮输入的活动极性以支持原始实现。如果您怀疑按钮在增加或减少时会发生抖动,则可以增加DEBT值。)
如果特定的综合工具无法处理作为通用常量传递的
time
类型的值,则可以将CLKP
和DEBT
的各种声明转换为integer
类型,或者简单地传递最大计数。