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

Subversion Repositories simpcon

[/] [simpcon/] [trunk/] [vhdl/] [sc_sys.vhd] - Diff between revs 26 and 29

Show entire file | Details | Blame | View Log

Rev 26 Rev 29
Line 1... Line 1...
--
--
 
--
 
--  This file is a part of JOP, the Java Optimized Processor
 
--
 
--  Copyright (C) 2001-2008, Martin Schoeberl (martin@jopdesign.com)
 
--
 
--  This program is free software: you can redistribute it and/or modify
 
--  it under the terms of the GNU General Public License as published by
 
--  the Free Software Foundation, either version 3 of the License, or
 
--  (at your option) any later version.
 
--
 
--  This program 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 General Public License for more details.
 
--
 
--  You should have received a copy of the GNU General Public License
 
--  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
--
 
 
 
 
 
--
--      sc_sys.vhd
--      sc_sys.vhd
--
--
--      counter, interrrupt handling and watchdog bit
--      counter, interrrupt handling and watchdog bit
--
--
--      Author: Martin Schoeberl        martin@good-ear.com
--      Author: Martin Schoeberl        martin@jopdesign.com
--
--
--              address map:
--              address map:
--
--
--                      0        read clk counter, write irq ena
--                      0        read clk counter, write irq ena
--                      1       read 1 MHz counter, write timer val (us) + irq ack
--                      1       read 1 MHz counter, write timer val (us)
--                      2       write generates sw-int (for yield())
--                      2       write generates sw-int (for yield())
--                      3       write wd port
--                      3       write wd port
--                      4       write generates SW exception, read exception reason
--                      4       write generates SW exception, read exception reason
--
--
--      todo:
--      todo:
Line 20... Line 41...
--      2003-08-15      us counter, irq added
--      2003-08-15      us counter, irq added
--      2005-11-30      change interface to SimpCon
--      2005-11-30      change interface to SimpCon
--      2006-01-11      added exception
--      2006-01-11      added exception
--      2007-03-17      changed interrupts to records
--      2007-03-17      changed interrupts to records
--  2007-06-01  changed name from sc_cnt to sc_sys
--  2007-06-01  changed name from sc_cnt to sc_sys
 
--  2007-11-22  added global lock and bootup of CMP
 
--      2007-12-03      prioritized interrupt processing
 
--  2007-12-07  global lock redesign
 
 
 
 
 
--
 
--      state for a single interrupt
--
--
 
library ieee;
 
use ieee.std_logic_1164.all;
 
use ieee.numeric_std.all;
 
 
 
entity intstate is
 
 
 
port (
 
        clk             : in std_logic;
 
        reset   : in std_logic;
 
 
 
        irq             : in std_logic;         -- external request
 
        ena             : in std_logic;         -- local enable
 
        ack             : in std_logic;         -- is served
 
        clear   : in std_logic;         -- reset pending interrupt
 
        pending : out std_logic         -- the output request
 
);
 
end intstate;
 
 
 
architecture rtl of intstate is
 
 
 
        signal flag             : std_logic;
 
 
 
begin
 
 
 
--      TODO: add minimum interarrival time
 
 
 
process(clk, reset) begin
 
 
 
        if reset='1' then
 
                flag <= '0';
 
        elsif rising_edge(clk) then
 
                if ack='1' or clear='1' then
 
                        flag <= '0';
 
                elsif irq='1' then
 
                        flag <= '1';
 
                end if;
 
        end if;
 
 
 
end process;
 
 
 
        pending <= flag and ena;
 
 
 
end rtl;
 
 
 
--
 
--      the sc_sys component
 
--
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.numeric_std.all;
 
 
use work.jop_types.all;
use work.jop_types.all;
 
 
entity sc_sys is
entity sc_sys is
 
 
generic (addr_bits : integer;
generic (addr_bits : integer;
        clk_freq : integer;
        clk_freq : integer;
        cpu_id   : integer);
        cpu_id   : integer;
 
        cpu_cnt  : integer;
 
        num_io_int : integer := 2);             -- a default value to play with SW interrupts
port (
port (
        clk             : in std_logic;
        clk             : in std_logic;
        reset   : in std_logic;
        reset   : in std_logic;
 
 
-- SimpCon interface
-- SimpCon interface
Line 48... Line 124...
        rdy_cnt         : out unsigned(1 downto 0);
        rdy_cnt         : out unsigned(1 downto 0);
 
 
--
--
--      Interrupts from IO devices
--      Interrupts from IO devices
--
--
        irq_in          : out irq_in_type;
        irq_in          : out irq_bcf_type;
 
        irq_out         : in irq_ack_type;
        exc_req         : in exception_type;
        exc_req         : in exception_type;
 
 
        sync_out : in sync_out_type;
        io_int          : in std_logic_vector(num_io_int-1 downto 0) := "00";
 
 
 
        sync_out : in sync_out_type := NO_SYNC;
        sync_in  : out sync_in_type;
        sync_in  : out sync_in_type;
 
 
        wd                              : out std_logic
        wd                              : out std_logic;
 
 
 
        -- remove the comment for RAM access counting
 
        -- ram_count    : in std_logic;
 
 
 
        inval           : out std_logic
 
 
);
);
end sc_sys ;
end sc_sys ;
 
 
architecture rtl of sc_sys is
architecture rtl of sc_sys is
Line 68... Line 152...
        signal us_cnt                   : std_logic_vector(31 downto 0);
        signal us_cnt                   : std_logic_vector(31 downto 0);
 
 
        constant div_val        : integer := clk_freq/1000000-1;
        constant div_val        : integer := clk_freq/1000000-1;
 
 
        signal timer_int                : std_logic;
        signal timer_int                : std_logic;
        signal yield_int                : std_logic;
 
        signal int_ack                  : std_logic;
 
 
 
        signal timer                    : std_logic;
        signal timer_cnt                : std_logic_vector(31 downto 0);
        signal yield                    : std_logic;
 
 
 
        signal irq_cnt                  : std_logic_vector(31 downto 0);
 
        signal timer_equ                : std_logic;
        signal timer_equ                : std_logic;
        signal timer_dly                : std_logic;
        signal timer_dly                : std_logic;
 
 
        signal exc_type                 : std_logic_vector(7 downto 0);
        signal exc_type                 : std_logic_vector(7 downto 0);
 
 
        signal cpu_identity     : std_logic_vector(31 downto 0);
        signal cpu_identity     : std_logic_vector(31 downto 0);
 
        signal lock_reqest              : std_logic;
 
 
 
        -- remove the comment for RAM access counting
 
        -- signal ram_counter   : std_logic_vector(31 downto 0);
 
 
 
 
 
        signal cnt_ena                  : unsigned(31 downto 0);
 
 
 
--
 
--      signals for interrupt handling
 
--
 
        signal int_pend         : std_logic;
 
        signal int_ena          : std_logic;
 
        signal exc_pend         : std_logic;
 
        signal irq_gate         : std_logic;
 
        signal irq_dly          : std_logic;
 
        signal exc_dly          : std_logic;
 
 
 
--
 
--      signals for interrupt source state machines
 
--
 
        constant NUM_INT        : integer := num_io_int+1;              -- plus timer interrupt
 
        signal hwreq            : std_logic_vector(NUM_INT-1 downto 0);
 
        signal swreq            : std_logic_vector(NUM_INT-1 downto 0);
 
        signal intreq           : std_logic_vector(NUM_INT-1 downto 0);
 
        signal mask                     : std_logic_vector(NUM_INT-1 downto 0);
 
        signal ack                      : std_logic_vector(NUM_INT-1 downto 0);
 
        signal pending          : std_logic_vector(NUM_INT-1 downto 0);
 
        signal prioint          : std_logic_vector(4 downto 0);
 
        signal intnr            : std_logic_vector(4 downto 0);          -- processing int number
 
        signal clearall         : std_logic;
 
 
begin
begin
 
 
        cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32));
        cpu_identity <= std_logic_vector(to_unsigned(cpu_id,32));
        rdy_cnt <= "00";        -- no wait states
        rdy_cnt <= "11" when (sync_out.halted='1' and lock_reqest='1') else "00";
 
 
--
--
--      read cnt values
--      read cnt values
--
--
process(clk, reset)
process(clk, reset)
begin
begin
 
 
        if (reset='1') then
        if reset='1' then
                rd_data <= (others => '0');
                rd_data <= (others => '0');
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                if rd='1' then
                if rd='1' then
                        case address(2 downto 0) is
                        case address(3 downto 0) is
                                when "000" =>
                                when "0000" =>
                                        rd_data <= clock_cnt;
                                        rd_data <= clock_cnt;
                                when "001" =>
                                when "0001" =>
                                        rd_data <= us_cnt;
                                        rd_data <= us_cnt;
                                when "100" =>
                                when "0010" =>
 
                                        rd_data(4 downto 0) <= intnr;
 
                                        rd_data(31 downto 5) <= (others => '0');
 
                                when "0100" =>
                                        rd_data(7 downto 0) <= exc_type;
                                        rd_data(7 downto 0) <= exc_type;
                                        rd_data(31 downto 8) <= (others => '0');
                                        rd_data(31 downto 8) <= (others => '0');
                                when "110" =>
                                when "0101" =>
 
                                        rd_data(0) <= lock_reqest;
 
                                        rd_data(31 downto 1) <= (others => '0');
 
                                when "0110" =>
                                        rd_data <= cpu_identity;
                                        rd_data <= cpu_identity;
--                              when "111" =>
                                when "0111" =>
                                when others =>
 
                                        rd_data(0) <= sync_out.s_out;
                                        rd_data(0) <= sync_out.s_out;
                                        rd_data(31 downto 1) <= (others => '0');
                                        rd_data(31 downto 1) <= (others => '0');
 
                                -- remove the comment for RAM access counting
 
                                -- when "1010" =>
 
                                --      rd_data(31 downto 0) <= ram_counter;
 
                                when "1011" =>
 
                                        rd_data <= std_logic_vector(to_unsigned(cpu_cnt, 32));
 
                                when "1111" =>
 
                                        -- nothing, cache inval is write only
 
                                when others =>
 
                                        -- nothing
                        end case;
                        end case;
                end if;
                end if;
        end if;
        end if;
 
 
end process;
end process;
 
 
--
--
--      compare timer value and us counter
--      compare timer value and us counter
--      and generate single shot
--      and generate single shot
--
--
process(us_cnt, irq_cnt) begin
process(us_cnt, timer_cnt) begin
        timer_equ <= '0';
        timer_equ <= '0';
        if us_cnt = irq_cnt then
        if us_cnt = timer_cnt then
                timer_equ <= '1';
                timer_equ <= '1';
        end if;
        end if;
end process;
end process;
 
 
process(clk, reset, timer_equ) begin
process(clk, reset) begin
        if (reset='1') then
        if reset='1' then
                timer_dly <= '0';
                timer_dly <= '0';
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
                timer_dly <= timer_equ;
                timer_dly <= timer_equ;
        end if;
        end if;
end process;
end process;
Line 143... Line 266...
        timer_int <= timer_equ and not timer_dly;
        timer_int <= timer_equ and not timer_dly;
 
 
--
--
--      int processing from timer and yield request
--      int processing from timer and yield request
--
--
process(clk, reset, timer_int, yield_int) begin
 
 
 
        if (reset='1') then
        hwreq(0) <= timer_int;
                timer <= '0';
        hwreq(NUM_INT-1 downto 1) <= io_int;
                yield <= '0';
 
        elsif rising_edge(clk) then
process(prioint, irq_out.ack_irq) begin
                if int_ack='1' then
        ack <= (others => '0');
                        timer <= '0';
        ack(to_integer(unsigned(prioint))) <= irq_out.ack_irq;
                        yield <= '0';
end process;
                else
 
                        if timer_int='1' then
        gen_int: for i in 0 to NUM_INT-1 generate
                                timer <= '1';
                intreq(i) <= hwreq(i) or swreq(i);
                        end if;
                cis: entity work.intstate
                        if yield_int='1' then
                        port map(clk, reset,
                                yield <= '1';
                                irq => intreq(i),
 
                                ena => mask(i),
 
                                ack => ack(i),
 
                                clear => clearall,
 
                                pending => pending(i)
 
                        );
 
 
 
 
 
        end generate;
 
 
 
-- find highest priority pending interrupt
 
process(pending) begin
 
 
 
        int_pend <= '0';
 
        prioint <= (others => '0');
 
        for i in NUM_INT-1 downto 0 loop
 
                if pending(i)='1' then
 
                        int_pend <= '1';
 
                        prioint <= std_logic_vector(to_unsigned(i, 5));
 
                        exit;
                        end if;
                        end if;
 
        end loop;
 
end process;
 
 
 
--
 
--      interrupt processing
 
--
 
process(clk, reset) begin
 
 
 
        if reset='1' then
 
                irq_dly <= '0';
 
                exc_dly <= '0';
 
                intnr <= (others => '0');
 
 
 
        elsif rising_edge(clk) then
 
 
 
                irq_dly <= irq_gate;
 
                exc_dly <= exc_pend;
 
                -- save processing interrupt number
 
                if irq_out.ack_irq='1' then
 
                        intnr <= prioint;
                end if;
                end if;
 
 
        end if;
        end if;
 
 
end process;
end process;
 
 
        irq_in.irq <= timer or yield;
        irq_gate <= int_pend and int_ena;
 
        irq_in.irq <= irq_gate and not irq_dly;
 
        irq_in.exc <= exc_pend and not exc_dly;
 
        irq_in.ena <= int_ena;
 
 
 
 
 
 
--
--
--      counters
--      counters
--              pre_scale is 8 bit => fmax = 255 MHz
--              pre_scale is 8 bit => fmax = 255 MHz
Line 199... Line 365...
process(clk, reset)
process(clk, reset)
 
 
begin
begin
        if (reset='1') then
        if (reset='1') then
 
 
                irq_in.irq_ena <= '0';
                int_ena <= '0';
                irq_cnt <= (others => '0');
                timer_cnt <= (others => '0');
                int_ack <= '0';
 
                wd <= '0';
                wd <= '0';
                sync_in.s_in <= '0';
                sync_in.s_in <= '0';
 
                sync_in.lock_req <= '0';
 
                lock_reqest <= '0';
 
 
                exc_type <= (others => '0');
                exc_type <= (others => '0');
                irq_in.exc_int <= '0';
                exc_pend <= '0';
 
 
 
                swreq <= (others => '0');
 
                mask <= (others => '0');
 
                clearall <= '0';
 
 
        elsif rising_edge(clk) then
        elsif rising_edge(clk) then
 
 
                int_ack <= '0';
                exc_pend <= '0';
                yield_int <= '0';
                swreq <= (others => '0');
 
                clearall <= '0';
 
                inval <= '0';
 
 
                irq_in.exc_int <= '0';
                -- disable interrupts on a taken interrupt or excption
 
                if irq_out.ack_irq='1' or irq_out.ack_exc='1' then
 
                        int_ena <= '0';
 
                end if;
 
 
 
                -- exceptions from core or memory
                if exc_req.spov='1' then
                if exc_req.spov='1' then
                        exc_type(2 downto 0) <= EXC_SPOV;
                        exc_type(2 downto 0) <= EXC_SPOV;
                        irq_in.exc_int <= '1';
                        exc_pend <= '1';
                end if;
                end if;
                if exc_req.np='1' then
                if exc_req.np='1' then
                        exc_type(2 downto 0) <= EXC_NP;
                        exc_type(2 downto 0) <= EXC_NP;
                        irq_in.exc_int <= '1';
                        exc_pend <= '1';
                end if;
                end if;
                if exc_req.ab='1' then
                if exc_req.ab='1' then
                        exc_type(2 downto 0) <= EXC_AB;
                        exc_type(2 downto 0) <= EXC_AB;
                        irq_in.exc_int <= '1';
                        exc_pend <= '1';
                end if;
                end if;
 
 
                if wr='1' then
                if wr='1' then
                        case address(2 downto 0) is
                        case address(3 downto 0) is
                                when "000" =>
                                when "0000" =>
                                        irq_in.irq_ena <= wr_data(0);
                                        int_ena <= wr_data(0);
                                when "001" =>
                                when "0001" =>
                                        irq_cnt <= wr_data;
                                        timer_cnt <= wr_data;
                                        int_ack <= '1';
                                when "0010" =>
                                when "010" =>
                                        swreq(to_integer(unsigned(wr_data))) <= '1';
                                        yield_int <= '1';
                                when "0011" =>
                                when "011" =>
 
                                        wd <= wr_data(0);
                                        wd <= wr_data(0);
                                when "100" =>
                                when "0100" =>
                                        exc_type <= wr_data(7 downto 0);
                                        exc_type <= wr_data(7 downto 0);
                                        irq_in.exc_int <= '1';
                                        exc_pend <= '1';
                                when "110" =>
                                when "0101" =>
 
                                        sync_in.lock_req <= wr_data(0);
 
                                        lock_reqest <= wr_data(0);
 
                                        -- implicit cache invalidation on monitorenter
 
                                        inval <= wr_data(0);
 
                                when "0110" =>
                                        -- nothing, processor id is read only
                                        -- nothing, processor id is read only
                                when others =>
                                when "0111" =>
--                              when "111" =>
 
                                        sync_in.s_in <= wr_data(0);
                                        sync_in.s_in <= wr_data(0);
 
                                when "1000" =>
 
                                        mask <= wr_data(NUM_INT-1 downto 0);
 
                                when "1001" =>
 
                                        clearall <= '1';
 
                                when "1010" =>
 
                                        -- nothing, ram_counter is read only
 
                                when "1111" =>
 
                                        -- explicit cache invalidation
 
                                        inval <= '1';
 
                                when others =>
                        end case;
                        end case;
                end if;
                end if;
 
 
        end if;
        end if;
end process;
end process;
 
 
 
-- remove the comment for RAM access counting
 
-- process(clk, reset)
 
-- begin
 
--      if reset = '1' then
 
--              ram_counter <= (others => '0');
 
--      elsif rising_edge(clk) then
 
--              if (ram_count='0') then
 
--                      ram_counter <= std_logic_vector(unsigned(ram_counter) + 1);
 
--              end if;
 
--      end if;
 
-- end process;
 
 
end rtl;
end rtl;
 
 
 No newline at end of file
 No newline at end of file

powered by: WebSVN 2.1.0

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