SimpleProcessorCore/src/FetchDecode.vhd

170 lines
6.6 KiB
VHDL

-------------------------------------------------------
--! @file
--! @brief Fetch/Decode Component for the Simple Processor Core (Geraffel Processor)
--! @author Dominik Meyer/ Marcel Eckert
--! @email dmeyer@federationhq.de
--! @licence GPLv2
--! @date unknown
-------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
library work;
use work.cpupkg.all;
--! Fetch/Decode Component 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 FetchDecode is
port(
iClk : in std_logic; --! main system clock
iReset : in std_logic; --! system active high reset
idData : in DATA; --! Data input coming from the RAM with instruction
icAddrSel : in std_logic; --! Put AddressRegister to Address BUS
icDecodeInstr : in std_logic; --! Decode the loaded instrcution
icJump : in std_logic; --! executed instruction is a jump, put jump register to address bus
icNextPC : in std_logic; --! increment the PC
odPC : out ADDRESS; --! put out the current PC
idPC : in ADDRESS; --! input for a new PC from extern
icUsePC : in std_logic; --! use the external PC
odAddress : out ADDRESS; --! output to the address bus
odImmidiate : out DATA; --! output the loaded immediate
odRegAsel : out std_logic_vector(4 downto 0); --! output the decoded register addr
odRegBsel : out std_logic_vector(4 downto 0); --! output the decoded register addr
odRegINsel : out std_logic_vector(4 downto 0); --! output the decoded result register addr
ocOperation : out OPTYPE --! output which operation to perform
);
end FetchDecode;
architecture Behavioral of FetchDecode is
signal sdPC, sdPC_next : ADDRESS;
signal sdAdr, sdAdr_next : ADDRESS;
signal sdImmidate, sdImmidiate_next : DATA;
signal sdRegAsel, sdRegAsel_next : std_logic_vector(4 downto 0);
signal sdRegBsel, sdRegBsel_next : std_logic_vector(4 downto 0);
signal sdRegINsel, sdRegINsel_next : std_logic_vector(4 downto 0);
signal scOp, scOp_next : OPTYPE;
begin
Transition : process(idData, sdImmidate, icDecodeInstr, icJump, icNextPC, sdAdr, sdPC, scOp, sdRegAsel, sdRegBsel, sdRegINsel, icUsePC, idPC)
begin
-- default values for all signals/registers
sdAdr_next <= sdAdr;
sdPC_next <= sdPC;
scOp_next <= scOp;
sdImmidiate_next <= sdImmidate;
-- fill the next register values with the old ones
sdRegAsel_next <= sdRegAsel;
sdRegBsel_next <= sdRegBsel;
sdRegINsel_next <= sdRegINsel;
--! ISA Definition, for the Decode run
if (icDecodeInstr = '1') then
-- because of the fixed bit positions we can fill in the correct values to the next register values
sdAdr_next <= idData(15 downto 0);
sdImmidiate_next <= "0000000000000000" & idData(15 downto 0);
sdRegINsel_next <= idData(25 downto 21);
sdRegAsel_next <= idData(20 downto 16);
sdRegBsel_next <= idData(15 downto 11);
-- select the operation to do according to the decoded opcode
case idData(31 downto 26) is
when "000000" => scOp_next <= shl;
when "000001" => scOp_next <= shr;
when "000010" => scOp_next <= sto;
when "000011" => scOp_next <= loa;
when "000100" => scOp_next <= add;
when "000101" => scOp_next <= sub;
when "000110" => scOp_next <= addc;
when "000111" => scOp_next <= subc;
when "001000" => scOp_next <= opor;
when "001001" => scOp_next <= opand;
when "001010" => scOp_next <= opxor;
when "001011" => scOp_next <= opnot;
when "001100" => scOp_next <= jpz;
when "001101" => scOp_next <= jpc;
when "001110" => scOp_next <= jmp;
when "001111" => scOP_next <= li;
when "010000" => scOp_next <= jmc;
when "010001" => scOp_next <= ret;
when others => scOp_next <= hlt;
end case;
end if;
-- set registers according of some special external control signals
if (icUsePC = '1') then
sdPC_next <= idPC;
end if;
if (icJump = '1') then
sdPC_next <= sdAdr;
end if;
if (icNextPC = '1') then
sdPC_next <= sdPC + '1';
end if;
end process;
-- Execute Transition, set register values to the calculated next register values
process(iClk, iReset)
begin
if (iReset = '1') then
sdPC <= (others => '0');
sdAdr <= (others => '0');
sdImmidate <= (others => '0');
sdRegAsel <= (others => '0');
sdRegBsel <= (others => '0');
sdRegINsel <= (others => '0');
scOp <= hlt;
elsif (rising_edge(iClk)) then
sdPC <= sdPC_next;
sdAdr <= sdAdr_next;
scOp <= scOp_next;
sdImmidate <= sdImmidiate_next;
sdRegAsel <= sdRegAsel_next;
sdRegBsel <= sdRegBsel_next;
sdRegINsel <= sdRegINsel_next;
end if;
end process;
-- Output everything to the correct output signal
odAddress <= idPC when icUsePC = '1' else
sdAdr when icAddrSel = '0' and icDecodeInstr = '0' else
sdAdr_next when icAddrSel = '0' and icDecodeInstr = '1' else
sdPC; -- addr_sel = '1'
odPC <= sdPC;
ocOperation <= scOp when icDecodeInstr = '0' else
scOp_next;
odImmidiate <= sdImmidate when icDecodeInstr = '0' else sdImmidiate_next;
odRegAsel <= sdRegAsel when icDecodeInstr = '0' else sdRegAsel_next;
odRegBsel <= sdRegBsel when icDecodeInstr = '0' else sdRegBsel_next;
odRegINsel <= sdRegINsel when icDecodeInstr = '0' else sdRegINsel_next;
end Behavioral;