SimpleProcessorCore/src/ControlUnit.vhd

402 lines
18 KiB
VHDL

-------------------------------------------------------
--! @file
--! @brief the control unit for the Simple Processor Core (Geraffel Processor)
--! @author Dominik Meyer
--! @email dmeyer@hsu-hh.de
--! @licence GPLv2
--! @date 2010-11-19
-------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library work;
use work.cpupkg.all;
--! the control unit for the Simple Processor Core (Geraffel Processor)
--!
--! This Code is based on a processor core used at the Helmut Schmidt University for
--! educational purposes.
--!
entity ControlUnit is
port (
iClk : in std_logic; --! iClk signal
iReset : in std_logic; --! iReset signal
icOpCode : in optype; --! icOpCode bus
idCarry : in std_logic; --! carry from register file
idZero : in std_logic; --! zero flag from register file
ocRnotWRam : out std_logic; --! r_notw to RAM
ocLoadEn : out std_logic; --! safe result of alu
ocEnableRAM : out std_logic; --! put akku on databus
ocLoadInstr : out std_logic; --! load instruction control signal
ocNextPC : out std_logic; --! increment pc
ocAddrSel : out std_logic; --! pc on addressbus
ocJump : out std_logic; --! do a ocJump
ocPCregister : out std_logic; --! put PC to register File
ocUsePC : out std_logic; --! use Register to fill in the PC
ocLoad : out std_logic --! put databus to ALU immediate port
);
end ControlUnit;
architecture arch of ControlUnit is
type STATES is (load, decode, exshl, exshr, exsto, exloa, exloa2, exli, exadd, exsub, exaddc, exsubc,
exopor, exopand, exopxor, exopnot, exjpz, exjpc, exjmp, exhlt, exjmc, exret);
signal sState, sState_next : STATES;
begin
--! switch sStates if needed
sState_change : process(iClk,iReset)
begin
if (iReset = '1') then
sState <= load;
elsif (rising_edge(iClk)) then
sState <= sState_next;
end if;
end process;
--! calculate the next state of the FSM
calc_sState_next : process(sState, icOpCode, idCarry, idZero)
begin
case sState is
when load =>
sState_next <= decode;
when decode =>
case icOpCode is
when shl => sState_next <= exshl;
when shr => sState_next <= exshr;
when sto => sState_next <= exsto;
when loa => sState_next <= exloa;
when li => sState_next <= exli;
when add => sState_next <= exadd;
when sub => sState_next <= exsub;
when addc => sState_next <= exaddc;
when subc => sState_next <= exsubc;
when opand => sState_next <= exopand;
when opor => sState_next <= exopor;
when opxor => sState_next <= exopxor;
when opnot => sState_next <= exopnot;
when jpz =>
if (idZero = '1') then
sState_next <= exjpz;
else
sState_next <= load;
end if;
when jpc =>
if (idCarry = '1') then
sState_next <= exjpc;
else
sState_next <= load;
end if;
when jmp => sState_next <= exjmp;
when jmc => sState_next <= exjmc;
when ret => sState_next <= exret;
when hlt => sState_next <= exhlt;
end case;
when exhlt => sState_next <= exhlt;
when exloa => sState_next <= exloa2;
when others => sState_next <= load;
end case;
end process;
--! calculate the output in each sState
calc_output : process(sState)
begin
case sState is
when load =>
ocRnotWRam <= '1'; -- read from RAM
ocLoadEn <= '0'; -- do not save result
ocEnableRAM <= '1'; -- do not put akku on databus
ocLoadInstr <= '0'; -- load instruction
ocNextPC <= '0'; -- do not increment pc
ocAddrSel <= '1'; -- pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when decode =>
ocRnotWRam <= '1'; -- read from RAM
ocLoadEn <= '0'; -- do not save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '1'; -- load instruction
ocNextPC <= '1'; -- do not increment pc
ocAddrSel <= '0'; -- pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exshl =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exshr =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exsto =>
ocRnotWRam <= '0'; -- write to RAM
ocLoadEn <= '0'; -- do not save result
ocEnableRAM <= '1'; -- put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exloa =>
ocRnotWRam <= '1'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '1'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exli =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exadd =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exsub =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exaddc =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exloa2 =>
ocRnotWRam <= '1'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '1'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '1';
when exsubc =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exopor =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exopand =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exopxor =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exopnot =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exjpz =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '0'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '1'; -- ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exjpc =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '0'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '1'; -- ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exjmp =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '0'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '1'; -- ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exjmc =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '1'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '1'; -- ocJump
ocPCregister <= '1'; -- put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when exret =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '0'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- ocJump
ocPCregister <= '0'; -- put PC to register File
ocUsePC <= '1';
ocLoad <= '0';
when exhlt =>
ocRnotWRam <= '0'; -- read from RAM
ocLoadEn <= '0'; -- save result
ocEnableRAM <= '0'; -- do not put akku on databus
ocLoadInstr <= '0'; -- do not load instruction
ocNextPC <= '0'; -- increment pc
ocAddrSel <= '0'; -- no pc on addressbus
ocJump <= '0'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
when others =>
ocRnotWRam <= '-'; -- read from RAM
ocLoadEn <= '-'; -- save result
ocEnableRAM <= '-'; -- do not put akku on databus
ocLoadInstr <= '-'; -- do not load instruction
ocNextPC <= '-'; -- increment pc
ocAddrSel <= '-'; -- no pc on addressbus
ocJump <= '-'; -- no ocJump
ocPCregister <= '0'; -- do not put PC to register File
ocUsePC <= '0';
ocLoad <= '0';
end case;
end process;
end arch;