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

Subversion Repositories ion

[/] [ion/] [trunk/] [vhdl/] [mips_cpu.vhdl] - Diff between revs 140 and 153

Go to most recent revision | Show entire file | Details | Blame | View Log

Rev 140 Rev 153
Line 2... Line 2...
-- ion_cpu.vhdl -- MIPS-I(tm) compatible CPU core
-- ion_cpu.vhdl -- MIPS-I(tm) compatible CPU core
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- project:       ION (http://www.opencores.org/project,ion_cpu)
-- project:       ION (http://www.opencores.org/project,ion_cpu)
-- author:        Jose A. Ruiz (ja_rd@hotmail.com)
-- author:        Jose A. Ruiz (ja_rd@hotmail.com)
-- created:       Jan/11/2011
-- created:       Jan/11/2011
-- last modified: Apr/13/2011 (ja_rd@hotmail.com)
-- last modified: Jun/05/2011 (ja_rd@hotmail.com)
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Use under the terms of the GPL.
-- Use under the terms of the GPL.
-- Software 'as is' without warranty.  Author liable for nothing.
-- Software 'as is' without warranty.  Author liable for nothing.
--
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
-- Please read file /doc/ion_project.txt for usage instructions.
 
--------------------------------------------------------------------------------
--### MIPS-I things not implemented
--### MIPS-I things not implemented
--  # Invalid instruction trapping:
 
--      * invalid opcodes do trap but the logic that prevents bad opcodes from
 
--        having side affects has not been tested yet.
 
--  # Kernel/user status
 
--  # RTE instruction (or ERET)
 
--  # Most of the CP0 registers and of course all of the CP1
 
--  # External interrupts
 
--
--
--### Things implemented but not tested
-- 1.- RTE instruction (or ERET) missing, with CP0.SR KUo/IEo & KUP/IEp flags.
--  # Memory pause input -- only tested with stub cache
-- 2.- Most of the R3000 CP0 registers and of course all of the CP1.
 
-- 3.- External interrupts missing, with CP0.SR IR, NMI and IM7..0 flags.
--
--
--### Things with provisional implementation
--### Things with provisional implementation
-- 
-- 
-- 1.- Load interlocks: the pipeline is stalled for every load instruction, even
-- 1.- Load interlocks: the pipeline is stalled for every load instruction, even
--     if the target register is not used in the following instruction. So that
--     if the target register is not used in the following instruction. So that
--     every load takes two cycles.
--     every load takes two cycles.
--     The interlock logic should check register indices (@note2)
--     The interlock logic should check register indices (@note2)
 
-- 2.- CP0 SR (status register) bits KUo/IEo & KUP/IEp are missing.
 
--     This means that EXCEPTIONS CAN'T BE NESTED in this version of the CPU.
 
-- 3.- Invalid instruction side effects:
 
--     Invalid opcodes do trap but the logic that prevents bad opcodes from
 
--     having side affects has not been tested yet.
 
-- 4.- Kernel/user status.
 
--     When in user mode, COP* instructions will trigger a 'CpU' exception.
 
--     BUT there's no address checking and user code can still access kernel 
 
--     space in this version.
 
--     Besides, see point 2 above about the missing SR bits.
--
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
 
library ieee;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_1164.all;
Line 135... Line 141...
signal p1_ir_fn :           std_logic_vector(5 downto 0);
signal p1_ir_fn :           std_logic_vector(5 downto 0);
signal p1_op_special :      std_logic;
signal p1_op_special :      std_logic;
signal p1_exception :       std_logic;
signal p1_exception :       std_logic;
signal p1_do_reg_jump :     std_logic;
signal p1_do_reg_jump :     std_logic;
signal p1_do_zero_ext_imm : std_logic;
signal p1_do_zero_ext_imm : std_logic;
 
signal p1_set_cp :          std_logic;
 
signal p1_get_cp :          std_logic;
signal p1_set_cp0 :         std_logic;
signal p1_set_cp0 :         std_logic;
signal p1_get_cp0 :         std_logic;
signal p1_get_cp0 :         std_logic;
 
signal p1_rfe :             std_logic;
signal p1_alu_op2_sel :     std_logic_vector(1 downto 0);
signal p1_alu_op2_sel :     std_logic_vector(1 downto 0);
signal p1_alu_op2_sel_set0: std_logic_vector(1 downto 0);
signal p1_alu_op2_sel_set0: std_logic_vector(1 downto 0);
signal p1_alu_op2_sel_set1: std_logic_vector(1 downto 0);
signal p1_alu_op2_sel_set1: std_logic_vector(1 downto 0);
signal p1_do_load :         std_logic;
signal p1_do_load :         std_logic;
signal p1_do_store :        std_logic;
signal p1_do_store :        std_logic;
Line 163... Line 172...
signal p1_muldiv_running :  std_logic;
signal p1_muldiv_running :  std_logic;
signal p1_muldiv_started :  std_logic;
signal p1_muldiv_started :  std_logic;
signal p1_muldiv_stall :    std_logic;
signal p1_muldiv_stall :    std_logic;
 
 
signal p1_unknown_opcode :  std_logic;
signal p1_unknown_opcode :  std_logic;
 
signal p1_cp_unavailable :  std_logic;
 
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Pipeline stage 2
-- Pipeline stage 2
 
 
signal p2_muldiv_started :  std_logic;
signal p2_muldiv_started :  std_logic;
Line 199... Line 209...
signal reset_done :         std_logic;
signal reset_done :         std_logic;
 
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- CP0 registers and signals
-- CP0 registers and signals
 
 
-- CP0[12]: status register 
-- CP0[12]: status register, KUo/IEo & KUP/IEp & KU/IE  bits
signal cp0_status :         std_logic_vector(1 downto 0);
signal cp0_status :         std_logic_vector(5 downto 0);
-- CP0[12]: status register, cache control
-- CP0[12]: status register, cache control
signal cp0_cache_control :  std_logic_vector(17 downto 16);
signal cp0_cache_control :  std_logic_vector(17 downto 16);
-- Output of CP0 register bank (only a few regs are implemented)
-- Output of CP0 register bank (only a few regs are implemented)
signal cp0_reg_read :       t_word;
signal cp0_reg_read :       t_word;
-- CP0[14]: EPC register (PC value saved at exceptions)
-- CP0[14]: EPC register (PC value saved at exceptions)
Line 591... Line 601...
         p1_alu_flags.inp1_eq_inp2)     when "111",
         p1_alu_flags.inp1_eq_inp2)     when "111",
    '1'                                 when others;
    '1'                                 when others;
 
 
-- Decode instructions that launch exceptions
-- Decode instructions that launch exceptions
p1_exception <= '1' when
p1_exception <= '1' when
    (p1_op_special='1' and p1_ir_reg(5 downto 1)="00110") or
    (p1_op_special='1' and p1_ir_reg(5 downto 1)="00110") or -- syscall/break
    p1_unknown_opcode='1'
    p1_unknown_opcode='1' or
 
    p1_cp_unavailable='1'
    else '0';
    else '0';
 
 
-- Decode MTC0/MFC0 instructions
-- Decode MTC0/MFC0 instructions (see @note3)
p1_set_cp0 <= '1' when p1_ir_reg(31 downto 21)="01000000100" else '0';
p1_set_cp  <= '1' when p1_ir_reg(31 downto 28)="0100" and
p1_get_cp0 <= '1' when p1_ir_reg(31 downto 21)="01000000000" else '0';
                       p1_ir_reg(25 downto 21)="00100" else '0';
 
p1_get_cp  <= '1' when p1_ir_reg(31 downto 28)="0100" and
 
                       p1_ir_reg(25 downto 21)="00000" else '0';
 
 
 
p1_set_cp0 <= '1' when p1_ir_reg(27 downto 26)="00" and p1_set_cp='1' else '0';
 
p1_get_cp0 <= '1' when p1_ir_reg(27 downto 26)="00" and p1_get_cp='1' else '0';
 
 
 
-- Decode RFE instruction (see @note3)
 
p1_rfe <= '1' when p1_ir_reg(31 downto 21)="01000010000" and
 
                   p1_ir_reg(5 downto 0)="010000"
 
          else '0';
 
 
-- Raise some signals for some particular group of opcodes
-- Raise some signals for some particular group of opcodes
p1_op_special <= '1' when p1_ir_op="000000" else '0'; -- group '0' opcodes
p1_op_special <= '1' when p1_ir_op="000000" else '0'; -- group '0' opcodes
p1_do_reg_jump <= '1' when p1_op_special='1' and p1_ir_fn(5 downto 1)="00100" else '0';
p1_do_reg_jump <= '1' when p1_op_special='1' and p1_ir_fn(5 downto 1)="00100" else '0';
p1_do_zero_ext_imm <= '1' when (p1_ir_op(31 downto 28)="0011") else '0';
p1_do_zero_ext_imm <= '1' when (p1_ir_op(31 downto 28)="0011") else '0';
Line 766... Line 787...
                 p1_ir_reg(20 downto 16)/="10000" and -- BLTZAL is valid 
                 p1_ir_reg(20 downto 16)/="10000" and -- BLTZAL is valid 
                 p1_ir_reg(20 downto 16)/="10001")) -- BGEZAL is valid
                 p1_ir_reg(20 downto 16)/="10001")) -- BGEZAL is valid
 
 
    else '0';
    else '0';
 
 
 
p1_cp_unavailable <= '1' when
 
    (p1_set_cp='1' and p1_set_cp0='0') or   -- mtc1..3
 
    (p1_get_cp='1' and p1_get_cp0='0') or   -- mfc1..3
 
    ((p1_get_cp0='1' or p1_set_cp0='1' or p1_rfe='1')
 
                     and cp0_status(1)='0') -- COP0 user mode
 
    else '0';
 
 
--##############################################################################
--##############################################################################
-- Pipeline registers & pipeline control logic
-- Pipeline registers & pipeline control logic
 
 
-- Stage 1 pipeline register. Involved in ALU control.
-- Stage 1 pipeline register. Involved in ALU control.
pipeline_stage1_register:
pipeline_stage1_register:
Line 997... Line 1025...
    p1_rt(15 downto  8) when "010100",  -- SH %0
    p1_rt(15 downto  8) when "010100",  -- SH %0
    p1_rt(31 downto 24) when others;
    p1_rt(31 downto 24) when others;
 
 
 
 
--##############################################################################
--##############################################################################
-- CP0 (what little is implemented of it)
-- CP0 and exception processing
 
 
 
cp0_registers:
process(clk)
process(clk)
begin
begin
    if clk'event and clk='1' then
    if clk'event and clk='1' then
        if reset='1' then
        if reset='1' then
            -- "10" => mode=kernel; ints=disabled
            -- KU/IE="10"  ==>  mode=kernel; ints=disabled
            cp0_status <= "10";
            cp0_status <= "000010";  -- bits (KUo/IEo & KUp/IEp) reset to zero
            cp0_cache_control <= "00";
            cp0_cache_control <= "00";
            cp0_cause_exc_code <= "00000";
            cp0_cause_exc_code <= "00000";
            cp0_cause_bd <= '0';
            cp0_cause_bd <= '0';
        else
        else
            -- no need to check for stall cycles when loading these
            if pipeline_stalled='0' then
            if p1_set_cp0='1' then
                if p1_exception='1' then
                -- NOTE: in MTCx, the source register is Rt
                    -- Exception: do all that needs to be done right here
                -- FIXME check for CP0 reg index
 
                cp0_status <= p1_rt(cp0_status'high downto 0);
                    -- Save PC in EPC register...
                cp0_cache_control <= p1_rt(17 downto 16);
 
            end if;
 
            if p1_exception='1' and pipeline_stalled='0' then
 
                cp0_epc <= p0_pc_restart;
                cp0_epc <= p0_pc_restart;
 
                    -- ... set KU flag to Kernel mode ...
 
                    cp0_status(1) <= '1';
 
                    -- ... and 'push' old KU/IE flag values 
 
                    cp0_status(5 downto 4) <= cp0_status(3 downto 2);
 
                    cp0_status(3 downto 2) <= cp0_status(1 downto 0);
 
 
 
                    -- Set the 'exception cause' code... 
                if p1_unknown_opcode='1' then
                if p1_unknown_opcode='1' then
                    cp0_cause_exc_code <= "01010"; -- bad opcode
                        cp0_cause_exc_code <= "01010"; -- bad opcode ('reserved')
 
                    elsif p1_cp_unavailable='1' then
 
                        -- this triggers for mtc0/mfc0 in user mode too
 
                        cp0_cause_exc_code <= "01011"; -- CP* unavailable 
                else
                else
                    if p1_ir_fn(0)='0' then
                    if p1_ir_fn(0)='0' then
                        cp0_cause_exc_code <= "01000"; -- syscall
                        cp0_cause_exc_code <= "01000"; -- syscall
                    else
                    else
                        cp0_cause_exc_code <= "01001"; -- break
                        cp0_cause_exc_code <= "01001"; -- break
                    end if;
                    end if;
                end if;
                end if;
 
                    -- ... and the BD flag for exceptions in delay slots
                cp0_cause_bd <= cp0_in_delay_slot;
                cp0_cause_bd <= cp0_in_delay_slot;
 
 
 
                -- FIXME RFE missing
 
                elsif p1_rfe='1' and cp0_status(1)='1' then
 
                    -- RFE: restore ('pop') the KU/IE flag values
 
 
 
                    cp0_status(3 downto 2) <= cp0_status(5 downto 4);
 
                    cp0_status(1 downto 0) <= cp0_status(3 downto 2);
 
 
 
                elsif p1_set_cp0='1' and cp0_status(1)='1' then
 
                    -- MTC0: load CP0[xx] with Rt
 
 
 
                    -- NOTE: in MTCx, the source register is Rt
 
                    -- FIXME this works because only SR is writeable; when 
 
                    -- CP0[13].IP1-0 are implemented, check for CP0 reg index.
 
                    cp0_status <= p1_rt(cp0_status'high downto 0);
 
                    cp0_cache_control <= p1_rt(17 downto 16);
 
                end if;
            end if;
            end if;
        end if;
        end if;
    end if;
    end if;
end process;
end process cp0_registers;
 
 
cache_enable <= cp0_cache_control(17);
cache_enable <= cp0_cache_control(17);
ic_invalidate <= cp0_cache_control(16);
ic_invalidate <= cp0_cache_control(16);
 
 
cp0_cause_ce <= "00"; -- FIXME CP* traps merged with unimplemented opcode traps
cp0_cause_ce <= "00"; -- FIXME CP* traps merged with unimplemented opcode traps
cp0_cause <= cp0_cause_bd & '0' & cp0_cause_ce &
cp0_cause <= cp0_cause_bd & '0' & cp0_cause_ce &
             X"00000" & "000" &
             X"00000" & '0' & cp0_cause_exc_code & "00";
             cp0_cause_exc_code;
 
 
 
-- FIXME the mux should mask to zero for any unused reg index
-- FIXME the mux should mask to zero for any unused reg index
with p1_c0_rs_num select cp0_reg_read <=
with p1_c0_rs_num select cp0_reg_read <=
    X"0000000" & "00" & cp0_status  when "01100",
    X"000000" & "00" & cp0_status   when "01100",
    cp0_cause                       when "01101",
    cp0_cause                       when "01101",
    cp0_epc & "00"                  when others;
    cp0_epc & "00"                  when others;
 
 
 
 
end architecture rtl;
end architecture rtl;
 
 
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- Implementation notes
-- Implementation notes
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
-- @note1 : 
-- @note1 : 
--
 
-- This is the meaning of these two signals:
-- This is the meaning of these two signals:
-- pipeline_stalled & stalled_interlock =>
-- pipeline_stalled & stalled_interlock =>
--  "00" => normal state
--  "00" => normal state
--  "01" => normal state (makes for easier decoding)
--  "01" => normal state (makes for easier decoding)
--  "10" => all stages of pipeline stalled, including rbank
--  "10" => all stages of pipeline stalled, including rbank
Line 1074... Line 1124...
-- load operation can complete while the rest of the pipeline is frozen.
-- load operation can complete while the rest of the pipeline is frozen.
--
--
-- @note2:
-- @note2:
-- The logic that checks register indices for data hazards is 'commented out'
-- The logic that checks register indices for data hazards is 'commented out'
-- because it has not been tested yet.
-- because it has not been tested yet.
 
--
 
-- @note3:
 
-- CP0 instructions (mtc0, mfc0 and rfe) are only partially decoded.
 
-- This is possible because no other VALID MIPS* opcode shares the decoded 
 
-- part; that is, we're not going to misdecode a MIPS32 opcode, but we MIGHT
 
-- mistake a bad opcode for a COP0; we'll live with that for the time being.
 
--
--------------------------------------------------------------------------------
--------------------------------------------------------------------------------
 
 
 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.