VME_IRQ_Controller.vhd 9.13 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
--
Tom Levens's avatar
Tom Levens committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 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
-- unit name:     VME_IRQ_Controller (VME_IRQ_Controller.vhd)
--
-- 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
--   3) The Interrupter Controller wait for the falling edge on the VME_IACKIN
--      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*.
--   5) If it is the responding interrupter should send the source/ID on the
--      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
--
--   To implement the 5 phases before mentioned the follow FSM has been
--   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 94 95 96 97 98 99 100
--
--  To respect the time constraint indicated with the number 35 fig. 55 pag. 183
--  in the "VMEbus Specification" ANSI/IEEE STD1014-1987, is necessary to
--  generate the VME_AS1_n_i signal which is the AS signal not sampled, and
--  assign this signal to the s_IACKOUT signal when the fsm is in the IACKOUTx
--  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;
dpedrett's avatar
dpedrett committed
128
use work.vme64x_pack.all;
Tom Levens's avatar
Tom Levens committed
129

dpedrett's avatar
dpedrett committed
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 136
  port (
    clk_i           : in  std_logic;
    reset_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 141
    irq_pending_o   : out std_logic;
    irq_ack_i       : in  std_logic;
    VME_IRQ_n_o     : out std_logic_vector (7 downto 1)
Tom Levens's avatar
Tom Levens committed
142
  );
dpedrett's avatar
dpedrett committed
143
end VME_IRQ_Controller;
Tom Levens's avatar
Tom Levens committed
144

dpedrett's avatar
dpedrett committed
145
architecture Behavioral of VME_IRQ_Controller is
146 147 148

  type t_retry_state is (WAIT_IRQ, WAIT_RETRY);

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

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

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

Tom Levens's avatar
Tom Levens committed
190
  p_main_fsm : process (clk_i)
191 192 193
  begin
    if rising_edge(clk_i) then
      if reset_n_i = '0' then
194 195
        VME_IRQ_n_o     <= (others => '1');
        s_irq_pending   <= '0';
196
      else
197 198 199
        if s_irq_pending = '0' then
          VME_IRQ_n_o     <= (others => '1');

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

            -- 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;
217 218 219 220 221 222
          end if;
        else
          if irq_ack_i = '1' then
            s_irq_pending  <= '0';
          end if;
        end if;
223
      end if;
dpedrett's avatar
dpedrett committed
224
    end if;
225
  end process;
Tom Levens's avatar
Tom Levens committed
226
end Behavioral;