vme_irq_controller.vhd 9.16 KB
Newer Older
Tom Levens's avatar
Tom Levens committed
1 2 3 4 5
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- VME64x Core
-- http://www.ohwr.org/projects/vme64x-core
--------------------------------------------------------------------------------
dpedrett's avatar
dpedrett committed
6
--
7
-- unit name:     vme_irq_controller
Tom Levens's avatar
Tom Levens committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21
--
-- author:        Pablo Alvarez Sanchez <pablo.alvarez.sanchez@cern.ch>
--                Davide Pedretti       <davide.pedretti@cern.ch>
--
-- description:
--
--   This block acts as Interrupter. Phases of an interrupt cycle:
--
--   1) The Interrupt Controller receives an interrupt request by the WB bus;
--      this request is a pulse on the INT_Req input
--   2) The Interrupt Controller asserts ('0') one of the 7 VME_IRQ lines;
--      --> request of a service.
--      The Interrupt priority is specificated by the Master writing the
--      INT_Level register in the CR/CSR space
22
--   3) The Interrupter Controller waits for the falling edge on the VME_IACKIN
Tom Levens's avatar
Tom Levens committed
23 24 25 26 27 28 29 30 31 32
--      line.
--   4) When detects VME_IACKIN_n_i = '0' and the Interrupt Handler initiates
--      the Interrupt cycle by asserting AS,the Interrupt Controller check if it
--      is the responding interrupter. Indeed before responding to an interrupt
--      acknowledge cycle the interrupter shall have an interrupt request
--      pending, shall check if the level of that request match the level
--      indicated on the address lines A1, A2 and A3,the data transfer width
--      during the interrupt acknowledge cycle should be equal or greater than
--      the size the it can respond with, and it shall receive a falling edge on
--      its IACKIN*.
33
--   5) If it is the responding interrupter, it should send the source/ID on the
Tom Levens's avatar
Tom Levens committed
34 35 36 37 38 39 40 41
--      VME_DATA lines (in our case the source/ID is the INT_Vector that the
--      Master can write in the corresponding register in the CR/CSR space) and
--      it terminates the interrupt cycle with an acknowledge before releasing
--      the IRQ lines. If it isn't the responding interrupter, it should pass a
--      falling edge on down the daisy-chain so other interrupters can respond.
--
--   All the output signals are registered
--
42
--   To implement the above-mentioned 5 phases, the following FSM has been
Tom Levens's avatar
Tom Levens committed
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
--   implemented:
--       __________
--   |--| IACKOUT2 |<-|
--   |  |__________|  |
--   |                |
--   |    _________   |  _________     _________     _________
--   |-->|  IDLE   |--->|  IRQ    |-->| WAIT_AS |-->| WAIT_DS |-------------->|
--       |_________|    |_________|   |_________|   |_________|               |
--          |             |                                                   |
--          |             |                       _________      _________    |
--          |             |---------<------------| IACKOUT1| <--| CHECK   |<--|
--          |                                    |_________|    |_________|
--          |                     __________     __________         |
--          |--<-----------------|  DTACK   |<--| DATA_OUT |---<----|
--                               |__________|   |__________|
--
--  The interrupter wait the IACKIN falling edge in the IRQ state, so if the
--  interrupter don't have interrupt pending for sure it will not respond
--  because it is in IDLE.
--  If the slave module does not have an interrupt pending (IDLE state) and it
--  receives a falling edge on the IACKIN, it shall pass the falling edge
--  through the daisy chain.
--  To obtain this the IACKOUT2 state has been added.
--
--  Time constraint:
dpedrett's avatar
dpedrett committed
68
--
69
--  Time constraint #35:
Tom Levens's avatar
Tom Levens committed
70
--
71 72
-- Clk         ____      ____      ____      ____      ____      ____
--       _____|    |____|    |____|    |____|    |____|    |____|    |_____
Tom Levens's avatar
Tom Levens committed
73
--
74 75
-- VME_AS1_n_i   __________________________________________________________
--       _______|
Tom Levens's avatar
Tom Levens committed
76
--
77 78
-- VME_AS_n_i                                ______________________________
--       ___________________________________|
Tom Levens's avatar
Tom Levens committed
79
--
80 81
-- s_AS_RisingEge                                      _________
--       _____________________________________________|         |__________
Tom Levens's avatar
Tom Levens committed
82
--
83 84
-- s_IACKOUT     __________________________________________________________
--       _______|
Tom Levens's avatar
Tom Levens committed
85
--
86 87
-- VME_IACKOUT_  __________________________________________________________
--       _______|
dpedrett's avatar
dpedrett committed
88
--
89 90 91
--       _______________________________________________________  _________
--                                       IACKOUT 1/2            \/ IDLE/IRQ
--       _______________________________________________________/\_________
Tom Levens's avatar
Tom Levens committed
92 93
--
--  To respect the time constraint indicated with the number 35 fig. 55 pag. 183
94 95 96
--  in the "VMEbus Specification" ANSI/IEEE STD1014-1987, it is necessary to
--  generate the VME_AS1_n_i signal which is the AS signal that is not sampled,
--  and assign this signal to the s_IACKOUT signal when the fsm is in the IACKOUTx
Tom Levens's avatar
Tom Levens committed
97 98 99 100
--  state.
--
--  The LWORD* input is not used now, since this is a D08(O) Interrupter (see
--  Table 31 page 157 VMEbus specification).
dpedrett's avatar
dpedrett committed
101
--
Tom Levens's avatar
Tom Levens committed
102 103
--  Since this is a D08 interrupter we do not need to monitor the LWORD* and
--  DS1* lines and the Vector (1 byte) is outputted in the D00-D07 data lines.
dpedrett's avatar
dpedrett committed
104
--
Tom Levens's avatar
Tom Levens committed
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
-- dependencies:
--
--------------------------------------------------------------------------------
-- GNU LESSER GENERAL PUBLIC LICENSE
--------------------------------------------------------------------------------
-- This source file is free software; you can redistribute it and/or modify it
-- under the terms of the GNU Lesser General Public License as published by the
-- Free Software Foundation; either version 2.1 of the License, or (at your
-- option) any later version. This source is distributed in the hope that it
-- will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
-- of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
-- See the GNU Lesser General Public License for more details. You should have
-- received a copy of the GNU Lesser General Public License along with this
-- source; if not, download it from http://www.gnu.org/licenses/lgpl-2.1.html
--------------------------------------------------------------------------------
-- last changes: see log.
--------------------------------------------------------------------------------
-- TODO: -
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
128
use work.vme64x_pkg.all;
Tom Levens's avatar
Tom Levens committed
129

130
entity vme_irq_controller is
131
  generic (
132
    g_RETRY_TIMEOUT : integer range 1024 to 16777215
Tom Levens's avatar
Tom Levens committed
133
  );
134 135
  port (
    clk_i           : in  std_logic;
136
    rst_n_i         : in  std_logic;
137
    INT_Level_i     : in  std_logic_vector (2 downto 0);
138
    INT_Req_i       : in  std_logic;
139 140

    -- Set when an irq is pending (not yet acknowledged).
141
    irq_pending_o   : out std_logic;
142

143 144
    irq_ack_i       : in  std_logic;
    VME_IRQ_n_o     : out std_logic_vector (7 downto 1)
Tom Levens's avatar
Tom Levens committed
145
  );
146
end vme_irq_controller;
Tom Levens's avatar
Tom Levens committed
147

148
architecture rtl of vme_irq_controller is
149 150 151

  type t_retry_state is (WAIT_IRQ, WAIT_RETRY);

Tom Levens's avatar
Tom Levens committed
152 153 154
  signal retry_state      : t_retry_state;
  signal retry_count      : unsigned(23 downto 0);
  signal retry_mask       : std_logic;
155
  signal s_irq_pending    : std_logic;
dpedrett's avatar
dpedrett committed
156
begin
157
  irq_pending_o <= s_irq_pending;
dpedrett's avatar
dpedrett committed
158

159
  -- Interrupts are automatically masked for g_RETRY_TIMEOUT (i.e. 1 ms) once
160 161
  -- they are acknowledge by the interrupt handler until they are deasserted
  -- by the interrupter.
Tom Levens's avatar
Tom Levens committed
162
  p_retry_fsm : process (clk_i)
163 164
  begin
    if rising_edge(clk_i) then
165
      if rst_n_i = '0' then
166 167 168 169 170
        retry_mask  <= '1';
        retry_state <= WAIT_IRQ;
      else
        case retry_state is
          when WAIT_IRQ =>
171
            if s_irq_pending = '1' and INT_Req_i = '1' then
172 173 174 175
              retry_state <= WAIT_RETRY;
              retry_count <= (others => '0');
              retry_mask  <= '0';
            else
Tom Levens's avatar
Tom Levens committed
176
              retry_mask  <= '1';
177
            end if;
dpedrett's avatar
dpedrett committed
178

179
          when WAIT_RETRY =>
180
            if INT_Req_i = '0' then
181 182 183
              retry_state <= WAIT_IRQ;
            else
              retry_count <= retry_count + 1;
184
              if retry_count = g_RETRY_TIMEOUT then
185 186 187 188
                retry_state <= WAIT_IRQ;
              end if;
            end if;
        end case;
dpedrett's avatar
dpedrett committed
189
      end if;
190 191 192
    end if;
  end process;

193
  p_main : process (clk_i)
194 195
  begin
    if rising_edge(clk_i) then
196
      if rst_n_i = '0' then
197 198
        VME_IRQ_n_o     <= (others => '1');
        s_irq_pending   <= '0';
199
      else
200 201 202
        if s_irq_pending = '0' then
          VME_IRQ_n_o     <= (others => '1');

203
          if INT_Req_i = '1' and retry_mask = '1' then
204
            s_irq_pending <= '1';
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219

            -- Explicit decoding
            case INT_Level_i is
              when "001" =>  VME_IRQ_n_o <= "1111110";
              when "010" =>  VME_IRQ_n_o <= "1111101";
              when "011" =>  VME_IRQ_n_o <= "1111011";
              when "100" =>  VME_IRQ_n_o <= "1110111";
              when "101" =>  VME_IRQ_n_o <= "1101111";
              when "110" =>  VME_IRQ_n_o <= "1011111";
              when "111" =>  VME_IRQ_n_o <= "0111111";
              when others =>
                --  Incorrect value for INT_Level_i, ignore it.
                VME_IRQ_n_o <= "1111111";
                s_irq_pending <= '0';
            end case;
220 221 222 223 224 225
          end if;
        else
          if irq_ack_i = '1' then
            s_irq_pending  <= '0';
          end if;
        end if;
226
      end if;
dpedrett's avatar
dpedrett committed
227
    end if;
228
  end process;
229
end rtl;