237 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
			
		
		
	
	
			237 lines
		
	
	
		
			8.5 KiB
		
	
	
	
		
			VHDL
		
	
	
	
	
	
| 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;
 |