0

我们正在为我们的项目使用 OR1200,我们想为 FPGA 板的第 8 个按钮分配一个中断。下面是产生中断的代码:

   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)。

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

我们做错了什么?

4

2 回答 2

0

首先,第二个过程没有正确编写。它应该具有与第一个进程等效的结构(即,if(rising_edge(CLK_I))围绕除复位逻辑之外的所有进程)。您当前正在描述具有多个启用信号和错误灵敏度列表的锁存器。

继续前进,根本没有真正的理由需要第二个过程。您只需要一个寄存器来充当中断 ( butt_int),一个来跟踪按钮的先前状态 ( butt_prev)。当DATA_I(8)is '1'while butt_previs '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;

请注意,这仅在您的按钮正确去抖动时才有效,否则当您按下(甚至释放)按钮时,您可能会触发多个中断。

于 2013-07-19T15:39:12.907 回答
-1

最好不要考虑中断。当您以 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';

这会导致按钮按下被异步锁定。然后锁存信号沿移位寄存器计时,并且中断仅在一个周期内有效,这是在时钟域上看到锁存器的第一个时钟周期。

于 2013-07-21T13:02:25.320 回答