2013-07-02 22:15:26 +02:00
|
|
|
-------------------------------------------------------
|
|
|
|
--! @file
|
2013-12-30 14:56:42 +01:00
|
|
|
--! @brief the control unit for the Simple Processor Core (Geraffel Processor)
|
2013-07-02 22:15:26 +02:00
|
|
|
--! @author Dominik Meyer
|
|
|
|
--! @email dmeyer@hsu-hh.de
|
2013-12-30 14:56:42 +01:00
|
|
|
--! @licence GPLv2
|
2013-07-02 22:15:26 +02:00
|
|
|
--! @date 2010-11-19
|
|
|
|
-------------------------------------------------------
|
|
|
|
library ieee;
|
2013-12-30 14:56:42 +01:00
|
|
|
use ieee.std_logic_1164.all;
|
|
|
|
use ieee.std_logic_unsigned.all;
|
2013-07-02 22:15:26 +02:00
|
|
|
|
|
|
|
library work;
|
2013-12-30 14:56:42 +01:00
|
|
|
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.
|
|
|
|
--!
|
2013-07-02 22:15:26 +02:00
|
|
|
|
2013-12-30 14:56:42 +01:00
|
|
|
entity ControlUnit is
|
2013-07-02 22:15:26 +02:00
|
|
|
port (
|
2013-12-30 14:56:42 +01:00
|
|
|
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
|
2013-07-02 22:15:26 +02:00
|
|
|
);
|
2013-12-30 14:56:42 +01:00
|
|
|
end ControlUnit;
|
2013-07-02 22:15:26 +02:00
|
|
|
|
2013-12-30 14:56:42 +01:00
|
|
|
architecture arch of ControlUnit is
|
2013-07-02 22:15:26 +02:00
|
|
|
|
2013-12-30 14:56:42 +01:00
|
|
|
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);
|
2013-07-02 22:15:26 +02:00
|
|
|
|
2013-12-30 14:56:42 +01:00
|
|
|
signal sState, sState_next : STATES;
|
2013-07-02 22:15:26 +02:00
|
|
|
|
|
|
|
begin
|
|
|
|
|
|
|
|
|
2013-12-30 14:56:42 +01:00
|
|
|
--! 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;
|
2013-07-02 22:15:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
--! calculate the output in each sState
|
2013-12-30 14:56:42 +01:00
|
|
|
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;
|
2013-07-02 22:15:26 +02:00
|
|
|
|
|
|
|
|
|
|
|
end arch;
|