2013-07-19 105 views
0

我们使用OR1200作为我们的项目,我们希望为FPGA板的第8个按钮分配一个中断。这里是产生中断的代码:在VHDL中处理中断

inrpt: process(CLK_I, RST_I) 
    begin 
     if RST_I = '1' then 
     butt_int_pul <= '0'; 
     butt_int_tmp <= '0'; 
     elsif rising_edge(CLK_I) then 
     if(DATA_I(8) = '1' and butt_int_tmp = '0') then 
      butt_int_pul <= '1'; 
     else 
       butt_int_pul <= '0'; 
     end if; 

     butt_int_tmp <= DATA_I(8); 
     end if; 

    end process inrpt; 

    process(CLK_I, RST_I) 
    begin 
    if RST_I = '1' then 
      butt_int <= '0'; 
    elsif butt_int_pul = '1' then 
      butt_int <= '1'; 
    elsif clear_int = '1' then 
     butt_int <= '0'; 
    end if; 

    end process; 

我们只希望这个中断只进行一次处理(按住该按钮,不应该再调用中断),这就是为什么我们包括一个标志,检查这个(butt_int_tmp)。

问题是中断调用不稳定。我们每次按下按钮都不会打电话。当我们移除标志时,它会起作用,但在这种情况下,它的处理方式与我们按住按钮一样多。

我们做错了什么?

回答

0

首先,第二个过程没有正确书写。它应该具有与第一个处理相同的结构(即围绕除了复位逻辑之外的所有其他处理器,即if(rising_edge(CLK_I)))。您目前正在描述具有多个使能信号和错误灵敏度列表的锁存器。

继续前进,根本没有真正的理由需要第二个过程。您只需要一个寄存器充当中断(butt_int),另一个记录按钮的前一状态(butt_prev)。当DATA_I(8)'1',而butt_prev'0'(即,按钮从未按下变为按下)时,中断被触发一个周期。

process(CLK_I, RST_I) begin 
    if(RST_I='1') then 
     butt_prev <= '0'; 
     butt_int <= '0'; 
    elsif(rising_edge(CLK_I)) then 
     if(DATA_I(8)='1' and butt_prev='0') then 
      butt_int <= '1'; 
     else 
      butt_int <= '0'; 
     end if; 
     butt_prev <= DATA_I(8); 
    end if; 
end process; 

请注意,如果你的按钮是否正确抖这只会工作,否则你可能会得到多个中断,当你按下(甚至释放)按钮触发。

+0

我尝试了两种解决方案,但它仍然不稳定。我需要做非常短暂而快速的印刷来使它工作。 – www

+0

@www你使用什么时钟频率?给定几个到几百MHz的典型时钟,您执行的任何物理操作都是“很长”(~100000个时钟周期),按下按钮的速度应该没有什么区别。你确定你的按钮被消除了吗?该按钮可能是低电平有效(即按下该按钮时该信号为0)? – zennehoy

0

最好不要考虑中断。当你在瞄准FPGA时,你正在描述数字逻辑,而不是软件处理器。

有很多方法可以用你想要的行为构建电路。 最简单的可能是一个重新计时锁存

signal latched_button : std_logic; 
signal meta_chain  : std_logic_vector(2 downto 0); 

p_async_latch: process(rst_i,data(8)) 
begin 
    if rst_i = '1' then 
     latched_button <= '0'; 
    elsif data(8) = '1' then 
     latched_button <= '1'; 
    end if; 
end process; 

p_meta_chain: process(rst_i,clk_i) 
begin 
    if rst_i = '1' then 
     meta_chain <= (others => '0'); 
    elsif rising_edge(clk_i) then 
     meta_chain <= meta_chain(1 downto 0) & latched_button; 
    end if; 
end process; 

button_int <= '1' when meta_chain(2 downto 1) = "01" else '0'; 

这将导致按下按钮以异步方式锁定。锁存的信号随后沿着移位寄存器提供时钟,并且中断仅在一个周期内有效,这是锁存在时钟域中看到的第一个时钟周期。