LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
USE work.mips_types.all;

ENTITY e_mips_core IS
    PORT (
        rst:   IN  std_logic;
        clk:   IN  std_logic;
        o_res: OUT std_logic_vector(31 DOWNTO 0)
    );
END ENTITY e_mips_core;

ARCHITECTURE a_mips_core OF e_mips_core IS

    SIGNAL r_instr: std_logic_vector(31 DOWNTO 0);

    SIGNAL s_src_s:  std_logic_vector( 4 DOWNTO 0);
    SIGNAL s_src_t:  std_logic_vector( 4 DOWNTO 0);
    SIGNAL s_dest:   std_logic_vector( 4 DOWNTO 0);
    SIGNAL s_imm_a:  std_logic_vector( 4 DOWNTO 0);
    SIGNAL s_imm_16: std_logic_vector(15 DOWNTO 0);
    SIGNAL s_imm_26: std_logic_vector(25 DOWNTO 0);
    SIGNAL s_op:     t_op;
    SIGNAL s_link:   t_link;
    SIGNAL s_cmp:    t_cmp;
    SIGNAL s_alu:    t_alu;
    SIGNAL s_imm:    t_imm;

    SIGNAL s_op1: std_logic_vector(31 DOWNTO 0);
    SIGNAL s_op2: std_logic_vector(31 DOWNTO 0);
    SIGNAL s_res: std_logic_vector(31 DOWNTO 0);

    COMPONENT e_mips_decoder IS
        PORT (
            i_instr:  IN  std_logic_vector(31 DOWNTO 0);
            o_src_s:  OUT std_logic_vector( 4 DOWNTO 0);
            o_src_t:  OUT std_logic_vector( 4 DOWNTO 0);
            o_dest:   OUT std_logic_vector( 4 DOWNTO 0);
            o_imm_a:  OUT std_logic_vector( 4 DOWNTO 0);
            o_imm_16: OUT std_logic_vector(15 DOWNTO 0);
            o_imm_26: OUT std_logic_vector(25 DOWNTO 0);
            o_op:     OUT t_op;
            o_link:   OUT t_link;
            o_cmp:    OUT t_cmp;
            o_alu:    OUT t_alu;
            o_imm:    OUT t_imm
        );
    END COMPONENT e_mips_decoder;

    COMPONENT e_mips_regs IS
        PORT (
            rst:         IN  std_logic;
            clk:         IN  std_logic;
            i_rd_a_no:   IN  std_logic_vector( 4 DOWNTO 0);
            o_rd_a_data: OUT std_logic_vector(31 DOWNTO 0);
            i_rd_b_no:   IN  std_logic_vector( 4 DOWNTO 0);
            o_rd_b_data: OUT std_logic_vector(31 DOWNTO 0);
            i_wr_no:     IN  std_logic_vector( 4 DOWNTO 0);
            i_wr_data:   IN  std_logic_vector(31 DOWNTO 0);
            i_wr_en:     IN  std_logic
        );
    END COMPONENT e_mips_regs;

    COMPONENT e_mips_alu IS
        PORT (
            i_alu: IN  t_alu;
            i_op1: IN  std_logic_vector(31 DOWNTO 0);
            i_op2: IN  std_logic_vector(31 DOWNTO 0);
            o_res: OUT std_logic_vector(31 DOWNTO 0)
        );
    END COMPONENT e_mips_alu;

BEGIN

    decoder: e_mips_decoder
        PORT MAP (
            i_instr  => r_instr,
            o_src_s  => s_src_s,
            o_src_t  => s_src_t,
            o_dest   => s_dest,
            o_imm_a  => s_imm_a,
            o_imm_16 => s_imm_16,
            o_imm_26 => s_imm_26,
            o_op     => s_op,
            o_link   => s_link,
            o_cmp    => s_cmp,
            o_alu    => s_alu,
            o_imm    => s_imm
        );

    regs: e_mips_regs
        PORT MAP (
            rst         => rst,
            clk         => clk,
            i_rd_a_no   => s_src_s,
            o_rd_a_data => s_op1,
            i_rd_b_no   => s_src_t,
            o_rd_b_data => s_op2,
            i_wr_no     => s_dest,
            i_wr_data   => s_res,
            i_wr_en     => '1'
        );

    alu: e_mips_alu
        PORT MAP (
            i_alu => s_alu,
            i_op1 => s_op1,
            i_op2 => s_op2,
            o_res => s_res
        );

    p_dummy_fetch: PROCESS(rst, clk)
    BEGIN
        IF rst = '1' THEN
            r_instr <= X"00000000";
        ELSIF rising_edge(clk) THEN
            r_instr <= std_logic_vector(unsigned(r_instr) + to_unsigned(1, 32));
        END IF;
    END PROCESS p_dummy_fetch;

    o_res <= s_res;

END ARCHITECTURE a_mips_core;