首页 文章

vhdl中信号的边缘检测

提问于
浏览
1

我是VHDL的新手,我有一个按钮,我想在按下时检测它的信号,这意味着我想在按下时检测信号按钮的上升沿?我做了研究,我发现的所有内容都是关于检测clk的上升边缘 .

我的问题是当按下按钮时,按钮的信号变为1并保持在1直到另一个甚至发生,所以当按钮的信号升高时,我会更多?

谢谢

2 回答

  • 1

    您在惯用英语中的问题:

    我是VHDL的新手,并且有一个按钮,我想在按下时将其检测为上升沿 . 我做了一些研究,我发现的所有内容都是关于检测时钟的上升沿 . 当按下按钮时,按钮的信号变为“1”并保持在“1”直到另一个事件发生 . 如何检测按钮上升沿事件?

    这不是VHDL问题,而是数字设计问题 . VHDL用于实现VHDL解决方案 .

    请参阅sonicwave对问题VHDL - Incrementing Register Value on Push Button Event的回答,该问题提供了边缘检测器 .

    但是,对于tens of milliseconds(可能产生多个事件的Maxim网络文章),可能会发生开关反弹,这取决于开关,并且纠正措施还取决于采样时钟速率 .

    Figures 1 and 2 from Maxim link

    请注意,Maxim网页文章提到薄膜开关在新的时候可以弹跳,随着时间的推移会降低,并且弹跳特性不可重复 .

    一些FPGA供应商在按钮之间提供施密特触发缓冲器,然后声称膜瞬时开关被“去抖” . Maxim网站文章声称薄膜开关在其使用寿命期间可能无法保持清洁 . 这些和其他类型的瞬时开关可能需要去抖动 .

    debouncing

    当FPGA板未提供去抖动时,想法是以数字方式过滤掉所有这些反弹并生成单个事件,显示按钮已被按下 . 这需要一个时钟 .

    first get the button signal into your clock domain

    这需要亚稳态滤波,这是通过最小化两个连续触发器之间的延迟来实现的,以在第一触发器看到 Build 或保持时间违规时最大化对第一触发器的亚稳态区域内发生的事件的免疫力 .

    第一个触发器的输入是按钮信号,第二个触发器的输入是第一个触发器的输出 .

    第二触发器的输出处于时钟域,当不超过表示由两个触发器之间的路由延迟加上触发器的亚稳态恢复时间组成的时钟速率时,亚稳态自由 .

    触发器的亚稳态恢复时间通常由FPGA中的最大时钟速率周期表示 .

    filtering out bounces

    当按钮无效时,将亚稳态过滤按钮信号输入计数器作为重置 . 当您松开按钮时,计数器将被清除 .

    计数器的大小取决于时钟频率和开关弹跳的长度,您可能需要几十毫秒 .

    终端计数表示有效的按钮事件,也用于停止计数器 . (终端计数FALSE是计数器的启用) .

    计数器停止以提供单个按钮事件 .

    另请注意,当按钮输入为亚稳态滤波时,它将充当同步复位 .

    Edge detection

    使用触发器完成边沿检测,其中终端计数信号作为输入和两个输入门,其输入的门的类型和极性可用于选择事件的哪个边缘(可能都带有XOR门)检测 . 一个来自触发器的门输入,另一个来自计数器的终端计数 .

    如果您认为FPGA板设计能够充分提供去抖动,则可以在不使用去抖动计数器的情况下将亚稳态滤波和边缘检测结合起来 .

    Maxim's application note

    如果你有一个商业化 生产环境 的FPGA板,你不必担心数字信号电平之外的电压瞬变,Maxim的文章正在向电路板设计人员宣传它们的保护器件 .

    该网络文章提供了关于开关反弹和反弹波形的权威参考 .

    FPGA board vendors

    一些FPGA板供应商提供去抖电路参考设计代码 . 他们这样做是因为计数器大小取决于参考时钟速率,并且可能使用的时钟由DPLL导出 .

  • 3

    取决于您是否需要对元稳定性进行安全检查,或者不要制作移位寄存器并在时钟上移动输入信号并查看是否存在差异 . 下面的代码非常简单,并考虑到您的系统中有一个时钟 .

    signal edge_detect : std_logic_vector( 1 downto 0 );
    
    process (clk_i) is
    begin
      if rising_edge(clk_i) then
        edge_detect <= edge_detect(0) & input_signal;
        if edge_detect = "01" then
          -- do stuff on rising_edge
        elsif edge_detect = "10" then
          -- do stuff on falling_edge   
      end if;
    end process;
    

    但是,如果你遇到误报问题,你可能还需要考虑信号的上升/下降时间与时钟的关系 .

相关问题