library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity Control_Unit is
port (
clk,reset : in std_logic;
Reg_file_wb , Reg_File_r1,Reg_File_r2 , Inst_Mem_r,inc_pc,Data_Mem_W_RBAR , ALU_Output_Mux, Data_Mem_Output_Mux,pc_w_enable, Load_Immediate: out std_logic ;
ALU_control : out std_logic_vector(3 downto 0);
--curr_state: out std_logic_vector(3 downto 0);
op_code_CU: in std_logic_vector(3 downto 0));
end Control_Unit;
architecture a_Control_Unit of Control_Unit is
subtype TargetSeqStates is bit_vector(4 downto 0);
signal curr_st, next_st: TargetSeqStates;
constant IDLE : TargetSeqStates:= "00001";
constant FETCH : TargetSeqStates:= "00011";
constant DECODE : TargetSeqStates:= "00010";
constant EX_AND : TargetSeqStates:= "00110";
constant EX_OR : TargetSeqStates:= "00100";
constant EX_XOR : TargetSeqStates:= "00101";
constant WB : TargetSeqStates:= "00111";
constant EX_NOT : TargetSeqStates:= "01111";
constant EX_ADD : TargetSeqStates:= "01110";
constant EX_SUB : TargetSeqStates:= "01010";
constant EX_SRA : TargetSeqStates:= "01011";
constant EX_SLA : TargetSeqStates:= "01001";
constant EX_SW : TargetSeqStates := "01000";
constant EX_LW : TargetSeqStates := "00000";
constant EX_MOV : TargetSeqStates :="10000";
constant EX_JMP : TargetSeqStates :="10011";
constant EX_JMP_2 : TargetSeqStates :="10010";
constant EX_LI : TargetSeqStates := "10110";
constant EX_LI_2 : TargetSeqStates := "10100";
--- Should change the states at the end. use ONE EXECUTE State only for all
--- of the instructions, and let the op-code connected to the ALU from the Instruction word
--- without the interferance of the CU
BEGIN
Main_process: process(curr_st,reset,op_code_CU)
begin
next_st <= IDLE; -- default next state condition--
case curr_st is
WHEN IDLE =>
if (reset ='1') then
next_st <= IDLE;
else
next_st <= FETCH;
end if;
WHEN FETCH =>
next_st <= DECODE;
WHEN DECODE | EX_AND | EX_OR | EX_XOR| EX_ADD | EX_SUB | EX_NOT| EX_SLA | EX_SRA|
EX_SW | EX_LW | EX_MOV| EX_JMP_2 | EX_LI_2 =>
if op_code_CU ="0001" then -- AND Instruction
next_st <= EX_AND;
elsif op_code_CU ="0010" then --OR instruction
next_st <= EX_OR;
elsif op_code_CU ="0011" then -- XOR instruction
next_st <= EX_XOR;
elsif op_code_CU= "0000" then
next_st <= EX_NOT;
elsif op_code_CU= "0110" then
next_st <= EX_ADD;
elsif op_code_CU= "0111" then
next_st <= EX_SUB;
elsif op_code_CU= "0100" then
next_st <= EX_SLA;
elsif op_code_CU= "0101" then
next_st <= EX_SRA;
elsif op_code_CU= "1111" then
next_st <= EX_SW;
elsif op_code_CU= "1110" then
next_st <= EX_LW;
elsif op_code_CU = "1101" then
next_st <= EX_MOV;
elsif op_code_CU = "1100" then
next_st <= EX_JMP;
elsif op_code_CU= "1001" then
next_st <= EX_LI;
end if;
WHEN EX_JMP =>
next_st <= EX_JMP_2;
WHEN EX_LI =>
next_st <= EX_LI_2;
WHEN others =>
next_st <= IDLE;
end case;
end process;
process (clk, reset)
begin
if (reset ='1') then
curr_st <= IDLE;
elsif (clk'event and clk='1') then
curr_st <= next_st;
end if;
end process;
FSM_Outputs: process(curr_st)
begin
case curr_st is
WHEN IDLE | FETCH =>
Reg_File_r1 <= '0';
WHEN others =>
Reg_File_r1 <= '1';
end case;
case curr_st is
WHEN IDLE | FETCH =>
Reg_File_r2 <= '0';
WHEN others =>
Reg_File_r2 <= '1';
end case;
case curr_st is
WHEN IDLE | EX_JMP | EX_JMP_2 =>
Inst_Mem_r <= '0';
WHEN others =>
Inst_Mem_r <= '1';
end case;
case curr_st is
WHEN IDLE | FETCH | EX_JMP | EX_JMP_2 | EX_SW | EX_LI =>
Reg_file_wb <= '0';
WHEN OTHERS =>
Reg_file_wb <= '1';
END case;
case curr_st is
WHEN IDLE | EX_JMP_2 | EX_JMP =>
inc_pc <= '0';
WHEN OTHERS =>
inc_pc <= '1';
END case;
case curr_st is
WHEN EX_SW =>
Data_Mem_W_RBAR <= '1';
WHEN OTHERS =>
Data_Mem_W_RBAR <= '0';
end case;
if curr_st = EX_JMP then
pc_w_enable <= '1';
else
pc_w_enable <= '0';
end if;
case curr_st is
WHEN EX_AND | EX_OR | EX_XOR | EX_NOT | EX_ADD | EX_SLA | EX_SRA | EX_SUB =>
ALU_Output_Mux <= '1';
WHEN OTHERS =>
ALU_Output_Mux <= '0';
END CASE;
if curr_st = EX_LI then
Load_Immediate <= '1';
else
Load_Immediate <= '0';
end if;
case curr_st is
WHEN EX_AND | EX_OR | EX_XOR | EX_NOT | EX_ADD | EX_SLA | EX_SRA | EX_SUB | EX_MOV | EX_JMP | EX_JMP_2 | EX_LI | EX_LI_2 =>
Data_Mem_Output_Mux <= '1';
WHEN OTHERS =>
Data_Mem_Output_Mux <= '0';
END CASE;
case curr_st is
WHEN EX_AND => ALU_control <="0001";
WHEN EX_OR => ALU_control <= "0010";
WHEN EX_XOR => ALU_control <= "0011";
WHEN EX_NOT => ALU_control <= "0000";
WHEN EX_ADD => ALU_control <= "0110";
WHEN EX_SLA => ALU_control <= "0100";
WHEN EX_SRA => ALU_control <= "0101";
WHEN EX_SUB => ALU_control <= "0111";
WHEN OTHERS => ALU_control <= "1111";
END CASE;
-----------------------------------------------------
end process;
end a_Control_Unit;