2013-07-19 144 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'; 

這將導致按下按鈕以異步方式鎖定。鎖存的信號隨後沿着移位寄存器提供時鐘,並且中斷僅在一個週期內有效,這是鎖存在時鐘域中看到的第一個時鐘週期。