Line 78... |
Line 78... |
signal acc_en : std_ulogic; -- module access enable
|
signal acc_en : std_ulogic; -- module access enable
|
signal addr : std_ulogic_vector(31 downto 0); -- access address
|
signal addr : std_ulogic_vector(31 downto 0); -- access address
|
|
|
-- control registers --
|
-- control registers --
|
signal irq_enable : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: interrupt enable
|
signal irq_enable : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: interrupt enable
|
signal clr_pending : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- (r)/w: clear/ack pending IRQs
|
signal clr_pending : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0); -- r/w: clear pending IRQs
|
|
signal irq_src : std_ulogic_vector(4 downto 0); -- r/w: source IRQ, ACK on any write
|
|
|
-- interrupt trigger --
|
-- interrupt trigger --
|
signal irq_sync : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_sync : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_sync2 : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_sync2 : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_trig : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_trig : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
Line 90... |
Line 91... |
-- interrupt buffer --
|
-- interrupt buffer --
|
signal irq_buf : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_buf : std_ulogic_vector(XIRQ_NUM_CH-1 downto 0);
|
signal irq_fire : std_ulogic;
|
signal irq_fire : std_ulogic;
|
|
|
-- interrupt source --
|
-- interrupt source --
|
signal irq_src, irq_src_nxt : std_ulogic_vector(04 downto 0);
|
signal irq_src_nxt : std_ulogic_vector(4 downto 0);
|
|
|
-- arbiter --
|
-- arbiter --
|
signal irq_run : std_ulogic;
|
signal irq_run : std_ulogic;
|
signal irq_run_ff : std_ulogic;
|
|
signal host_ack : std_ulogic;
|
signal host_ack : std_ulogic;
|
|
|
begin
|
begin
|
|
|
-- Sanity Checks --------------------------------------------------------------------------
|
-- Sanity Checks --------------------------------------------------------------------------
|
Line 120... |
Line 120... |
-- bus handshake --
|
-- bus handshake --
|
ack_o <= acc_en and (rden_i or wren_i);
|
ack_o <= acc_en and (rden_i or wren_i);
|
|
|
-- write access --
|
-- write access --
|
host_ack <= '0';
|
host_ack <= '0';
|
clr_pending <= (others => '0');
|
clr_pending <= (others => '1');
|
if ((acc_en and wren_i) = '1') then
|
if ((acc_en and wren_i) = '1') then
|
-- channel-enable --
|
-- channel-enable --
|
if (addr = xirq_enable_addr_c) then
|
if (addr = xirq_enable_addr_c) then
|
irq_enable <= data_i(XIRQ_NUM_CH-1 downto 0);
|
irq_enable <= data_i(XIRQ_NUM_CH-1 downto 0);
|
end if;
|
end if;
|
-- clear/ACK pending IRQ --
|
-- clear pending IRQs --
|
if (addr = xirq_pending_addr_c) then
|
if (addr = xirq_pending_addr_c) then
|
|
clr_pending <= data_i(XIRQ_NUM_CH-1 downto 0); -- set zero to clear pending IRQ
|
|
end if;
|
|
-- acknowledge IRQ --
|
|
if (addr = xirq_source_addr_c) then -- write _any_ value to ACK
|
host_ack <= '1';
|
host_ack <= '1';
|
clr_pending <= data_i(XIRQ_NUM_CH-1 downto 0);
|
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
-- read access --
|
-- read access --
|
data_o <= (others => '0');
|
data_o <= (others => '0');
|
Line 178... |
Line 181... |
-- IRQ Buffer ---------------------------------------------------------------
|
-- IRQ Buffer ---------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
irq_buffer: process(clk_i)
|
irq_buffer: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
irq_buf <= (irq_buf or (irq_trig and irq_enable)) and (not clr_pending);
|
irq_buf <= (irq_buf or (irq_trig and irq_enable)) and clr_pending;
|
end if;
|
end if;
|
end process irq_buffer;
|
end process irq_buffer;
|
|
|
-- anyone firing? --
|
-- anyone firing? --
|
irq_fire <= or_reduce_f(irq_buf);
|
irq_fire <= or_reduce_f(irq_buf);
|
Line 191... |
Line 194... |
-- IRQ Priority Encoder -----------------------------------------------------
|
-- IRQ Priority Encoder -----------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
irq_priority: process(irq_buf)
|
irq_priority: process(irq_buf)
|
begin
|
begin
|
irq_src_nxt <= (others => '0');
|
irq_src_nxt <= (others => '0');
|
|
if (XIRQ_NUM_CH > 1) then
|
for i in 0 to XIRQ_NUM_CH-1 loop
|
for i in 0 to XIRQ_NUM_CH-1 loop
|
if (irq_buf(i) = '1') then
|
if (irq_buf(i) = '1') then
|
irq_src_nxt <= std_ulogic_vector(to_unsigned(i, 5));
|
irq_src_nxt(index_size_f(XIRQ_NUM_CH)-1 downto 0) <= std_ulogic_vector(to_unsigned(i, index_size_f(XIRQ_NUM_CH)));
|
exit;
|
exit;
|
end if;
|
end if;
|
end loop;
|
end loop;
|
|
end if;
|
end process irq_priority;
|
end process irq_priority;
|
|
|
|
|
-- IRQ Arbiter --------------------------------------------------------------
|
-- IRQ Arbiter --------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
-- -----------------------------------------------------------------------------
|
irq_arbiter: process(clk_i)
|
irq_arbiter: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
irq_run_ff <= irq_run;
|
cpu_irq_o <= '0';
|
if (irq_run = '0') then -- no active IRQ
|
if (irq_run = '0') then -- no active IRQ
|
if (irq_fire = '1') then
|
if (irq_fire = '1') then
|
|
cpu_irq_o <= '1';
|
irq_run <= '1';
|
irq_run <= '1';
|
irq_src <= irq_src_nxt;
|
irq_src <= irq_src_nxt;
|
end if;
|
end if;
|
else -- active IRQ, wait for CPU acknowledge
|
else -- active IRQ, wait for CPU to acknowledge
|
if (host_ack = '1') then
|
if (host_ack = '1') then
|
irq_run <= '0';
|
irq_run <= '0';
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end if;
|
end process irq_arbiter;
|
end process irq_arbiter;
|
|
|
-- rising-edge detector --
|
|
cpu_irq_o <= irq_run and (not irq_run_ff);
|
|
|
|
|
|
end neorv32_xirq_rtl;
|
end neorv32_xirq_rtl;
|
|
|
No newline at end of file
|
No newline at end of file
|