LIBRARY IEEE; 
USE IEEE.std_logic_1164.ALL; 
USE IEEE.std_logic_arith.ALL; 
USE IEEE.std_logic_unsigned.ALL; 


ENTITY Control IS PORT
	(Op				:	in BIT_VECTOR (5 downto 0);  
	StateIn			:	in BIT_VECTOR (3 downto 0); 
	Clk				:	in BIT;
		 
	PCWriteCond		:	out BIT;
	PCWrite			:	out BIT;
	IorD			:	out BIT;
	MemRead			:	out BIT;
	MemWrite		:	out BIT;
	IRWrite			:	out BIT;
	MemtoReg		:	out BIT;
	ALUSrcA			:	out BIT;
	RegWrite		:	out BIT;
	RegDst			:	out BIT;

	PCSource		:	out BIT_VECTOR (1 downto 0);
	ALUOp			:	out BIT_VECTOR (1 downto 0);
	ALUSrcB			:	out BIT_VECTOR (1 downto 0);  

	StateOut		:	out BIT_VECTOR (3 downto 0));

end Control;  
		 
Architecture Control_Arch of Control is  

	
BEGIN
	PROCESS (Clk) 

	--variable faltu: BIT;
	variable init: INTEGER:=0;
	BEGIN
		IF (Clk'event and Clk='1') then
		IF (init<1) then
			IF (init = 0) then
				MemRead<='1';
			END IF;
			
			init:=init+1;

		ELSE

			case StateIn is
				when "0000" =>	 

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								--RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";  

							
								--faltu:='1'; MemRead<=faltu;
								MemRead<='1';					--0
								
								ALUSrcA<='0';
								IorD<='0';
								--IRWrite<='1';
								ALUSrcB<="01";
								ALUOp<="00";
								PCWrite<='1';
								PCSource<="00";
								StateOut<="0001";
								--L3:for i in 99096 downto 0 loop 
								--	faltu:=i*5;
								--end loop L3;
								IRWrite<='1';
								--IRWrite<=faltu;
				
				when "0001" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";

								ALUSrcA<='0';					-- 1
								ALUSrcB<="11";
								ALUOp<="00";
								IF (Op="000000") then			-- R
									StateOut<="0110";
								END IF;
								IF (Op="100011") then			-- lw
									StateOut<="0010";
								END IF;
								IF (Op="101011") then			-- sw				
									StateOut<="0010";
								END IF;
								IF (Op="000100" or Op="000101") then			-- beq or bne
									StateOut<="1000";
								END IF;
								IF (Op="000010") then			-- J
									StateOut<="1001";
								END IF;
				
				when "0010" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";

								ALUSrcA<='1';					-- 2
								ALUSrcB<="10";
								ALUOp<="00";
								--IorD<='1';						-- temp redundant iord
								IF (Op="100011") then			-- lw
									StateOut<="0011";
								END IF;
								IF (Op="101011") then			-- sw				
									StateOut<="0101";
								END IF;

				when "0011" =>

								PCWriteCond<='0';
								PCWrite<='0';
								--IorD<='0';
								--MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								--ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								--ALUSrcB<="00";

								IorD<='1';
								MemRead<='1';					-- 3
								StateOut<="0100";
 

				when "0100" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								--ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								--ALUSrcB<="00";

								RegDst<='0';					-- 4
								RegWrite<='1';
								MemtoReg<='1';
								StateOut<="0000";

			
				when "0101" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								--ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								--ALUSrcB<="00";

								MemWrite<='1';					-- 5	
								IorD<='1';
								StateOut<="0000";

								
				when "0110" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";

								ALUSrcA<='1';					-- 6
								ALUSrcB<="00";
								ALUop<="10";
								StateOut<="0111";

			
				when "0111" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								--ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								--ALUOp<="00";
								--ALUSrcB<="00";			

								RegDst<='1';					-- 7
								MemtoReg<='0';
								RegWrite<='1';
								StateOut<="0000";

			
				when "1000" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";

								ALUSrcA<='1';					-- 8
								ALUSrcB<="00";
								ALUOp<="01";
								PCWriteCond<='1';
								PCSource<="01";
								StateOut<="0000";

				when "1001" =>

								PCWriteCond<='0';
								PCWrite<='0';
								IorD<='0';
								MemRead<='0';
								MemWrite<='0';
								IRWrite<='0';
								MemtoReg<='0';
								ALUSrcA<='0';
								RegWrite<='0';
								RegDst<='0';
								PCSource<="00";
								ALUOp<="00";
								ALUSrcB<="00";

								PCWrite<='1';					-- 9
								PCSource<="10";
								StateOut<="0000";



				when others => StateOut<="0000";	

			end case;			

		END IF;	
		END IF;
		
	
	END PROCESS ; 
END Control_Arch;