--------------------------------------------------------------------------
-- Project: JIPS, a portable 32-bit RISC CPU written in VHDL
-- This file: The datapath controller
--
-- Copyright (C) 2008 J. Ahrensfeld
--
-- 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/>.
--
-- For questions and ideas, please contact the author at jens@jayfield.org
--
--------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;

library work;
use work.mips_types.all;
use work.mips_instr.all;

entity idecode_rom is
	Port
	(
		nop			: in  std_logic;
		inst_in		: in  word_t;
		ctrl_out	: out ctrl_lines_t
	);
end idecode_rom;

architecture Behavioral of idecode_rom is

	signal ctrl_special		: ctrl_lines_t;
	signal ctrl_regimm		: ctrl_lines_t;
	signal ctrl_opcode		: ctrl_lines_t;

	signal rom_special : rom_special_t := gen_rom_special;
	signal rom_regimm : rom_regimm_t := gen_rom_regimm;
	signal rom_opcode : rom_opcode_t := gen_rom_opcode;

	attribute rom_style : string;
	
	attribute rom_style of rom_special: signal is "distributed";
	attribute rom_style of rom_regimm: signal is "distributed";
	attribute rom_style of rom_opcode: signal is "distributed";

begin

i_dec_special:
	process(inst_in, rom_special)
	variable func : func_t;
	begin
		func := extract_func(inst_in);
		ctrl_special <= rom_special(to_integer(func));
	end process;

i_dec_regimm:
	process(inst_in, rom_regimm)
	variable rt : reg_ptr_t;
	begin
		rt := extract_rt(inst_in);
		ctrl_regimm <= rom_regimm(to_integer(rt));
	end process;

i_dec_opcode:
	process(inst_in, rom_opcode)
	variable opc : opcode_t;
	begin
		opc := extract_opc(inst_in);
		ctrl_opcode <= rom_opcode(to_integer(opc));
	end process;

proc_decode:
	process(inst_in, ctrl_special, ctrl_regimm, ctrl_opcode, nop)
	variable opclass : opcode_t;
	begin
		opclass := extract_opc(inst_in);
		ctrl_out <= ctrl_lines_default after 2 ns;
		if nop = '0' then
			case opclass is
			when "000000" =>
				ctrl_out	<= ctrl_special after 2 ns;
			when "000001" =>
				ctrl_out	<= ctrl_regimm after 2 ns;
			when others =>
				ctrl_out	<= ctrl_opcode after 2 ns;
			end case;
		end if;	
	end process;

end Behavioral;
