ARCHITECTURE RTL OF controller IS signal en1, enInt: std_ulogic; constant opCodeLength : integer := 5; subtype opCodeType is std_ulogic_vector(opCodeLength-1 downto 0); constant opLoad : opCodeType := "00000"; constant opInput : opCodeType := "00010"; constant opFetch : opCodeType := "00011"; constant opAnd : opCodeType := "00101"; constant opOr : opCodeType := "00110"; constant opXor : opCodeType := "00111"; constant opTest : opCodeType := "01001"; constant opComp : opCodeType := "01010"; constant opAdd : opCodeType := "01100"; constant opAddCy : opCodeType := "01101"; constant opSub : opCodeType := "01110"; constant opSubCy : opCodeType := "01111"; constant opShRot : opCodeType := "10000"; constant opRet : opCodeType := "10101"; constant opOutput: opCodeType := "10110"; constant opStore : opCodeType := "10111"; constant opCall : opCodeType := "11000"; constant opJump : opCodeType := "11010"; constant opIntF : opCodeType := "11110"; constant branchConditionLength : integer := 3; subtype branchConditionType is std_ulogic_vector(branchConditionLength-1 downto 0); constant brAw : branchConditionType := "000"; constant brZ : branchConditionType := "100"; constant brNZ : branchConditionType := "101"; constant brC : branchConditionType := "110"; constant brNC : branchConditionType := "111"; signal aluOpSel: std_ulogic; signal regWriteEn: std_ulogic; signal flagsEn, flagsEnable: std_ulogic; signal carrySaved: std_ulogic; signal zeroSaved: std_ulogic; signal branchEnable1, branchEnable: std_ulogic; signal discardOpCode: std_ulogic; signal updateIntFlag: std_ulogic; BEGIN ------------------------------------------------------------------------------ -- Enable signal buildEnable: process(reset, clock) begin if reset = '1' then en1 <= '0'; elsif rising_edge(clock) then en1 <= '1'; end if; end process buildEnable; enInt <= en1 and en; -- don't enable very first instruction twice ------------------------------------------------------------------------------ -- ALU controls selectdataSource: process(opCode) begin aluOpSel <= '0'; portInSel <= '0'; scratchpadSel <= '0'; case opCode(opCodeLength-1 downto 0) is when opLoad => aluOpSel <= '1'; when opInput => portInSel <= '1'; when opFetch => scratchpadSel <= '1'; when opAnd => aluOpSel <= '1'; when opOr => aluOpSel <= '1'; when opXor => aluOpSel <= '1'; when opTest => aluOpSel <= '1'; when opComp => aluOpSel <= '1'; when opAdd => aluOpSel <= '1'; when opAddCy => aluOpSel <= '1'; when opSub => aluOpSel <= '1'; when opSubCy => aluOpSel <= '1'; when opShRot => aluOpSel <= '1'; when others => aluOpSel <= '-'; portInSel <= '-'; scratchpadSel <= '-'; end case; end process selectdataSource; registerFileSel <= aluOpSel and twoRegInstr; instrDataSel <= aluOpSel and (not twoRegInstr); regWriteEn <= enInt and (not discardOpCode); regWriteTable: process(opCode, regWriteEn) begin case opCode(opCodeLength-1 downto 0) is when opLoad => regWrite <= regWriteEn; when opInput => regWrite <= regWriteEn; when opFetch => regWrite <= regWriteEn; when opAnd => regWrite <= regWriteEn; when opOr => regWrite <= regWriteEn; when opXor => regWrite <= regWriteEn; when opAdd => regWrite <= regWriteEn; when opAddCy => regWrite <= regWriteEn; when opSub => regWrite <= regWriteEn; when opSubCy => regWrite <= regWriteEn; when opShRot => regWrite <= regWriteEn; when others => regWrite <= '0'; end case; end process regWriteTable; ------------------------------------------------------------------------------ -- I/O controls readStrobe <= enInt when (opCode = opInput) and (discardOpCode = '0') else '0'; writeStrobe <= enInt when (opCode = opOutput) and (discardOpCode = '0') else '0'; ------------------------------------------------------------------------------ -- scratchpad controls scratchpadWrite <= '1' when opCode = opStore else '0'; ------------------------------------------------------------------------------ -- Carry logic flagsEn <= enInt and (not branchEnable); flagsEnableTable: process(opCode, flagsEn) begin case opCode(opCodeLength-1 downto 0) is when opAnd => flagsEnable <= flagsEn; when opOr => flagsEnable <= flagsEn; when opXor => flagsEnable <= flagsEn; when opTest => flagsEnable <= flagsEn; when opComp => flagsEnable <= flagsEn; when opAdd => flagsEnable <= flagsEn; when opAddCy => flagsEnable <= flagsEn; when opSub => flagsEnable <= flagsEn; when opSubCy => flagsEnable <= flagsEn; when opShRot => flagsEnable <= flagsEn; when others => flagsEnable <= '0'; end case; end process flagsEnableTable; saveCarries: process(reset, clock) begin if reset = '1' then carrySaved <= '0'; zeroSaved <= '0'; elsif rising_edge(clock) then if flagsEnable = '1' then carrySaved <= cOut; zeroSaved <= zero; end if; end if; end process saveCarries; cIn <= carrySaved; ------------------------------------------------------------------------------ -- Program counter controls checkBranchCondition: process(branchCond, zeroSaved, carrySaved) begin case branchCond(branchConditionLength-1 downto 0) is when brAw => branchEnable1 <= '1'; when brZ => branchEnable1 <= zeroSaved; when brNZ => branchEnable1 <= not zeroSaved; when brC => branchEnable1 <= carrySaved; when brNC => branchEnable1 <= not carrySaved; when others => branchEnable1 <= '-'; end case; end process checkBranchCondition; branchEnableTable: process(opCode, branchEnable1, discardOpCode) begin if discardOpCode = '0' then case opCode(opCodeLength-1 downto 0) is when opRet => branchEnable <= branchEnable1; when opCall => branchEnable <= branchEnable1; when opJump => branchEnable <= branchEnable1; when others => branchEnable <= '0'; end case; else branchEnable <= '0'; end if; end process branchEnableTable; progCounterControlTable: process(opCode, enInt, branchEnable) begin incPC <= enInt; loadInstrAddress <= '0'; loadStoredPC <= '0'; case opCode(opCodeLength-1 downto 0) is when opRet => incPC <= not branchEnable; loadStoredPC <= enInt and branchEnable; when opCall => incPC <= not branchEnable; loadInstrAddress <= enInt and branchEnable; when opJump => incPC <= not branchEnable; loadInstrAddress <= enInt and branchEnable; when others => null; end case; end process progCounterControlTable; -- If a branch condition is met, the next operation has to be discarded. -- This is due to the synchronous operation of the program ROM: the -- instructions are provided one clock period after the program counter. -- so while the branch operation is processed, the next instruction is -- already being fetched. delayBranchEnable: process(reset, clock) begin if reset = '1' then discardOpCode <= '0'; elsif rising_edge(clock) then discardOpCode <= branchEnable; end if; end process delayBranchEnable; ------------------------------------------------------------------------------ -- Stack pointer controls pcStackControlTable: process(discardOpCode, opCode, enInt) begin storePC <= '0'; prevPC <= '0'; if discardOpCode = '0' then case opCode(opCodeLength-1 downto 0) is when opRet => prevPC <= enInt; when opCall => storePC <= enInt; when others => null; end case; end if; end process pcStackControlTable; ------------------------------------------------------------------------------ -- interrupt control updateIntFlag <= '1' when opCode = opIntF else '0'; END ARCHITECTURE RTL;