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; i_stall: IN std_logic; o_instr_addr: OUT std_logic_vector(31 DOWNTO 0); i_instr_data: IN std_logic_vector(31 DOWNTO 0); o_data_addr: OUT std_logic_vector(31 DOWNTO 0); i_data_rd_data: IN std_logic_vector(31 DOWNTO 0); o_data_wr_data: OUT std_logic_vector(31 DOWNTO 0); o_data_wr_en: OUT std_logic_vector( 3 DOWNTO 0) ); END ENTITY e_mips_core; ARCHITECTURE a_mips_core OF e_mips_core IS SIGNAL s_stall: std_logic; SIGNAL s_stall_data_rd: std_logic; SIGNAL r_pc: std_logic_vector(31 DOWNTO 0); SIGNAL n_pc: std_logic_vector(31 DOWNTO 0); SIGNAL s_instr: std_logic_vector(31 DOWNTO 0); SIGNAL n_reg_s: std_logic_vector( 4 DOWNTO 0); SIGNAL n_reg_t: std_logic_vector( 4 DOWNTO 0); SIGNAL n_reg_d: std_logic_vector( 4 DOWNTO 0); SIGNAL n_imm_a: std_logic_vector( 4 DOWNTO 0); SIGNAL n_imm_16: std_logic_vector(15 DOWNTO 0); SIGNAL n_imm_26: std_logic_vector(25 DOWNTO 0); SIGNAL n_op: t_op; SIGNAL n_link: t_link; SIGNAL n_cmp: t_cmp; SIGNAL n_alu: t_alu; SIGNAL n_imm: t_imm; SIGNAL n_ldst: t_ldst; SIGNAL r_reg_s: std_logic_vector( 4 DOWNTO 0); SIGNAL r_reg_t: std_logic_vector( 4 DOWNTO 0); SIGNAL r_reg_d: std_logic_vector( 4 DOWNTO 0); SIGNAL r_imm_a: std_logic_vector( 4 DOWNTO 0); SIGNAL r_imm_16: std_logic_vector(15 DOWNTO 0); SIGNAL r_imm_26: std_logic_vector(25 DOWNTO 0); SIGNAL r_op: t_op; SIGNAL r_link: t_link; SIGNAL r_cmp: t_cmp; SIGNAL r_alu: t_alu; SIGNAL r_imm: t_imm; SIGNAL r_ldst: t_ldst; SIGNAL s_val_s: std_logic_vector(31 DOWNTO 0); SIGNAL s_val_t: std_logic_vector(31 DOWNTO 0); SIGNAL s_alu_op1: std_logic_vector(31 DOWNTO 0); SIGNAL s_alu_op2: std_logic_vector(31 DOWNTO 0); SIGNAL s_alu_res: std_logic_vector(31 DOWNTO 0); SIGNAL s_cmp_op1: std_logic_vector(31 DOWNTO 0); SIGNAL s_cmp_op2: std_logic_vector(31 DOWNTO 0); SIGNAL s_cmp_res: std_logic; SIGNAL s_reg_wr_alu_no: std_logic_vector( 4 DOWNTO 0); SIGNAL s_reg_wr_alu_data: std_logic_vector(31 DOWNTO 0); SIGNAL s_reg_wr_alu_en: std_logic; SIGNAL s_reg_wr_data_no: std_logic_vector( 4 DOWNTO 0); SIGNAL s_reg_wr_data_data: std_logic_vector(31 DOWNTO 0); SIGNAL s_reg_wr_data_en: std_logic; SIGNAL s_reg_wr_hi_lo_no: std_logic_vector( 4 DOWNTO 0); SIGNAL s_reg_wr_hi_lo_data: std_logic_vector(31 DOWNTO 0); SIGNAL s_reg_wr_hi_lo_en: std_logic; SIGNAL s_reg_wr_no: std_logic_vector( 4 DOWNTO 0); SIGNAL s_reg_wr_data: std_logic_vector(31 DOWNTO 0); SIGNAL s_reg_wr_en: std_logic; SIGNAL s_data_addr: std_logic_vector(31 DOWNTO 0); TYPE t_data_rd IS (data_rd_idle, data_rd_read); SIGNAL r_data_rd: t_data_rd; SIGNAL n_data_rd: t_data_rd; SIGNAL n_reg_lo: std_logic_vector(31 DOWNTO 0); SIGNAL n_reg_hi: std_logic_vector(31 DOWNTO 0); SIGNAL r_reg_lo: std_logic_vector(31 DOWNTO 0); SIGNAL r_reg_hi: std_logic_vector(31 DOWNTO 0); COMPONENT e_mips_decoder IS PORT ( i_instr: IN std_logic_vector(31 DOWNTO 0); o_reg_s: OUT std_logic_vector( 4 DOWNTO 0); o_reg_t: OUT std_logic_vector( 4 DOWNTO 0); o_reg_d: 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; o_ldst: OUT t_ldst ); 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; COMPONENT e_mips_cmp IS PORT ( i_cmp: IN t_cmp; i_op1: IN std_logic_vector(31 DOWNTO 0); i_op2: IN std_logic_vector(31 DOWNTO 0); o_res: OUT std_logic ); END COMPONENT e_mips_cmp; BEGIN s_stall <= i_stall OR s_stall_data_rd; decoder: e_mips_decoder PORT MAP ( i_instr => s_instr, o_reg_s => n_reg_s, o_reg_t => n_reg_t, o_reg_d => n_reg_d, o_imm_a => n_imm_a, o_imm_16 => n_imm_16, o_imm_26 => n_imm_26, o_op => n_op, o_link => n_link, o_cmp => n_cmp, o_alu => n_alu, o_imm => n_imm, o_ldst => n_ldst ); regs: e_mips_regs PORT MAP ( rst => rst, clk => clk, i_rd_a_no => r_reg_s, o_rd_a_data => s_val_s, i_rd_b_no => r_reg_t, o_rd_b_data => s_val_t, i_wr_no => s_reg_wr_no, i_wr_data => s_reg_wr_data, i_wr_en => s_reg_wr_en ); alu: e_mips_alu PORT MAP ( i_alu => r_alu, i_op1 => s_alu_op1, i_op2 => s_alu_op2, o_res => s_alu_res ); cmp: e_mips_cmp PORT MAP ( i_cmp => r_cmp, i_op1 => s_cmp_op1, i_op2 => s_cmp_op2, o_res => s_cmp_res ); p_sync_pc: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_pc <= (OTHERS => '0'); ELSIF rising_edge(clk) THEN IF s_stall = '0' THEN r_pc <= n_pc; END IF; END IF; END PROCESS p_sync_pc; p_fetch: PROCESS(n_pc, i_instr_data) BEGIN o_instr_addr <= n_pc; s_instr <= i_instr_data; END PROCESS p_fetch; p_sync_dec2ex: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_reg_s <= (OTHERS => '0'); r_reg_t <= (OTHERS => '0'); r_reg_d <= (OTHERS => '0'); r_imm_a <= (OTHERS => '0'); r_imm_16 <= (OTHERS => '0'); r_imm_26 <= (OTHERS => '0'); r_op <= op_none; r_link <= link_none; r_cmp <= cmp_none; r_alu <= alu_none; r_imm <= imm_none; r_ldst <= ldst_none; ELSIF rising_edge(clk) THEN IF s_stall = '0' THEN r_reg_s <= n_reg_s; r_reg_t <= n_reg_t; r_reg_d <= n_reg_d; r_imm_a <= n_imm_a; r_imm_16 <= n_imm_16; r_imm_26 <= n_imm_26; r_op <= n_op; r_link <= n_link; r_cmp <= n_cmp; r_alu <= n_alu; r_imm <= n_imm; r_ldst <= n_ldst; END IF; END IF; END PROCESS p_sync_dec2ex; p_alu_in: PROCESS(r_op, r_imm, s_val_s, s_val_t, r_imm_a, r_imm_16) BEGIN s_alu_op1 <= (OTHERS => '0'); s_alu_op2 <= (OTHERS => '0'); IF r_op = op_alu THEN CASE r_imm IS WHEN imm_none => s_alu_op1 <= s_val_s; s_alu_op2 <= s_val_t; WHEN imm_a => s_alu_op1(4 DOWNTO 0) <= r_imm_a; s_alu_op2 <= s_val_t; WHEN imm_16se => s_alu_op1 <= s_val_s; s_alu_op2(15 DOWNTO 0) <= r_imm_16; s_alu_op2(31 DOWNTO 16) <= (OTHERS => r_imm_16(15)); WHEN imm_16ze => s_alu_op1 <= s_val_s; s_alu_op2(15 DOWNTO 0) <= r_imm_16; WHEN OTHERS => NULL; END CASE; END IF; END PROCESS p_alu_in; p_alu_out: PROCESS(r_op, r_imm, r_reg_t, r_reg_d, s_alu_res) BEGIN s_reg_wr_alu_no <= (OTHERS => '0'); s_reg_wr_alu_data <= (OTHERS => '0'); s_reg_wr_alu_en <= '0'; IF r_op = op_alu THEN CASE r_imm IS WHEN imm_none | imm_a => s_reg_wr_alu_no <= r_reg_d; s_reg_wr_alu_data <= s_alu_res; s_reg_wr_alu_en <= '1'; WHEN imm_16se | imm_16ze => s_reg_wr_alu_no <= r_reg_t; s_reg_wr_alu_data <= s_alu_res; s_reg_wr_alu_en <= '1'; WHEN OTHERS => NULL; END CASE; END IF; END PROCESS p_alu_out; p_cmp_in: PROCESS(r_op, s_val_s, s_val_t) BEGIN s_cmp_op1 <= (OTHERS => '0'); s_cmp_op2 <= (OTHERS => '0'); IF r_op = op_j THEN s_cmp_op1 <= s_val_s; s_cmp_op2 <= s_val_t; END IF; END PROCESS p_cmp_in; p_reg_wr: PROCESS(s_stall, s_reg_wr_alu_no, s_reg_wr_alu_data, s_reg_wr_alu_en, s_reg_wr_data_no, s_reg_wr_data_data, s_reg_wr_data_en, s_reg_wr_hi_lo_no, s_reg_wr_hi_lo_data, s_reg_wr_hi_lo_en) BEGIN s_reg_wr_no <= (OTHERS => '0'); s_reg_wr_data <= (OTHERS => '0'); s_reg_wr_en <= '0'; IF s_stall = '0' THEN IF s_reg_wr_alu_en = '1' THEN s_reg_wr_no <= s_reg_wr_alu_no; s_reg_wr_data <= s_reg_wr_alu_data; s_reg_wr_en <= '1'; ELSIF s_reg_wr_data_en = '1' THEN s_reg_wr_no <= s_reg_wr_data_no; s_reg_wr_data <= s_reg_wr_data_data; s_reg_wr_en <= '1'; ELSIF s_reg_wr_hi_lo_en = '1' THEN s_reg_wr_no <= s_reg_wr_hi_lo_no; s_reg_wr_data <= s_reg_wr_hi_lo_data; s_reg_wr_en <= '1'; END IF; END IF; END PROCESS p_reg_wr; p_next_pc: PROCESS(r_pc, r_op, r_imm, s_cmp_res, r_imm_16, r_imm_26) VARIABLE v_pc: signed(31 DOWNTO 0); VARIABLE v_rel: signed(17 DOWNTO 0); BEGIN IF r_op = op_j AND s_cmp_res = '1' THEN IF r_imm = imm_26 THEN n_pc <= r_pc(31 DOWNTO 28) & r_imm_26 & "00"; ELSE n_pc <= std_logic_vector(signed(r_pc) + signed(r_imm_16 & "00")); END IF; ELSE n_pc <= std_logic_vector(signed(r_pc) + to_signed(4, 32)); END IF; END PROCESS p_next_pc; p_data_addr: PROCESS(r_op, s_val_s, r_imm_16) VARIABLE v_ofs: signed(31 DOWNTO 0); VARIABLE v_addr: signed(31 DOWNTO 0); BEGIN s_data_addr <= (OTHERS => '0'); IF r_op = op_l OR r_op = op_s THEN v_ofs(15 DOWNTO 0) := signed(r_imm_16); v_ofs(31 DOWNTO 16) := (OTHERS => r_imm_16(15)); v_addr := signed(s_val_s) + v_ofs; s_data_addr <= std_logic_vector(v_addr); END IF; END PROCESS p_data_addr; o_data_addr <= s_data_addr(31 DOWNTO 2) & "00"; p_data_rd: PROCESS(r_data_rd, r_op, r_ldst, s_data_addr, r_reg_t, i_data_rd_data, s_val_t) VARIABLE v_b: std_logic_vector( 7 DOWNTO 0); VARIABLE v_h: std_logic_vector(15 DOWNTO 0); VARIABLE v_w: std_logic_vector(31 DOWNTO 0); BEGIN s_stall_data_rd <= '0'; n_data_rd <= data_rd_idle; s_reg_wr_data_no <= (OTHERS => '0'); s_reg_wr_data_data <= (OTHERS => '0'); s_reg_wr_data_en <= '0'; CASE r_data_rd IS WHEN data_rd_idle => IF r_op = op_l THEN s_stall_data_rd <= '1'; n_data_rd <= data_rd_read; END IF; WHEN data_rd_read => CASE r_ldst IS WHEN ldst_b | ldst_bu => CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => v_b := i_data_rd_data( 7 DOWNTO 0); WHEN "01" => v_b := i_data_rd_data(15 DOWNTO 8); WHEN "10" => v_b := i_data_rd_data(23 DOWNTO 16); WHEN "11" => v_b := i_data_rd_data(31 DOWNTO 24); WHEN OTHERS => NULL; END CASE; s_reg_wr_data_data(7 DOWNTO 0) <= v_b; IF r_ldst = ldst_b THEN s_reg_wr_data_data(31 DOWNTO 8) <= (OTHERS => v_b(7)); END IF; WHEN ldst_h | ldst_hu => CASE s_data_addr(1 DOWNTO 1) IS WHEN "0" => v_h := i_data_rd_data(15 DOWNTO 0); WHEN "1" => v_h := i_data_rd_data(31 DOWNTO 16); WHEN OTHERS => NULL; END CASE; s_reg_wr_data_data(15 DOWNTO 0) <= v_h; IF r_ldst = ldst_h THEN s_reg_wr_data_data(31 DOWNTO 16) <= (OTHERS => v_h(15)); END IF; WHEN ldst_w => s_reg_wr_data_data <= i_data_rd_data; WHEN ldst_wl => v_w := s_val_t; CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => v_w(31 DOWNTO 24) := i_data_rd_data( 7 DOWNTO 0); WHEN "01" => v_w(31 DOWNTO 16) := i_data_rd_data(15 DOWNTO 0); WHEN "10" => v_w(31 DOWNTO 8) := i_data_rd_data(23 DOWNTO 0); WHEN "11" => v_w(31 DOWNTO 0) := i_data_rd_data(31 DOWNTO 0); WHEN OTHERS => NULL; END CASE; s_reg_wr_data_data <= v_w; WHEN ldst_wr => v_w := s_val_t; CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => v_w(31 DOWNTO 0) := i_data_rd_data(31 DOWNTO 0); WHEN "01" => v_w(23 DOWNTO 0) := i_data_rd_data(31 DOWNTO 8); WHEN "10" => v_w(15 DOWNTO 0) := i_data_rd_data(31 DOWNTO 16); WHEN "11" => v_w( 7 DOWNTO 0) := i_data_rd_data(31 DOWNTO 24); WHEN OTHERS => NULL; END CASE; s_reg_wr_data_data <= v_w; WHEN OTHERS => NULL; END CASE; s_reg_wr_data_no <= r_reg_t; s_reg_wr_data_en <= '1'; WHEN OTHERS => NULL; END CASE; END PROCESS p_data_rd; p_sync_data_rd: PROCESS(rst, clk) BEGIN IF rst = '1' THEN r_data_rd <= data_rd_idle; ELSIF rising_edge(clk) THEN IF i_stall = '0' THEN r_data_rd <= n_data_rd; END IF; END IF; END PROCESS p_sync_data_rd; p_data_wr: PROCESS(r_op, r_ldst, s_data_addr, s_val_t) BEGIN o_data_wr_data <= (OTHERS => '0'); o_data_wr_en <= "0000"; IF r_op = op_s THEN CASE r_ldst IS WHEN ldst_b => CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => o_data_wr_data( 7 DOWNTO 0) <= s_val_t(7 DOWNTO 0); o_data_wr_en <= "0001"; WHEN "01" => o_data_wr_data(15 DOWNTO 8) <= s_val_t(7 DOWNTO 0); o_data_wr_en <= "0010"; WHEN "10" => o_data_wr_data(23 DOWNTO 16) <= s_val_t(7 DOWNTO 0); o_data_wr_en <= "0100"; WHEN "11" => o_data_wr_data(31 DOWNTO 24) <= s_val_t(7 DOWNTO 0); o_data_wr_en <= "1000"; WHEN OTHERS => NULL; END CASE; WHEN ldst_h => CASE s_data_addr(1 DOWNTO 1) IS WHEN "0" => o_data_wr_data(15 DOWNTO 0) <= s_val_t(15 DOWNTO 0); o_data_wr_en <= "0011"; WHEN "1" => o_data_wr_data(31 DOWNTO 16) <= s_val_t(15 DOWNTO 0); o_data_wr_en <= "1100"; WHEN OTHERS => NULL; END CASE; WHEN ldst_w => o_data_wr_data <= s_val_t; o_data_wr_en <= "1111"; WHEN ldst_wl => CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => o_data_wr_data( 7 DOWNTO 0) <= s_val_t(31 DOWNTO 24); o_data_wr_en <= "0001"; WHEN "01" => o_data_wr_data(15 DOWNTO 0) <= s_val_t(31 DOWNTO 16); o_data_wr_en <= "0011"; WHEN "10" => o_data_wr_data(23 DOWNTO 0) <= s_val_t(31 DOWNTO 8); o_data_wr_en <= "0111"; WHEN "11" => o_data_wr_data(31 DOWNTO 0) <= s_val_t(31 DOWNTO 0); o_data_wr_en <= "1111"; WHEN OTHERS => NULL; END CASE; WHEN ldst_wr => CASE s_data_addr(1 DOWNTO 0) IS WHEN "00" => o_data_wr_data(31 DOWNTO 0) <= s_val_t(31 DOWNTO 0); o_data_wr_en <= "1111"; WHEN "01" => o_data_wr_data(31 DOWNTO 8) <= s_val_t(23 DOWNTO 0); o_data_wr_en <= "1110"; WHEN "10" => o_data_wr_data(31 DOWNTO 16) <= s_val_t(15 DOWNTO 0); o_data_wr_en <= "1100"; WHEN "11" => o_data_wr_data(31 DOWNTO 24) <= s_val_t( 7 DOWNTO 0); o_data_wr_en <= "1000"; WHEN OTHERS => NULL; END CASE; WHEN OTHERS => NULL; END CASE; END IF; END PROCESS p_data_wr; p_reg_hi_lo: PROCESS(r_reg_lo, r_reg_hi, r_op, r_reg_d, s_val_s) BEGIN n_reg_lo <= r_reg_lo; n_reg_hi <= r_reg_hi; s_reg_wr_hi_lo_no <= (OTHERS => '0'); s_reg_wr_hi_lo_data <= (OTHERS => '0'); s_reg_wr_hi_lo_en <= '0'; CASE r_op IS WHEN op_mfhi => s_reg_wr_hi_lo_no <= r_reg_d; s_reg_wr_hi_lo_data <= r_reg_hi; s_reg_wr_hi_lo_en <= '1'; WHEN op_mflo => s_reg_wr_hi_lo_no <= r_reg_d; s_reg_wr_hi_lo_data <= r_reg_lo; s_reg_wr_hi_lo_en <= '1'; WHEN op_mthi => n_reg_hi <= s_val_s; WHEN op_mtlo => n_reg_lo <= s_val_s; WHEN OTHERS => NULL; END CASE; END PROCESS p_reg_hi_lo; p_sync_reg_hi_lo: PROCESS(clk, rst) BEGIN IF rst = '1' THEN r_reg_lo <= (OTHERS => '0'); r_reg_hi <= (OTHERS => '0'); ELSIF rising_edge(clk) THEN IF s_stall = '0' THEN r_reg_lo <= n_reg_lo; r_reg_hi <= n_reg_hi; END IF; END IF; END PROCESS p_sync_reg_hi_lo; END ARCHITECTURE a_mips_core;