[英]Handling Interrupt in VHDL
我们将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
)的原因。
问题是中断调用不稳定。 每次我们按下按钮时,它不会调用。 当我们删除该标志时,它可以工作,但是在这种情况下,它的处理量与按住按钮的次数相同。
我们做错了什么?
首先,第二个过程编写不正确。 它的结构应与第一个进程(即,除复位逻辑之外的所有进程)的if(rising_edge(CLK_I))
等效。 您当前正在描述具有多个使能信号和错误灵敏度列表的锁存器。
继续前进,根本没有理由完全需要第二个过程。 您只需要一个寄存器来充当中断( butt_int
),并需要一个寄存器来跟踪按钮的先前状态( butt_prev
)。 当butt_prev
为'0'
时DATA_I(8)
为'1'
时,中断被触发一个周期(即,按钮从未按下变为已按下)。
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;
请注意,这仅在按钮被正确消除抖动的情况下才有效,否则当您按下(甚至释放)按钮时,您可能会触发多个中断。
最好不要考虑中断。 以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';
这导致按钮按下被异步锁定。 然后,将锁存的信号沿移位寄存器计时,并且该中断仅在一个周期内有效,这是在时钟域上看到锁存器的第一个时钟周期。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.