0
0
VhdlHow-ToBeginner · 4 min read

VHDL Code for Interrupt Controller: Syntax and Example

A basic interrupt controller in VHDL monitors interrupt request signals and generates an interrupt acknowledge signal. It typically uses input signals for interrupts and outputs a signal to the processor when an interrupt is active. The controller can be implemented using a process that checks interrupt lines and sets flags accordingly.
📐

Syntax

The interrupt controller in VHDL usually includes input signals for interrupt requests, an output for interrupt acknowledge, and internal logic to prioritize and handle interrupts.

Key parts:

  • entity: Defines inputs and outputs like irq (interrupt requests) and int_ack (interrupt acknowledge).
  • architecture: Contains the logic to detect interrupts and generate acknowledge signals.
  • process: Monitors interrupt lines and sets output signals.
vhdl
entity InterruptController is
    Port (
        clk      : in  std_logic;
        reset    : in  std_logic;
        irq      : in  std_logic_vector(3 downto 0); -- 4 interrupt lines
        int_ack  : out std_logic;
        int_num  : out std_logic_vector(1 downto 0) -- interrupt number
    );
end InterruptController;

architecture Behavioral of InterruptController is
begin
    process(clk, reset)
    begin
        if reset = '1' then
            int_ack <= '0';
            int_num <= "00";
        elsif rising_edge(clk) then
            int_ack <= '0';
            int_num <= "00";
            if irq(0) = '1' then
                int_ack <= '1';
                int_num <= "00";
            elsif irq(1) = '1' then
                int_ack <= '1';
                int_num <= "01";
            elsif irq(2) = '1' then
                int_ack <= '1';
                int_num <= "10";
            elsif irq(3) = '1' then
                int_ack <= '1';
                int_num <= "11";
            end if;
        end if;
    end process;
end Behavioral;
💻

Example

This example shows a simple interrupt controller with 4 interrupt lines. It checks each interrupt in priority order and outputs an acknowledge signal and the interrupt number.

The int_ack signal goes high when any interrupt is active, and int_num indicates which interrupt is active.

vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity InterruptController is
    Port (
        clk      : in  std_logic;
        reset    : in  std_logic;
        irq      : in  std_logic_vector(3 downto 0);
        int_ack  : out std_logic;
        int_num  : out std_logic_vector(1 downto 0)
    );
end InterruptController;

architecture Behavioral of InterruptController is
begin
    process(clk, reset)
    begin
        if reset = '1' then
            int_ack <= '0';
            int_num <= "00";
        elsif rising_edge(clk) then
            int_ack <= '0';
            int_num <= "00";
            if irq(0) = '1' then
                int_ack <= '1';
                int_num <= "00";
            elsif irq(1) = '1' then
                int_ack <= '1';
                int_num <= "01";
            elsif irq(2) = '1' then
                int_ack <= '1';
                int_num <= "10";
            elsif irq(3) = '1' then
                int_ack <= '1';
                int_num <= "11";
            end if;
        end if;
    end process;
end Behavioral;
Output
When irq(0) = '1', int_ack = '1' and int_num = "00"; for irq(1) = '1', int_ack = '1' and int_num = "01"; similarly for irq(2) and irq(3). If no irq is active, int_ack = '0' and int_num = "00".
⚠️

Common Pitfalls

Common mistakes when writing an interrupt controller in VHDL include:

  • Not resetting output signals properly, causing stale interrupt acknowledges.
  • Checking interrupts without priority, which can cause multiple interrupts to be acknowledged simultaneously.
  • Forgetting to use rising_edge(clk) for synchronous logic, leading to glitches.
  • Not handling the reset condition correctly, which can cause undefined outputs.
vhdl
Wrong approach (no priority, no reset):
process(clk)
begin
    if rising_edge(clk) then
        if irq(0) = '1' then
            int_ack <= '1';
            int_num <= "00";
        end if;
        if irq(1) = '1' then
            int_ack <= '1';
            int_num <= "01";
        end if;
    end if;
end process;

Right approach (priority and reset):
process(clk, reset)
begin
    if reset = '1' then
        int_ack <= '0';
        int_num <= "00";
    elsif rising_edge(clk) then
        int_ack <= '0';
        int_num <= "00";
        if irq(0) = '1' then
            int_ack <= '1';
            int_num <= "00";
        elsif irq(1) = '1' then
            int_ack <= '1';
            int_num <= "01";
        end if;
    end if;
end process;
📊

Quick Reference

Interrupt Controller Tips:

  • Use a synchronous process with rising_edge(clk) and asynchronous reset.
  • Check interrupts in priority order using elsif to avoid multiple acknowledges.
  • Reset outputs to known states to avoid glitches.
  • Use std_logic_vector for multiple interrupt lines and output interrupt number.

Key Takeaways

Use a synchronous process with reset to handle interrupts cleanly.
Check interrupt lines in priority order using elsif to avoid multiple active interrupts.
Reset output signals to known states to prevent glitches.
Output both interrupt acknowledge and interrupt number for processor handling.
Test your interrupt controller with different interrupt inputs to verify behavior.