VHDL:按钮去抖动(或不去抖动,视情况而定)

VHDL:按钮去抖动(或不去抖动,视情况而定),vhdl,fpga,xilinx,vivado,debounce,Vhdl,Fpga,Xilinx,Vivado,Debounce,我已经阅读了其他帖子,但似乎无法修复我的。我不熟悉VHDL,所以我相信这是一个简单的修复程序 简言之,按钮没有去抖动。代码编译并生成位流程序。在测试台中,按钮按下工作,但输出LED不会改变。在电路板上,按下按钮会使随机发光二极管亮起(我猜是因为反弹)。根据示意图,输入通过去抖动器 有人能确定这个问题吗?任何其他提示和提示都将不胜感激:) 谢谢 EDIT1:增加了上升沿(clk)。 另外请注意,当我按下任一按钮时,按下该按钮时,所有LED都会亮起 按钮计数器.vhd library IEEE;

我已经阅读了其他帖子,但似乎无法修复我的。我不熟悉VHDL,所以我相信这是一个简单的修复程序

简言之,按钮没有去抖动。代码编译并生成位流程序。在测试台中,按钮按下工作,但输出LED不会改变。在电路板上,按下按钮会使随机发光二极管亮起(我猜是因为反弹)。根据示意图,输入通过去抖动器

有人能确定这个问题吗?任何其他提示和提示都将不胜感激:)

谢谢

EDIT1:增加了上升沿(clk)。 另外请注意,当我按下任一按钮时,按下该按钮时,所有LED都会亮起

按钮计数器.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;
IEEE库;
使用IEEE.STD_LOGIC_1164.ALL;
使用IEEE.NUMERIC_STD.ALL;
实体按钮_计数器为
端口(时钟:在标准逻辑中;
btnU:标准逻辑中;
btnD:标准逻辑中;
led:输出标准逻辑向量(15到0);
结束按钮计数器;
按钮计数器的结构是
分量去抖器
端口(时钟:在标准逻辑中;
btn:标准逻辑中;
btn_clr:输出标准逻辑);
端部元件;
信号btnU\U clr:标准逻辑;
信号btnD\U clr:标准逻辑;
开始
去Bouncer_btnU:去Bouncer端口映射(clk=>clk,btn=>btnU,btn_clr=>btnU_clr);
去Bouncer_btnD:去Bouncer端口映射(clk=>clk,btn=>btnD,btn_clr=>btnD_clr);
过程(clk)
变量计数:整数:=0;
开始
如果(上升沿(clk)),则
如果(btnU_clr='1'),则计数:=计数+1;
elsif(btnD_clr='1')则count:=count-1;
如果结束;

led您忘记了
按钮计数器中的
上升沿

 process(clk)
    variable count : integer := 0;
    begin
        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 process;
我不确定,但我认为工具链会对此产生一些警告。所以请检查一下


而且您的测试台不包含任何时钟生成过程,因此您不会有时钟信号。也许这会让你相信你的设计是可行的(或者你是否忘记了帖子中的时钟信号?

在你的代码更新之后,还有几个问题:

  • 测试台上没有生成时钟

  • 测试台上的刺激(按钮按下)没有充分计时

  • 去抖动器不会为单个时钟生成启用

  • 为了便于设计验证的模拟,您的设计已修改为允许较慢的时钟(看起来您实际使用的是100 MHz时钟)。其思想是减少计算需求和显示波形存储

    前两点在测试台中讨论:

    ieee库;
    使用ieee.std_logic_1164.all;
    使用ieee.numeric_std.all;
    实体按钮\u计数器\u tb为
    结束实体按钮\u计数器\u tb;
    按钮计数器tb的结构是
    --注意:后缀_tb已被删除,反复键入很烦人
    信号时钟:标准逻辑:='0';--已添加默认值“0”
    信号btnU:std_逻辑;
    信号btnD:std_逻辑;
    信号led:标准逻辑矢量(15至0);
    组件按钮计数器
    泛型(--添加泛型
    CLKP:时间:=10纳秒;
    债务:时间:=6.5毫秒——去盎司时间支持不同的
    );                              -- 机械按钮/开关
    港口(
    clk:标准逻辑中;
    btnU:标准逻辑中;
    btnD:标准逻辑中;
    led:输出标准逻辑向量(15至0)
    );
    端部元件;
    恒定CLKP:时间:=12.5 us;——添加的长度刚好足以显示debounce
    固定负债:时间:=6.5毫秒;——补充
    开始
    时钟:--添加了时钟进程
    过程
    开始
    等待CLKP/2;
    clk 2秒然后--停止模拟
    等待
    如果结束;
    结束过程;
    受测试单元:
    按钮计数器
    通用映射(--添加了通用映射
    CLKP=>CLKP,
    债务=>债务
    )
    港口地图(
    时钟=>clk,
    btnU=>btnU,
    btnD=>btnD,
    发光二极管=>发光二极管
    );
    --刺激:
    --过程
    --开始
    
    --btnU_tb这个问题已经得到了很好的回答,但我想强调一下同步和去抖动的不同技术

    同步 对于同步,可以使用简单的缓冲器或链,避免为缓冲器或链中的每个阶段创建单独的信号/变量。通用常数可用于控制链的长度(至少2个):

    signal sync_buffer:std_logic_vector(sync_buffer_MSB downto 0);--N位同步缓冲器。
    ...
    同步缓冲区“0”);--N位同步缓冲器(最少2位)。
    别名sync_输入:std_逻辑是sync_缓冲区(sync_缓冲区\u MSB);--同步输入是同步缓冲区的MSB。
    恒定最大计数:自然:=去盎司周期/时钟周期;
    信号计数器:自然范围0到最大计数:=0;--指定范围以减少合成的位数。
    开始
    断言同步\u位>=2报告“同步缓冲区中至少需要2位。”;
    进程(时钟)
    可变边_内部:标准_逻辑:='0';
    可变上升_内部:标准_逻辑:='0';
    变量fall_internal:std_逻辑:='0';
    开始
    如果上升沿(时钟),则
    --同步异步输入。
    --sync_缓冲区的MSB是同步输入。
    
    sync\u buffer您的测试台似乎没有任何驱动
    clk
    ,这是故意的吗?是的,我可以确定问题。基于锁存器的计数器在启用时用作选通振荡器。至少有一个“位”被增量或减量反转。启用时会有一个反馈路径。有耽搁。工艺灵敏度列表不正确,模拟
    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;
    
     process(clk)
        variable count : integer := 0;
        begin
            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 process;
    
     process(clk)
        variable count : integer := 0;
     begin
            if(rising_edge(clk)) then
                ...
            end if;
     end process;