OpenCores
URL https://opencores.org/ocsvn/neo430/neo430/trunk

Subversion Repositories neo430

[/] [neo430/] [trunk/] [neo430/] [rtl/] [core/] [neo430_exirq.vhd] - Blame information for rev 198

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 198 zero_gravi
-- #################################################################################################
2
-- #  << NEO430 - External Interrupts Controller >>                                                #
3
-- # ********************************************************************************************* #
4
-- # This unit provides 8 maskable external interrupt lines with according ACK lines. The IRQ      #
5
-- # trigger on a high level (use external edge detectors if required). Each line has a unique     #
6
-- # enable bit. The acknowledge output is set high for one clock cycle to confirm the             #
7
-- # interrupt has been sampled and has also been cpatured by the according handler function.      #
8
-- # All external interrupt requests are forwarded to a *single CPU interrupt*. The according IRQ  #
9
-- # has to check the SRC bits in the unit's control register to determine the actual source and   #
10
-- # start the according handler function.                                                         #
11
-- # If several IRQs occur at the same time, the one with highest priority is executed while the   #
12
-- # others are kept in a buffer. The buffer is reset when the global enable flag of the unit is   #
13
-- # cleared. ext_irq_i(0) has highest priority while ext_irq_i(7) has the lowest priority.        #
14
-- # Each enabled interrupt channel can also be triggered by software using the sw_irq_x bits.     #
15
-- # ********************************************************************************************* #
16
-- # BSD 3-Clause License                                                                          #
17
-- #                                                                                               #
18
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
19
-- #                                                                                               #
20
-- # Redistribution and use in source and binary forms, with or without modification, are          #
21
-- # permitted provided that the following conditions are met:                                     #
22
-- #                                                                                               #
23
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
24
-- #    conditions and the following disclaimer.                                                   #
25
-- #                                                                                               #
26
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
27
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
28
-- #    provided with the distribution.                                                            #
29
-- #                                                                                               #
30
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
31
-- #    endorse or promote products derived from this software without specific prior written      #
32
-- #    permission.                                                                                #
33
-- #                                                                                               #
34
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
35
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
36
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
37
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
38
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
39
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
40
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
41
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
42
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
43
-- # ********************************************************************************************* #
44
-- # The NEO430 Processor - https://github.com/stnolting/neo430                                    #
45
-- #################################################################################################
46
 
47
library ieee;
48
use ieee.std_logic_1164.all;
49
use ieee.numeric_std.all;
50
 
51
library neo430;
52
use neo430.neo430_package.all;
53
 
54
entity neo430_exirq is
55
  port (
56
    -- host access --
57
    clk_i     : in  std_ulogic; -- global clock line
58
    rden_i    : in  std_ulogic; -- read enable
59
    wren_i    : in  std_ulogic; -- write enable
60
    addr_i    : in  std_ulogic_vector(15 downto 0); -- address
61
    data_i    : in  std_ulogic_vector(15 downto 0); -- data in
62
    data_o    : out std_ulogic_vector(15 downto 0); -- data out
63
    -- cpu interrupt --
64
    cpu_irq_o : out std_ulogic;
65
    -- external interrupt lines --
66
    ext_irq_i : in  std_ulogic_vector(7 downto 0); -- IRQ, triggering on HIGH level
67
    ext_ack_o : out std_ulogic_vector(7 downto 0)  -- acknowledge
68
  );
69
end neo430_exirq;
70
 
71
architecture neo430_exirq_rtl of neo430_exirq is
72
 
73
  -- control register bits --
74
  constant ctrl_irq_sel0_c : natural :=  0; -- r/w: IRQ source bit 0 (r); SW IRQ select (w)
75
  constant ctrl_irq_sel1_c : natural :=  1; -- r/w: IRQ source bit 1 (r); SW IRQ select (w)
76
  constant ctrl_irq_sel2_c : natural :=  2; -- r/w: IRQ source bit 2 (r); SW IRQ select (w)
77
  constant ctrl_en_c       : natural :=  3; -- r/w: unit enable
78
  constant ctrl_sw_irq_c   : natural :=  4; -- -/w: use irq_sel as SW IRQ trigger, auto-clears
79
  constant ctrl_ack_irq_c  : natural :=  5; -- -/w: ACK current IRQ, auto-clears
80
  -- ...
81
  constant ctrl_en_irq0_c  : natural :=  8; -- r/w: IRQ channel 0 enable
82
  constant ctrl_en_irq1_c  : natural :=  9; -- r/w: IRQ channel 1 enable
83
  constant ctrl_en_irq2_c  : natural := 10; -- r/w: IRQ channel 2 enable
84
  constant ctrl_en_irq3_c  : natural := 11; -- r/w: IRQ channel 3 enable
85
  constant ctrl_en_irq4_c  : natural := 12; -- r/w: IRQ channel 4 enable
86
  constant ctrl_en_irq5_c  : natural := 13; -- r/w: IRQ channel 5 enable
87
  constant ctrl_en_irq6_c  : natural := 14; -- r/w: IRQ channel 6 enable
88
  constant ctrl_en_irq7_c  : natural := 15; -- r/w: IRQ channel 7 enable
89
 
90
  -- IO space: module base address --
91
  constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit
92
  constant lo_abb_c : natural := index_size_f(exirq_size_c); -- low address boundary bit
93
 
94
  -- access control --
95
  signal acc_en : std_ulogic; -- module access enable
96
  signal wren   : std_ulogic; -- full word write enable
97
  signal rden   : std_ulogic; -- read enable
98
 
99
  -- r/w accessible registers --
100
  signal irq_enable  : std_ulogic_vector(7 downto 0);
101
  signal enable      : std_ulogic; -- global enable
102
  signal irq_sel     : std_ulogic_vector(2 downto 0);
103
  signal sw_trig     : std_ulogic;
104
  signal ack_trig    : std_ulogic;
105
 
106
  -- irq input / ack output system --
107
  signal irq_sync, irq_raw, sw_irq, irq_valid, ack_mask : std_ulogic_vector(7 downto 0);
108
 
109
  -- controller core --
110
  signal irq_buf              : std_ulogic_vector(7 downto 0);
111
  signal irq_src, irq_src_reg : std_ulogic_vector(2 downto 0);
112
  signal irq_fire, state      : std_ulogic;
113
 
114
begin
115
 
116
  -- Access control -----------------------------------------------------------
117
  -- -----------------------------------------------------------------------------
118
  acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = exirq_base_c(hi_abb_c downto lo_abb_c)) else '0';
119
  wren   <= acc_en and wren_i;
120
  rden   <= acc_en and rden_i;
121
 
122
 
123
  -- Write access -------------------------------------------------------------
124
  -- -----------------------------------------------------------------------------
125
  wr_access: process(clk_i)
126
  begin
127
    if rising_edge(clk_i) then
128
      sw_trig  <= '0';
129
      ack_trig <= '0';
130
      if (wren = '1') then
131
        irq_sel    <= data_i(ctrl_irq_sel2_c downto ctrl_irq_sel0_c);
132
        enable     <= data_i(ctrl_en_c);
133
        irq_enable <= data_i(ctrl_en_irq7_c downto ctrl_en_irq0_c);
134
        -- irq_sel options --
135
        sw_trig    <= data_i(ctrl_sw_irq_c);
136
        ack_trig   <= data_i(ctrl_ack_irq_c);
137
      end if;
138
    end if;
139
  end process wr_access;
140
 
141
 
142
  -- Get external/software interrupt request ----------------------------------
143
  -- -----------------------------------------------------------------------------
144
  ext_irq_source_sync: process(clk_i)
145
  begin
146
    if rising_edge(clk_i) then
147
      irq_sync <= ext_irq_i;
148
      irq_raw  <= irq_sync; -- sync to avoid metastability
149
    end if;
150
  end process ext_irq_source_sync;
151
 
152
  sw_irq_source: process(sw_trig, irq_sel)
153
    variable sw_irq_v : std_ulogic_vector(3 downto 0);
154
  begin
155
    sw_irq_v := sw_trig & irq_sel;
156
    case sw_irq_v is
157
      when "1000" => sw_irq <= "00000001";
158
      when "1001" => sw_irq <= "00000010";
159
      when "1010" => sw_irq <= "00000100";
160
      when "1011" => sw_irq <= "00001000";
161
      when "1100" => sw_irq <= "00010000";
162
      when "1101" => sw_irq <= "00100000";
163
      when "1110" => sw_irq <= "01000000";
164
      when "1111" => sw_irq <= "10000000";
165
      when others => sw_irq <= "00000000";
166
    end case;
167
  end process sw_irq_source;
168
 
169
  -- only pass enabled interrupt sources --
170
  irq_valid <= (irq_raw or sw_irq) and irq_enable;
171
 
172
 
173
  -- IRQ controller core ------------------------------------------------------
174
  -- -----------------------------------------------------------------------------
175
  irq_core: process(clk_i)
176
  begin
177
    if rising_edge(clk_i) then
178
      -- ack output --
179
      ext_ack_o <= ack_mask;
180
 
181
      -- irq buffer --
182
      for i in 0 to 7 loop
183
        -- keep requests until they are acknowledged
184
        -- clear buffer when unit is disabled
185
        irq_buf(i) <= (irq_buf(i) or irq_valid(i)) and enable and (not ack_mask(i));
186
      end loop; -- i
187
 
188
      -- mini state FSM --
189
      cpu_irq_o <= '0';
190
      if (state = '0') or (enable = '0') then -- idle or deactivated
191
        state <= '0';
192
        if (irq_fire = '1') and (enable = '1') then -- valid active IRQ
193
          irq_src_reg <= irq_src; -- capture source
194
          cpu_irq_o   <= '1'; -- trigger CPU interrupt
195
          state       <= '1'; -- go to active IRQ state
196
        end if;
197
      else -- active interrupt request
198
        if (ack_trig = '1') or (enable = '0') then -- ack or disable
199
          state <= '0';
200
        end if;
201
      end if;
202
    end if;
203
  end process irq_core;
204
 
205
  -- anybody firing? --
206
  irq_fire <= or_all_f(irq_buf);
207
 
208
  -- get interrupt priority --
209
  irq_src <= "000" when (irq_buf(0) = '1') else
210
             "001" when (irq_buf(1) = '1') else
211
             "010" when (irq_buf(2) = '1') else
212
             "011" when (irq_buf(3) = '1') else
213
             "100" when (irq_buf(4) = '1') else
214
             "101" when (irq_buf(5) = '1') else
215
             "110" when (irq_buf(6) = '1') else
216
             "111";-- when (irq_buf(7) = '1') else "---";
217
 
218
 
219
  -- ACK priority decoder -----------------------------------------------------
220
  -- -----------------------------------------------------------------------------
221
  ack_priority_dec: process(state, ack_trig, irq_src_reg)
222
    variable irq_ack_v : std_ulogic_vector(3 downto 0);
223
  begin
224
    irq_ack_v := (ack_trig and state) & irq_src_reg;
225
    case irq_ack_v is
226
      when "1000" => ack_mask <= "00000001";
227
      when "1001" => ack_mask <= "00000010";
228
      when "1010" => ack_mask <= "00000100";
229
      when "1011" => ack_mask <= "00001000";
230
      when "1100" => ack_mask <= "00010000";
231
      when "1101" => ack_mask <= "00100000";
232
      when "1110" => ack_mask <= "01000000";
233
      when "1111" => ack_mask <= "10000000";
234
      when others => ack_mask <= "00000000";
235
    end case;
236
  end process ack_priority_dec;
237
 
238
 
239
  -- Read access --------------------------------------------------------------
240
  -- -----------------------------------------------------------------------------
241
  rd_access: process(clk_i)
242
  begin
243
    if rising_edge(clk_i) then
244
      data_o <= (others => '0');
245
      if (rden = '1') then
246
        data_o(ctrl_irq_sel2_c downto ctrl_irq_sel0_c) <= irq_src_reg;
247
        data_o(ctrl_en_irq7_c downto ctrl_en_irq0_c) <= irq_enable;
248
        data_o(ctrl_en_c) <= enable;
249
      end if;
250
    end if;
251
  end process rd_access;
252
 
253
 
254
end neo430_exirq_rtl;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.