Commit 7102fab4 authored by egousiou's avatar egousiou

vic on spec (not stable yet:s)

git-svn-id: http://svn.ohwr.org/fmc-tdc@144 85dfdc96-de2c-444c-878d-45b388be74a9
parent a45b1c0a
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
--------------------------------------------------------------------------------
-- CERN (BE-CO-HT)
-- IRQ controller
-- http://www.ohwr.org/projects/fmc-adc-100m14b4cha
--------------------------------------------------------------------------------
--
-- unit name: irq_controller (irq_controller.vhd)
--
-- author: Matthieu Cattin (matthieu.cattin@cern.ch)
--
-- date: 18-11-2011
--
-- version: 1.0
--
-- description:
--
-- 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 svn log.
--------------------------------------------------------------------------------
-- TODO: -
--------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
--library UNISIM;
--use UNISIM.vcomponents.all;
entity irq_controller is
port (
-- Clock, reset
clk_i : in std_logic;
rst_n_i : in std_logic;
-- Interrupt sources input, must be 1 clk_i tick long
irq_src_p_i : in std_logic_vector(31 downto 0);
-- IRQ pulse output
irq_p_o : out std_logic;
-- Wishbone interface
wb_adr_i : in std_logic_vector(1 downto 0);
wb_dat_i : in std_logic_vector(31 downto 0);
wb_dat_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic
);
end irq_controller;
architecture rtl of irq_controller is
------------------------------------------------------------------------------
-- Components declaration
------------------------------------------------------------------------------
component irq_controller_regs
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(1 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
irq_ctrl_multi_irq_o : out std_logic_vector(31 downto 0);
irq_ctrl_multi_irq_i : in std_logic_vector(31 downto 0);
irq_ctrl_multi_irq_load_o : out std_logic;
irq_ctrl_src_o : out std_logic_vector(31 downto 0);
irq_ctrl_src_i : in std_logic_vector(31 downto 0);
irq_ctrl_src_load_o : out std_logic;
irq_ctrl_en_mask_o : out std_logic_vector(31 downto 0)
);
end component irq_controller_regs;
------------------------------------------------------------------------------
-- Signals declaration
------------------------------------------------------------------------------
signal irq_en_mask : std_logic_vector(31 downto 0);
signal irq_pending : std_logic_vector(31 downto 0);
signal irq_pending_d : std_logic_vector(31 downto 0);
signal irq_pending_re : std_logic_vector(31 downto 0);
signal irq_src_rst : std_logic_vector(31 downto 0);
signal irq_src_rst_en : std_logic;
signal multi_irq : std_logic_vector(31 downto 0);
signal multi_irq_rst : std_logic_vector(31 downto 0);
signal multi_irq_rst_en : std_logic;
signal irq_p_or : std_logic_vector(32 downto 0);
begin
------------------------------------------------------------------------------
-- Wishbone interface to IRQ controller registers
------------------------------------------------------------------------------
cmp_irq_controller_regs : irq_controller_regs
port map(
rst_n_i => rst_n_i,
wb_clk_i => clk_i,
wb_addr_i => wb_adr_i,
wb_data_i => wb_dat_i,
wb_data_o => wb_dat_o,
wb_cyc_i => wb_cyc_i,
wb_sel_i => wb_sel_i,
wb_stb_i => wb_stb_i,
wb_we_i => wb_we_i,
wb_ack_o => wb_ack_o,
irq_ctrl_multi_irq_o => multi_irq_rst,
irq_ctrl_multi_irq_load_o => multi_irq_rst_en,
irq_ctrl_multi_irq_i => multi_irq,
irq_ctrl_src_o => irq_src_rst,
irq_ctrl_src_i => irq_pending,
irq_ctrl_src_load_o => irq_src_rst_en,
irq_ctrl_en_mask_o => irq_en_mask
);
------------------------------------------------------------------------------
-- Register interrupt sources
-- IRQ is pending until a '1' is written to the corresponding bit
------------------------------------------------------------------------------
p_irq_src : process (clk_i)
begin
if rising_edge(clk_i) then
for I in 0 to irq_pending'length-1 loop
if rst_n_i = '0' then
irq_pending(I) <= '0';
elsif irq_src_p_i(I) = '1' then
irq_pending(I) <= '1';
elsif irq_src_rst_en = '1' and irq_src_rst(I) = '1' then
irq_pending(I) <= '0';
end if;
end loop; -- I
end if;
end process p_irq_src;
------------------------------------------------------------------------------
-- Multiple interrupt detection
-- Rise a flag if an interrupt occurs while an irq is still pending
-- Write '1' to the flag to clear it
------------------------------------------------------------------------------
p_multi_irq_detect : process (clk_i)
begin
if rising_edge(clk_i) then
for I in 0 to multi_irq'length-1 loop
if rst_n_i = '0' then
multi_irq(I) <= '0';
elsif irq_src_p_i(I) = '1' and irq_pending(I) = '1' then
multi_irq(I) <= '1';
elsif multi_irq_rst_en = '1' and multi_irq_rst(I) = '1' then
multi_irq(I) <= '0';
end if;
end loop; -- I
end if;
end process p_multi_irq_detect;
------------------------------------------------------------------------------
-- Generate IRQ output pulse
------------------------------------------------------------------------------
irq_p_or(0) <= '0';
l_irq_out_pulse : for I in 0 to irq_src_p_i'length-1 generate
irq_p_or(I+1) <= irq_p_or(I) or (irq_src_p_i(I) and irq_en_mask(I));
end generate l_irq_out_pulse;
p_irq_out_pulse : process (clk_i)
begin
if rising_edge(clk_i) then
if rst_n_i = '0' then
irq_p_o <= '0';
else
irq_p_o <= irq_p_or(32);
end if;
end if;
end process p_irq_out_pulse;
end rtl;
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for IRQ controller registers
---------------------------------------------------------------------------------------
-- File : ../rtl/irq_controller_regs.vhd
-- Author : auto-generated by wbgen2 from irq_controller_regs.wb
-- Created : Wed Jan 18 09:43:55 2012
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE irq_controller_regs.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity irq_controller_regs is
port (
rst_n_i : in std_logic;
wb_clk_i : in std_logic;
wb_addr_i : in std_logic_vector(1 downto 0);
wb_data_i : in std_logic_vector(31 downto 0);
wb_data_o : out std_logic_vector(31 downto 0);
wb_cyc_i : in std_logic;
wb_sel_i : in std_logic_vector(3 downto 0);
wb_stb_i : in std_logic;
wb_we_i : in std_logic;
wb_ack_o : out std_logic;
-- Port for std_logic_vector field: 'Multiple interrupt' in reg: 'Multiple interrupt register'
irq_ctrl_multi_irq_o : out std_logic_vector(31 downto 0);
irq_ctrl_multi_irq_i : in std_logic_vector(31 downto 0);
irq_ctrl_multi_irq_load_o : out std_logic;
-- Port for std_logic_vector field: 'Interrupt sources' in reg: 'Interrupt sources register '
irq_ctrl_src_o : out std_logic_vector(31 downto 0);
irq_ctrl_src_i : in std_logic_vector(31 downto 0);
irq_ctrl_src_load_o : out std_logic;
-- Port for std_logic_vector field: 'Interrupt enable mask' in reg: 'Interrupt enable mask register'
irq_ctrl_en_mask_o : out std_logic_vector(31 downto 0)
);
end irq_controller_regs;
architecture syn of irq_controller_regs is
signal irq_ctrl_en_mask_int : std_logic_vector(31 downto 0);
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(1 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal bus_clock_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments. For (foreseen) compatibility with other bus standards.
wrdata_reg <= wb_data_i;
bwsel_reg <= wb_sel_i;
bus_clock_int <= wb_clk_i;
rd_int <= wb_cyc_i and (wb_stb_i and (not wb_we_i));
wr_int <= wb_cyc_i and (wb_stb_i and wb_we_i);
allones <= (others => '1');
allzeros <= (others => '0');
--
-- Main register bank access process.
process (bus_clock_int, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
irq_ctrl_multi_irq_load_o <= '0';
irq_ctrl_src_load_o <= '0';
irq_ctrl_en_mask_int <= "00000000000000000000000000000000";
elsif rising_edge(bus_clock_int) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
irq_ctrl_multi_irq_load_o <= '0';
irq_ctrl_src_load_o <= '0';
ack_in_progress <= '0';
else
irq_ctrl_multi_irq_load_o <= '0';
irq_ctrl_src_load_o <= '0';
end if;
else
if ((wb_cyc_i = '1') and (wb_stb_i = '1')) then
case rwaddr_reg(1 downto 0) is
when "00" =>
if (wb_we_i = '1') then
irq_ctrl_multi_irq_load_o <= '1';
else
rddata_reg(31 downto 0) <= irq_ctrl_multi_irq_i;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "01" =>
if (wb_we_i = '1') then
irq_ctrl_src_load_o <= '1';
else
rddata_reg(31 downto 0) <= irq_ctrl_src_i;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "10" =>
if (wb_we_i = '1') then
irq_ctrl_en_mask_int <= wrdata_reg(31 downto 0);
else
rddata_reg(31 downto 0) <= irq_ctrl_en_mask_int;
end if;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
wb_data_o <= rddata_reg;
-- Multiple interrupt
irq_ctrl_multi_irq_o <= wrdata_reg(31 downto 0);
-- Interrupt sources
irq_ctrl_src_o <= wrdata_reg(31 downto 0);
-- Interrupt enable mask
irq_ctrl_en_mask_o <= irq_ctrl_en_mask_int;
rwaddr_reg <= wb_addr_i;
-- ACK signal generation. Just pass the LSB of ACK counter.
wb_ack_o <= ack_sreg(0);
end syn;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment