--------------------------------------------------------------------------------------------------------------- -- RISA Project -- Author: A.Greensted -- Module: -- Description: -- History: --------------------------------------------------------------------------------------------------------------- library ieee; use ieee.std_logic_1164.all; library SnapLib; use SnapLib.SnapPkg.all; entity Snap is port ( clk : in std_logic; enable : in std_logic; nReset : in std_logic; -- Memory Interface mem_wEn : out std_logic; mem_add : out std_logic_vector(12 downto 0); mem_dIn : out std_logic_vector(15 downto 0); mem_dOutLU : in std_logic_vector(15 downto 0); mem_dOutU : in std_logic_vector(15 downto 0); -- Flags Registers extFlagsIn : in std_logic_vector(7 downto 0); -- Interrupt Controller extIRQsIn : in std_logic_vector(7 downto 0); -- Snap Links sLnk_N_txOut : out std_logic; sLnk_N_rxIn : in std_logic; sLnk_N_CTSOut : out std_logic; sLnk_N_CTSIn : in std_logic; sLnk_E_txOut : out std_logic; sLnk_E_rxIn : in std_logic; sLnk_E_CTSOut : out std_logic; sLnk_E_CTSIn : in std_logic; sLnk_S_txOut : out std_logic; sLnk_S_rxIn : in std_logic; sLnk_S_CTSOut : out std_logic; sLnk_S_CTSIn : in std_logic; sLnk_W_txOut : out std_logic; sLnk_W_rxIn : in std_logic; sLnk_W_CTSOut : out std_logic; sLnk_W_CTSIn : in std_logic; -- Counter 0 cnt_0_extCountEn : in std_logic; cnt_0_match0Out : out std_logic; cnt_0_match1Out : out std_logic; -- Counter 1 cnt_1_extCountEn : in std_logic; cnt_1_match0Out : out std_logic; cnt_1_match1Out : out std_logic; -- System UART sysUART_txOut : out std_logic; sysUART_rxIn : in std_logic; -- Randon Number Generator rngDIn : in std_logic_vector(15 downto 0); -- IO Ports ioP_N_dIn : in std_logic_vector(7 downto 0); ioP_N_outEn : out std_logic_vector(7 downto 0); ioP_N_dOut : out std_logic_vector(7 downto 0); ioP_E_dIn : in std_logic_vector(7 downto 0); ioP_E_outEn : out std_logic_vector(7 downto 0); ioP_E_dOut : out std_logic_vector(7 downto 0); ioP_W_dIn : in std_logic_vector(7 downto 0); ioP_W_outEn : out std_logic_vector(7 downto 0); ioP_W_dOut : out std_logic_vector(7 downto 0); -- Fabric Ports fabIO_N_dIn : in std_logic_vector(5 downto 0); fabIO_N_dOut : out std_logic_vector(5 downto 0); fabIO_S_dIn : in std_logic_vector(5 downto 0); fabIO_S_dOut : out std_logic_vector(5 downto 0); fabIO_E_dIn : in std_logic_vector(5 downto 0); fabIO_E_dOut : out std_logic_vector(5 downto 0); fabIO_W_dIn : in std_logic_vector(5 downto 0); fabIO_W_dOut : out std_logic_vector(5 downto 0); -- Fabric CAP Logic cap_L_cnfChainLockRequest : out std_logic; cap_L_cnfChainLock : in std_logic; cap_L_cnfChainShiftEn : out std_logic; cap_L_cnfChainLoadEn : out std_logic; cap_L_cnfChainReadBackEn : out std_logic; cap_L_cnfChainOut : out std_logic; cap_L_cnfChainIn : in std_logic; cap_L_selChainLockRequest : out std_logic; cap_L_selChainLock : in std_logic; cap_L_selChainShiftEn : out std_logic; cap_L_selChainFeedbackEn : out std_logic; cap_L_selChainOut : out std_logic; cap_L_selChainIn : in std_logic; -- Fabric CAP Route cap_R_cnfChainLockRequest : out std_logic; cap_R_cnfChainLock : in std_logic; cap_R_cnfChainShiftEn : out std_logic; cap_R_cnfChainLoadEn : out std_logic; cap_R_cnfChainReadBackEn : out std_logic; cap_R_cnfChainOut : out std_logic; cap_R_cnfChainIn : in std_logic; cap_R_selChainLockRequest : out std_logic; cap_R_selChainLock : in std_logic; cap_R_selChainShiftEn : out std_logic; cap_R_selChainFeedbackEn : out std_logic; cap_R_selChainOut : out std_logic; cap_R_selChainIn : in std_logic); end Snap; architecture General of Snap is -- Control Signals signal cpuCycle : SNAPTYPE_CPU_CYCLE; signal cu_memAddSelect : std_logic := '0'; signal cu_insnRegEn : std_logic := '0'; signal cu_regFEDEEn : std_logic := '0'; signal cu_regFilePortAAddSelect : std_logic := '0'; signal cu_regDEEXEn : std_logic := '0'; signal cu_regEXWBEn : std_logic := '0'; signal cu_regFileREn : std_logic := '0'; signal cu_dataOutSelect : std_logic := '0'; signal cu_trapBraPCEn : std_logic := '0'; signal cu_trapISRPCEn : std_logic := '0'; signal cu_forwardASelect : std_logic := '0'; signal cu_forwardBSelect : std_logic := '0'; signal cu_memWEn : std_logic := '0'; signal cu_flushPipelineEn : std_logic := '0'; signal cu_aluFlagsWEn : std_logic := '0'; signal cu_conditionCodeWEn : std_logic := '0'; signal cu_intFlagsWEn : std_logic := '0'; signal cu_writeBackEn : std_logic := '0'; signal cu_insnSkipEn : std_logic := '0'; signal cu_ISRBranchEn : std_logic := '0'; signal cu_setGIEEn : std_logic := '0'; signal cu_clrGIEEn : std_logic := '0'; signal cu_regFileWEn : std_logic := '0'; -- Register File signal rf_portAAdd : std_logic_vector(6 downto 0) := (others => '0'); signal rf_portADOut : std_logic_vector(15 downto 0); --:= (others => '0'); signal rf_portBDOut : std_logic_vector(15 downto 0); --:= (others => '0'); signal rf_pc_pcOut : SNAPTYPE_MEM_ADD; --:= (others => '0'); signal rf_intC_interruptRequest : std_logic; -- := '0'; signal rf_fReg_flagsOut : SNAPTYPE_FLAGS := SNAP_FLAGS_RESET; signal rf_fReg_conditionCodeOut : SNAPTYPE_CONDITION_CODE; --:= SNAP_CC_ZERO; signal rf_fReg_extFlagsIn : SNAPTYPE_EXTERNAL_FLAGS; -- Arithmetic Logic Unit signal alu_dataA : std_logic_vector(15 downto 0) := (others => '0'); signal alu_dataB : std_logic_vector(15 downto 0) := (others => '0'); signal alu_flags : SNAPTYPE_ALU_FLAGS; signal alu_dOut : std_logic_vector(15 downto 0) := (others => '0'); signal dataOut : std_logic_vector(15 downto 0) := (others => '0'); -- Fetch/Decode Register Outputs signal regFEDE_insnAdd : SNAPTYPE_MEM_ADD := (others => '0'); signal regFEDE_flushed : std_logic := '0'; signal regFEDE_insnType : SNAPTYPE_INSN_TYPE := SNAP_REG_INSN; signal regFEDE_insnEnable : std_logic := '0'; signal regFEDE_conditional : std_logic := '0'; signal regFEDE_flagSet : std_logic := '0'; signal regFEDE_writeBack : std_logic := '0'; signal regFEDE_opCode : SNAPTYPE_OPCODE := SNAP_OP_ADD; signal regFEDE_opA : std_logic_vector(6 downto 0) := (others => '0'); signal regFEDE_opB : std_logic_vector(15 downto 0) := (others => '0'); -- Decode/Execute Register Outputs signal regDEEX_extFlags : std_logic_vector(7 downto 0) := (others => '0'); signal regDEEX_lastActivePC : SNAPTYPE_MEM_ADD := (others => '0'); signal regDEEX_flushed : std_logic := '0'; signal regDEEX_interruptRequest : std_logic := '0'; signal regDEEX_insnType : SNAPTYPE_INSN_TYPE := SNAP_REG_INSN; signal regDEEX_insnEnable : std_logic := '0'; signal regDEEX_conditional : std_logic := '0'; signal regDEEX_flagSet : std_logic := '0'; signal regDEEX_writeBack : std_logic := '0'; signal regDEEX_conditionCode : SNAPTYPE_CONDITION_CODE := SNAP_CC_ZERO; signal regDEEX_subOpCode : SNAPTYPE_SUB_OPCODE := SNAP_SUBOP_BRA; signal regDEEX_opCode : SNAPTYPE_OPCODE := SNAP_OP_ADD; signal regDEEX_opA : std_logic_vector(6 downto 0) := (others => '0'); signal regDEEX_opB : std_logic_vector(6 downto 0) := (others => '0'); signal regDEEX_skipNextInsn : std_logic := '0'; signal regDEEX_intSafe : std_logic := '0'; signal regDEEX_dataA : std_logic_vector(15 downto 0) := (others => '0'); signal regDEEX_dataB : std_logic_vector(15 downto 0) := (others => '0'); -- Execute/WriteBack Register Outputs signal regEXWB_writeBackEn : std_logic := '0'; signal regEXWB_opA : std_logic_vector(6 downto 0) := (others => '0'); signal regEXWB_data : std_logic_vector(15 downto 0) := (others => '0'); begin -- Mem -------------------------------------------------------------------------------------------------------- -- SNAp Program and Data RAM --------------------------------------------------------------------------------------------------------------- MemoryAddSelect : process(cu_memAddSelect, rf_pc_pcOut, alu_dataB) begin case cu_memAddSelect is when '0' => mem_add <= rf_pc_pcOut; -- Program Counter (from RegFile) when '1' => mem_add <= alu_dataB(SNAPTYPE_MEM_ADD'range); -- ALU opB, for Stores and Loads when others => assert false report "MemoryAddSelect: bad cu_memAddSelect value" severity failure; end case; end process; mem_dIn <= alu_dataA; mem_WEn <= cu_memWEn; -- InsnReg ---------------------------------------------------------------------------------------------------- -- Fetch / Decode Register --------------------------------------------------------------------------------------------------------------- InsnReg : process(clk) begin if (clk'event and clk='1') then if (nReset='0') then regFEDE_insnAdd <= (others => '0'); regFEDE_flushed <= '0'; elsif (enable='1' and cu_insnRegEn='1') then regFEDE_insnAdd <= rf_pc_pcOut; regFEDE_flushed <= cu_flushPipelineEn; end if; end if; end process; -- FEDE_Register ----------------------------------------------------------------------------------------------- -- Fetch / Decode Register --------------------------------------------------------------------------------------------------------------- -- {{{ FEDE_Register : process(clk) variable insn : std_logic_vector(31 downto 0); begin if (clk'event and clk='1') then if (nReset='0') then regFEDE_insnType <= SNAP_REG_INSN; regFEDE_insnEnable <= '0'; regFEDE_conditional <= '0'; regFEDE_flagSet <= '0'; regFEDE_writeBack <= '0'; regFEDE_opCode <= SNAP_OP_ADD; regFEDE_opA <= b"000_0000"; regFEDE_opB <= b"0000_0000_0000_0000"; elsif (enable='1' and cu_regFEDEEn='1') then insn := mem_dOutU & mem_dOutLU; regFEDE_insnType <= to_SNAPTYPE_INSN_TYPE(insn(31)); regFEDE_insnEnable <= insn(30); regFEDE_conditional <= insn(29); regFEDE_flagSet <= insn(28); regFEDE_writeBack <= insn(27); regFEDE_opCode <= to_SNAPTYPE_OPCODE(insn(26 downto 23)); regFEDE_opA <= insn(22 downto 16); regFEDE_opB <= insn(15 downto 0); end if; end if; end process FEDE_Register; -- }}} RegFilePortAAddSelect : process(cu_regFilePortAAddSelect, regEXWB_opA, regFEDE_opA) begin case cu_regFilePortAAddSelect is when '0' => rf_portAAdd <= regEXWB_opA; when '1' => rf_portAAdd <= regFEDE_opA; when others => assert false report "RegFilePortAAddSelect: bad cu_regFilePortAAddSelect value" severity failure; end case; end process; -- RegFile ---------------------------------------------------------------------------------------------------- -- Register File containing Working, System and Function Registers --------------------------------------------------------------------------------------------------------------- -- {{{ rf_fReg_extFlagsIn.flags <= regDEEX_extFlags; RegFile : RegisterFile port map ( clk => clk, enable => enable, nReset => nReset, portAWEn => cu_regFileWEn, portBREn => cu_regFileREn, portADIn => regEXWB_data, portAAdd => rf_portAAdd, portBAdd => regFEDE_opB(6 downto 0), portADOut => rf_portADOut, portBDOut => rf_portBDOut, -- Program Counter pc_pcOut => rf_pc_pcOut, pc_isrBranchEn => cu_ISRBranchEn, pc_activePC => regDEEX_lastActivePC, pc_braPCWEn => cu_trapBraPCEn, pc_isrPCWEn => cu_trapISRPCEn, -- Flags Registers fReg_extFlagsIn => rf_fReg_extFlagsIn, fReg_aluFlagsWEn => cu_aluFlagsWEn, fReg_aluFlagsIn => alu_flags, fReg_conditionCodeWEn => cu_conditionCodeWEn, fReg_conditionCodeIn => to_SNAPTYPE_CONDITION_CODE(dataOut(4 downto 0)), fReg_intFlagsWEn => cu_intFlagsWEn, fReg_intFlagsIn => dataOut(7 downto 0), fReg_intFlagsMaskIn => dataOut(15 downto 8), fReg_setGIEEn => cu_setGIEEn, fReg_clrGIEEn => cu_clrGIEEn, fReg_flagsOut => rf_fReg_flagsOut, fReg_conditionCodeOut => rf_fReg_conditionCodeOut, -- Interrupt Controller intC_extIRQsIn => extIRQsIn, intC_interruptRequest => rf_intC_interruptRequest, -- Snap Links sLnk_N_linkTxOut => sLnk_N_txOut, sLnk_N_linkRxIn => sLnk_N_rxIn, sLnk_N_linkCTSOut => sLnk_N_CTSOut, sLnk_N_linkCTSIn => sLnk_N_CTSIn, sLnk_E_linkTxOut => sLnk_E_txOut, sLnk_E_linkRxIn => sLnk_E_rxIn, sLnk_E_linkCTSOut => sLnk_E_CTSOut, sLnk_E_linkCTSIn => sLnk_E_CTSIn, sLnk_S_linkTxOut => sLnk_S_txOut, sLnk_S_linkRxIn => sLnk_S_rxIn, sLnk_S_linkCTSOut => sLnk_S_CTSOut, sLnk_S_linkCTSIn => sLnk_S_CTSIn, sLnk_W_linkTxOut => sLnk_W_txOut, sLnk_W_linkRxIn => sLnk_W_rxIn, sLnk_W_linkCTSOut => sLnk_W_CTSOut, sLnk_W_linkCTSIn => sLnk_W_CTSIn, -- Counter 0 -- Counter 0 cnt_0_extCountEn => cnt_0_extCountEn, cnt_0_match0Out => cnt_0_match0Out, cnt_0_match1Out => cnt_0_match1Out, -- Counter 1 -- Counter 1 cnt_1_extCountEn => cnt_1_extCountEn, cnt_1_match0Out => cnt_1_match0Out, cnt_1_match1Out => cnt_1_match1Out, -- System UART -- System UART sUART_serialTxOut => sysUART_txOut, sUART_serialRxIn => sysUART_rxIn, -- Random Number Generator rng_randomDataIn => rngDIn, -- IO Ports ioP_N_dIn => ioP_N_dIn, ioP_N_outEn => ioP_N_outEn, ioP_N_dOut => ioP_N_dOut, ioP_E_dIn => ioP_E_dIn, ioP_E_outEn => ioP_E_outEn, ioP_E_dOut => ioP_E_dOut, ioP_W_dIn => ioP_W_dIn, ioP_W_outEn => ioP_W_outEn, ioP_W_dOut => ioP_W_dOut, -- Fabric IO fabIO_N_dIn => fabIO_N_dIn, fabIO_N_dOut => fabIO_N_dOut, fabIO_S_dIn => fabIO_S_dIn, fabIO_S_dOut => fabIO_S_dOut, fabIO_E_dIn => fabIO_E_dIn, fabIO_E_dOut => fabIO_E_dOut, fabIO_W_dIn => fabIO_W_dIn, fabIO_W_dOut => fabIO_W_dOut, -- Fabric CAP Logic cap_L_cnfChainLockRequest => cap_L_cnfChainLockRequest, cap_L_cnfChainLock => cap_L_cnfChainLock, cap_L_cnfChainShiftEn => cap_L_cnfChainShiftEn, cap_L_cnfChainLoadEn => cap_L_cnfChainLoadEn, cap_L_cnfChainReadBackEn => cap_L_cnfChainReadBackEn, cap_L_cnfChainOut => cap_L_cnfChainOut, cap_L_cnfChainIn => cap_L_cnfChainIn, cap_L_selChainLockRequest => cap_L_selChainLockRequest, cap_L_selChainLock => cap_L_selChainLock, cap_L_selChainShiftEn => cap_L_selChainShiftEn, cap_L_selChainFeedbackEn => cap_L_selChainFeedbackEn, cap_L_selChainOut => cap_L_selChainOut, cap_L_selChainIn => cap_L_selChainIn, -- Fabric CAP Route cap_R_cnfChainLockRequest => cap_R_cnfChainLockRequest, cap_R_cnfChainLock => cap_R_cnfChainLock, cap_R_cnfChainShiftEn => cap_R_cnfChainShiftEn, cap_R_cnfChainLoadEn => cap_R_cnfChainLoadEn, cap_R_cnfChainReadBackEn => cap_R_cnfChainReadBackEn, cap_R_cnfChainOut => cap_R_cnfChainOut, cap_R_cnfChainIn => cap_R_cnfChainIn, cap_R_selChainLockRequest => cap_R_selChainLockRequest, cap_R_selChainLock => cap_R_selChainLock, cap_R_selChainShiftEn => cap_R_selChainShiftEn, cap_R_selChainFeedbackEn => cap_R_selChainFeedbackEn, cap_R_selChainOut => cap_R_selChainOut, cap_R_selChainIn => cap_R_selChainIn); --}}} -- DEEX_Register ----------------------------------------------------------------------------------------------- -- Decode / Execute Register --------------------------------------------------------------------------------------------------------------- -- {{{ DEEX_Register : process(clk) variable subOpCode : SNAPTYPE_SUB_OPCODE; variable flush : std_logic := '0'; begin if (clk'event and clk='1') then if (nReset='0') then regDEEX_extFlags <= (others => '0'); regDEEX_lastActivePC <= (others => '0'); regDEEX_flushed <= '0'; regDEEX_interruptRequest <= '0'; regDEEX_insnType <= SNAP_REG_INSN; regDEEX_insnEnable <= '0'; regDEEX_conditional <= '0'; regDEEX_flagSet <= '0'; regDEEX_writeBack <= '0'; regDEEX_conditionCode <= SNAP_CC_ZERO; regDEEX_subOpCode <= SNAP_SUBOP_BRA; regDEEX_opCode <= SNAP_OP_ADD; regDEEX_opA <= b"000_0000"; regDEEX_opB <= b"000_0000"; regDEEX_skipNextInsn <= '0'; regDEEX_intSafe <= '0'; regDEEX_dataA <= b"0000_0000_0000_0000"; regDEEX_dataB <= b"0000_0000_0000_0000"; elsif (enable = '1' and cu_regDEEXEn = '1') then regDEEX_extFlags <= extFlagsIn; flush := regFEDE_flushed or cu_insnSkipEn or cu_flushPipelineEn; if (flush='0') then regDEEX_lastActivePC <= regFEDE_insnAdd; end if; regDEEX_flushed <= flush; regDEEX_interruptRequest<= rf_intC_interruptRequest; regDEEX_insnType <= regFEDE_insnType; regDEEX_insnEnable <= regFEDE_insnEnable; regDEEX_conditional <= regFEDE_conditional; regDEEX_flagSet <= regFEDE_flagSet; regDEEX_writeBack <= regFEDE_writeBack; -- ConditionSelect, Select source of condition code if (regFEDE_opCode = SNAP_OP_SPECIAL) then regDEEX_conditionCode <= to_SNAPTYPE_CONDITION_CODE(regFEDE_opA(4 downto 0)); else regDEEX_conditionCode <= to_SNAPTYPE_CONDITION_CODE(regFEDE_opB(11 downto 7)); end if; subOpCode := to_SNAPTYPE_SUB_OPCODE(regFEDE_opA(6 downto 5)); regDEEX_subOpCode <= subOpCode; regDEEX_opCode <= regFEDE_opCode; -- DestSelect, For a branch, set the destination register to PC if (regFEDE_opCode=SNAP_OP_SPECIAL and (subOpCode=SNAP_SUBOP_BRA or subOpCode=SNAP_SUBOP_RETI)) then regDEEX_opA <= to_std_logic_vector(SNAP_REG_PC_PC); else regDEEX_opA <= regFEDE_opA; end if; regDEEX_opB <= regFEDE_opB(6 downto 0); regDEEX_skipNextInsn <= regFEDE_opB(15); regDEEX_intSafe <= regFEDE_opB(14); regDEEX_dataA <= rf_portADOut; -- DataBSelect, Select Source for Data B if (regFEDE_insnType = SNAP_LIT_INSN) then regDEEX_dataB <= regFEDE_opB; -- Lit Type (1), pass literal else regDEEX_dataB <= rf_portBDOut; -- Reg Type (0), pass Reg value end if; end if; end if; end process DEEX_Register; -- }}} ForwardASelect : process(cu_forwardASelect, regDEEX_dataA, regEXWB_data) begin case cu_forwardASelect is when '0' => alu_dataA <= regDEEX_dataA; when '1' => alu_dataA <= regEXWB_data; when others => assert false report "ForwardASelect: bad cu_forwardASelect value" severity failure; end case; end process; ForwardBSelect : process(cu_forwardBSelect, regDEEX_dataB, regEXWB_data) begin case cu_forwardBSelect is when '0' => alu_dataB <= regDEEX_dataB; when '1' => alu_dataB <= regEXWB_data; when others => assert false report "ForwardBSelect: bad cu_forwardBSelect value" severity failure; end case; end process; -- ALUnit ----------------------------------------------------------------------------------------------------- -- The processor ALU --------------------------------------------------------------------------------------------------------------- ALUnit : ALU port map ( opCode => regDEEX_opCode, opA => alu_dataA, opB => alu_dataB, carryBorrowIn => '0', overflowIn => '0', flags => alu_flags, dOut => alu_dOut); DataOutSelect : process(cu_dataOutSelect, alu_dOut, mem_dOutLU) begin case cu_dataOutSelect is when '0' => dataOut <= alu_dOut; when '1' => dataOut <= mem_dOutLU; when others => assert false report "DataOutSelect: bad cu_dataOutSelect value" severity failure; end case; end process; -- EXWB_Register ----------------------------------------------------------------------------------------------- -- Execute / Write Back Register ---------------------------------------------------------------------------------------------------------------- -- {{{ EXWB_Register : process(clk) begin if (clk'event and clk='1') then if (nReset='0') then regEXWB_writeBackEn <= '0'; regEXWB_opA <= b"000_0000"; regEXWB_data <= b"0000_0000_0000_0000"; elsif (enable = '1' and cu_regEXWBEn = '1') then regEXWB_writeBackEn <= cu_writeBackEn; regEXWB_opA <= regDEEX_opA; regEXWB_data <= dataOut; end if; end if; end process EXWB_Register; -- }}} --===========================================================================================================-- -- CPU CONTROL --===========================================================================================================-- -- CPUCycler -------------------------------------------------------------------------------------------------- -- Controls the cpu cycle --------------------------------------------------------------------------------------------------------------- -- {{{ CPUCycler : process(clk) begin if (clk'event and clk='1') then if (nReset='0') then cpuCycle <= SNAP_CYCLE_0; elsif (enable = '1') then case cpuCycle is when SNAP_CYCLE_0 => cpuCycle <= SNAP_CYCLE_1; when SNAP_CYCLE_1 => cpuCycle <= SNAP_CYCLE_0; end case; end if; end if; end process CPUCycler; -- }}} Controller : process(cpuCycle, rf_intC_interruptRequest, regDEEX_intSafe, rf_fReg_flagsOut, regDEEX_insnType, regDEEX_opCode, regDEEX_flushed, regDEEX_insnEnable,regDEEX_conditionCode, regDEEX_conditional, regDEEX_subOpCode, regDEEX_writeBack, rf_fReg_conditionCodeOut, regEXWB_writeBackEn, regDEEX_flagSet, regDEEX_skipNextInsn, regDEEX_opA, regEXWB_opA, regDEEX_opB, regDEEX_interruptRequest) -- rf_fReg_flagsOut.intFlags.globalInterruptEn, -- rf_fReg_flagsOut.intFlags.aluFlags.zero, rf_fReg_flagsOut.intFlags.aluFlags.negative, -- rf_fReg_flagsOut.intFlags.aluFlags.carryBorrow, rf_fReg_flagsOut.intFlags.aluFlags.overflow, -- rf_fReg_flagsOut.intFlags.equalityTests, rf_fReg_flagsOut.extFlags.flags. variable serviceInterrupt : std_logic := '0'; variable conditionCode : SNAPTYPE_CONDITION_CODE := SNAP_CC_ZERO; variable executeInsn : std_logic := '0'; begin -- Unconditional controls cu_memAddSelect <= '0'; cu_insnRegEn <= '0'; cu_regFEDEEn <= '0'; cu_regFilePortAAddSelect <= '0'; cu_regDEEXEn <= '0'; cu_regEXWBEn <= '0'; -- Conditional controls cu_regFileREn <= '0'; cu_dataOutSelect <= '0'; cu_trapBraPCEn <= '0'; cu_trapISRPCEn <= '0'; cu_forwardASelect <= '0'; cu_forwardBSelect <= '0'; cu_memWEn <= '0'; cu_flushPipelineEn <= '0'; cu_aluFlagsWEn <= '0'; cu_conditionCodeWEn <= '0'; cu_intFlagsWEn <= '0'; cu_writeBackEn <= '0'; cu_insnSkipEn <= '0'; cu_ISRBranchEn <= '0'; cu_setGIEEn <= '0'; cu_clrGIEEn <= '0'; cu_regFileWEn <= '0'; -- Determine if an interrupt should be serviced if (regDEEX_intSafe='1' and regDEEX_insnType=SNAP_REG_INSN) then serviceInterrupt := '0'; -- Don't service interrupt if insn is interrupt safe (only for reg type insns) elsif (regDEEX_interruptRequest='1' and rf_fReg_flagsOut.intFlags.globalInterruptEn='1') then serviceInterrupt := '1'; -- Service if request and global interrupts enabled else serviceInterrupt := '0'; -- Nothing to service end if; -- Select Condition Code if (regDEEX_insnType=SNAP_REG_INSN or regDEEX_opCode=SNAP_OP_SPECIAL) then conditionCode := regDEEX_conditionCode; -- Use condition Code from instruction else conditionCode := rf_fReg_conditionCodeOut; -- Use Condition Code from Condition Code Reg end if; -- Determine if the instruction should execute executeInsn := '0'; if (serviceInterrupt='0') then -- Only execute if not servicing an interrupt if (regDEEX_flushed='0' and regDEEX_insnEnable='1') then -- Only execute if enabled and not flushed if (regDEEX_conditional='0') then -- Execute if unconditional executeInsn := '1'; elsif (isConditionSatisfied(conditionCode, rf_fReg_flagsOut)) then -- Execute if conditional and condition met executeInsn := '1'; end if; end if; end if; case cpuCycle is when SNAP_CYCLE_0 => cu_memAddSelect <= '1'; cu_regFEDEEn <= '1'; if (serviceInterrupt='1') then cu_trapISRPCEn <= '1'; cu_ISRBranchEn <= '1'; end if; if (executeInsn='1') then if (regDEEX_opCode=SNAP_OP_SPECIAL and regDEEX_subOpCode=SNAP_SUBOP_BRA) then cu_trapBraPCEn <= '1'; end if; if (regDEEX_opCode=SNAP_OP_ST and regDEEX_writeBack='1') then cu_memWEn <= '1'; -- Enable memory write if a store instruction and writeback selected end if; end if; if (regEXWB_writeBackEn='1') then cu_regFileWEn <= '1'; -- Write to regFile if writeback enabled end if; when SNAP_CYCLE_1 => cu_insnRegEn <= '1'; cu_regFilePortAAddSelect <= '1'; cu_regDEEXEn <= '1'; cu_regEXWBEn <= '1'; if (executeInsn = '1') then if (regDEEX_insnType=SNAP_REG_INSN) then cu_regFileREn <= '1'; -- Enable regifle read if a register based instruction end if; if (regDEEX_flagSet='1') then cu_aluFlagsWEn <= '1'; -- Set flags if insn's flagSet bit is set end if; if (regDEEX_opCode=SNAP_OP_SPECIAL and regDEEX_subOpCode=SNAP_SUBOP_CSET) then cu_conditionCodeWEn <= '1'; -- Write conditions if a CSET insn end if; if (regDEEX_opCode=SNAP_OP_SPECIAL and regDEEX_subOpCode=SNAP_SUBOP_FSET) then cu_intFlagsWEn <= '1'; -- Write flags if a FSET insn end if; if (regDEEX_writeBack='1' and isWriteBackInsn(regDEEX_opCode, regDEEX_subOpCode)) then cu_writeBackEn <= '1'; -- Write back if not ST, CSET or FSET end if; if (regDEEX_skipNextInsn='1' and regDEEX_insnType=SNAP_REG_INSN) then cu_insnSkipEn <= '1'; end if; if (regDEEX_opCode=SNAP_OP_SPECIAL and regDEEX_subOpCode=SNAP_SUBOP_RETI) then cu_setGIEEn <= '1'; end if; end if; if (serviceInterrupt='1') then cu_clrGIEEn <= '1'; -- Clear GIE, stopping re-interruption cu_insnSkipEn <= '1'; -- Flush next insn only end if; end case; if (executeInsn='1' and regDEEX_opCode=SNAP_OP_SPECIAL) then if (regDEEX_subOpCode=SNAP_SUBOP_BRA or regDEEX_subOpCode=SNAP_SUBOP_RETI) then cu_flushPipelineEn <= '1'; -- Flush pipeline on executing BRA or RETI end if; end if; -- Only forward if the previous insn was writing back and reg location is forwardable if (regEXWB_writeBackEn='1' and isForwardableRegister(regEXWB_opA)) then -- Forward opA if a match if (regDEEX_opA=regEXWB_opA) then cu_forwardASelect <= '1'; end if; -- Forward opB if a match and this is a reg type instruciton if (regDEEX_opB=regEXWB_opA and regDEEX_insnType = SNAP_REG_INSN) then cu_forwardBSelect <= '1'; end if; end if; -- Select data from memory on a load insn if (regDEEX_opCode=SNAP_OP_LD) then cu_dataOutSelect <= '1'; end if; end process; end General;