library ieee; use ieee.std_logic_1164.all; entity controller is port ( CLK: IN STD_LOGIC; OPCODE: IN STD_LOGIC_VECTOR (3 downto 0); ZERO: IN STD_LOGIC; nReset: IN STD_LOGIC; RT: IN STD_LOGIC_VECTOR(3 downto 0); ALUOp: OUT STD_LOGIC_VECTOR(3 downto 0); ALUselA: OUT STD_LOGIC_VECTOR(1 downto 0); ALUselB: OUT STD_LOGIC_VECTOR(2 downto 0); RegWE: OUT STD_LOGIC; RFWE: OUT STD_LOGIC; RegWSrc: OUT STD_LOGIC_VECTOR(1 downto 0); Reg1Src: OUT STD_LOGIC; MDRWE: OUT STD_LOGIC; Reg2Src: OUT STD_LOGIC; iMemWait: in STD_LOGIC; dMemWait: in STD_LOGIC; IRWE: OUT STD_LOGIC; imemRead: OUT STD_LOGIC; dmemRead: OUT STD_LOGIC; dmemWrite:OUT STD_LOGIC; PCWE: OUT STD_LOGIC; PCSel: OUT STD_LOGIC_VECTOR(1 downto 0); Halt: OUT STD_LOGIC; exSel: OUT STD_LOGIC_VECTOR(1 downto 0); AWE: OUT STD_LOGIC; BWE: OUT STD_LOGIC; ALUoutWE: OUT STD_LOGIC -- AND OTHER WE for other registers. ); end controller; architecture behavioral of controller is type state_type is (fetch, decode, haltstate, exec, mem, writeback); signal state, next_state: state_type; begin state_logic : process(state,iMemWait, dMemWait, OPCODE, RT, ZERO) begin ALUop <= "0000"; ALUselA <= "00"; ALUselB <= "000"; RegWE <= '0'; RFWE <= '0'; RegWSrc <= "00"; Reg1Src <= '0'; Reg2Src <= '0'; IRWE <= '0'; imemRead <= '0'; dmemRead <= '0'; dmemWrite <= '0'; PCWE <= '0'; PCSel <= "00"; AWE <= '0'; BWE <= '0'; Halt <= '0'; exSel <= "00"; ALUoutWE <= '0'; MDRWE <= '0'; case state is when fetch => imemRead <= '1'; IRWE <= '1'; ALUop <= "0010"; ALUselB <= "010"; ALUselA <= "00"; PCsel <= "01"; if imemWait = '1' then next_state <= fetch; else PCWE <= '1'; AWE <= '1'; BWE <= '1'; --imemRead <= '0'; next_state <= decode; end if; when decode => if OPCODE = x"C" then --LDI exSel <= "11"; -- sets to zero extend offset ALUselB <= "011"; --extended ALUselA <= "00"; --Doesnt matter RegWSrc <= "11"; --taken from extended imm, 11? RFWE <= '1'; next_state <= fetch; elsif OPCODE = x"B" then --LUI exSel <= "00"; ALUop <= "0000"; --OR ALUselB <= "011"; --extended ALUselA <= "10";--01? --rdat 16bit Reg1Src <= '1'; --rD RegWSrc <= "01"; --rdat of aluout ALUoutWE <= '1'; AWE <= '1'; BWE <= '1'; next_state <= exec; elsif OPCODE = x"8" then --LDW, need mem RegWSrc <= "00"; Reg1Src <= '0'; exSel <= "01"; ALUop <= "0010"; ALUselA <= "01"; ALUselB <= "011"; AWE <= '1'; BWE <= '1'; ALUoutWE <= '1'; next_state <= exec; elsif OPCODE = x"A" then --STW AWE <= '1'; BWE <= '1'; Reg2Src <= '1'; Reg1Src <= '0'; exSel <= "01";--"11"; ALUoutWE <= '1'; ALUselA <= "01"; ALUselB <= "011"; ALUop <= "0010"; next_state <= exec; elsif (OPCODE = x"F") and RT = x"F" then next_state <= haltstate; elsif (OPCODE = x"F") and RT = x"0" then --Jump RegWSrc <= "10"; RFWE <= '1'; --AWE should already have RS clocked into it ALUSelA <= "01"; --sets to r AWE <= '1'; next_state <= exec; elsif (OPCODE = x"F") and RT = x"2" then --NOT --rd <= not RS, xor with FFFF AWE <= '1'; next_state <= exec; elsif (OPCODE = x"E") then --BR RegWSrc <= "10"; --writing npc to rd RFWE <= '1'; --$rd <= $npc ALUSelA <= "00"; --sets PC to A exSel <= "10"; --???? ALUoutWE <= '1'; ALUSelB <= "011"; ALUop <= x"2"; PCSel <= "01"; PCWE <= '1'; next_state <= fetch; elsif (OPCODE = x"D") or (OPCODE = x"9") then --BZ or BNZ exSel <= "10"; ALUselA <= "00"; --00 ALUselB <= "011"; --011 ALUoutWE <= '1'; ALUop <= x"2"; Reg1Src <= '1'; AWE <= '1'; --add pc+extension and store in case next_state <= exec; BWE <= '1'; else if (OPCODE = x"0" or OPCODE = x"1" or OPCODE = x"2" or OPCODE = x"3" or OPCODE = x"4" or OPCODE = x"5" or OPCODE = x"6" or OPCODE = x"7") then --Do ALU Op ALUop <= OPCODE; Reg1Src <= '0'; Reg2Src <= '0'; AWE <= '1'; BWE <= '1'; next_state <= exec; else next_state <= fetch; end if; end if; when exec => if OPCODE = x"A" then --STW ALUselA <= "01"; ALUselB <= "011"; ALUop <= "0010"; ALUoutWE <= '1'; --dMemWrite <= '1'; --may need to move down a state next_state <= mem; exSel <= "01"; elsif OPCODE = x"8" then --LDW ALUoutWE <= '1'; ALUselA <= "01"; --added exSel <= "01"; ALUselB <= "011"; --added 011? ALUop <= "0010"; --dMemRead <= '1'; next_state <= mem; --without this data showsup elsif OPCODE = x"B" then ALUoutWE <= '1'; ALUselA <= "10"; ALUselB <= "011"; ALUop <= "0000"; exSel <= "00"; next_state<=writeback; elsif (OPCODE = x"F") and RT = x"2" then --NOT --OUTPUT is at aluout, write to rd ALUSelB <= "100"; --FFFF ALUSelA <= "01"; ALUop <= "0100"; --x"4"; ALUoutWE <= '1'; --clock output for RDRegWSrc <= "01"; --RFWE <= '1'; --RegWSrc <= "01"; next_state <= writeback; elsif (OPCODE = x"F") and RT = x"0" then --Jump ALUselA <= "01"; PCSel <= "00"; PCWE <= '1'; next_state <= fetch; elsif (OPCODE = x"D") then --BZ ALUSelA <= "01"; ALUSelB <= "001"; ALUop <= x"2"; --add rd + 0 to test if ZERO = '1' then --ALUoutWE <= '1'; --testing PCWE <= '1'; PCsel <= "10"; --ALUoutWE <= '0'; --to test for state next_state <= fetch; else --AWE <= '1'; PCsel <= "00"; PCWE <= '0'; --PCsel <= "10"; --PCWE <= '1'; next_state <= fetch; next_state <= fetch; end if; elsif (OPCODE = x"9") then --BNZ ALUSelA <= "01"; ALUSelB <= "001"; ALUop <= x"2"; if ZERO = '0' then --Reg1Src <= '0'; --AWE <= '0'; PCWE <= '1'; PCsel <= "10"; --10 next_state <= fetch; else PCsel <= "00"; PCWE <= '0'; next_state <= fetch; end if; next_state <= fetch; else --finish ALUop AlUSelA <= "01"; ALUSelB <= "000"; ALUop <= OPCODE; ALUoutWE <= '1'; --writes alu output next_state <= mem; end if; when mem => if dMemWait = '1' then if OPCODE = x"8" then dMemRead <= '1'; next_state <= mem; end if; if OPCODE = x"A" then dMemWrite <= '1'; next_state <= mem; end if; next_state <= mem; else if OPCODE = "1100" then --LDI RFWE <= '1'; next_state <= fetch; elsif OPCODE = x"B" then --LUI RFWE <= '1'; next_state <= fetch; elsif OPCODE = x"8"then --LDW --RFWE <='1'; --MDRWE <= '1'; -- ALUop <= "0010"; dMemRead <= '1'; --ALUoutWE <= '1'; MDRWE <= '1'; next_state <= writeback; elsif OPCODE = x"A" then --STW -- MDRWE <= '1'; --dMemWrite <= '1'; dMemWrite <= '1'; next_state <= fetch; elsif (OPCODE = x"D") or (OPCODE = x"9") then --BNZ or BZ if ZERO = '1' then ALUSelA <= "00"; --sets PC to A exSel <= "11"; --???? ALUSelB <= "011"; ALUop <= x"2"; PCSel <= "01"; PCWE <= '1'; next_state <= fetch; else next_state <= fetch; end if; else --ALUop Finish RegWSrc <= "01"; RFWE <= '1'; next_state <= fetch; end if; -- next_state <= fetch; end if; when writeback => if dMemWait = '1' then if OPCODE = x"8" then dMemRead <= '1'; MDRWE <= '1'; next_state <= writeback; end if; if OPCODE = x"A" then dMemWrite <= '1'; next_state <= writeback; end if; next_state <= writeback; else if OPCODE = x"8" then RFWE <= '1'; next_state <= fetch; --MDRWE <= '1'; end if; if OPCODE = x"A" then next_state <= fetch; end if; if OPCODE = x"B" then RegWSrc <= "01"; RFWE <= '1'; --ALUoutWE <= '1'; next_state <= fetch; end if; if (OPCODE = x"F") and RT = x"2" then RFWE <= '1'; RegWSrc <= "01"; next_state <= fetch; end if; --RFWE <= '1'; --MDRWE <= '1'; next_state <= fetch; end if; --RFWE <= '1'; --next_state <= fetch; when haltstate => Halt <= '1'; next_state <= haltstate; --when others => -- next_state <= fetch; end case; end process state_logic; state_register : process(CLK, nReset) begin if (nReset = '0') then state <= fetch; elsif (rising_edge(clk)) then state <= next_state; end if; end process state_register; end behavioral;