处理VHDL中断

时间:2013-07-19 15:21:02

标签: vhdl opencore

我们正在为项目使用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)。

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

我们做错了什么?

2 个答案:

答案 0 :(得分: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;

请注意,这仅适用于您的按钮被正确去抖动的情况,否则您可能会在按下(甚至释放)按钮时触发多次中断。

答案 1 :(得分: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';

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