-- Copyright 2000 UCR all rights reserved -- this program may be copy or altered so -- long as this header stays intake -- Original design Randy January rjanuary@cs.ucr.edu library IEEE; use IEEE.STD_LOGIC_1164.all; use IEEE.STD_LOGIC_ARITH.all; use WORK.SCPU_LIB.all; entity scpu_cntrl is port( clk : in std_logic; reset : in std_logic; jmp : in std_logic; rom_command : in unsigned (31 downto 0); interrupt : in std_logic; W_sel : out std_logic; R1_sel : out std_logic; R2_sel : out std_logic; O_sel : out std_logic; r_wEn : out std_logic; Zcheck : out std_logic; signChk : out std_logic; sign_out : in std_logic; mux_sel : out unsigned (1 downto 0); sh_sel : out unsigned (1 downto 0); alu_sel : out unsigned (2 downto 0); rom_address : out integer; ram_address : out unsigned (8 downto 0); imm : out unsigned (31 downto 0); Wrf_address : out unsigned (8 downto 0); Rrf1_address : out unsigned (8 downto 0); Rrf2_address : out unsigned (8 downto 0) ); end scpu_cntrl; architecture scpu_cntrl of scpu_cntrl is --***************************************************************************** type state_type is (S0, S1, S2, S3); type sub_state_type is (SS0, SS1, SS2); signal state: state_type; signal sub_state: sub_state_type; signal haltsig: std_logic; signal rom_add : unsigned (8 downto 0); signal opcodes : unsigned (4 downto 0); signal operand1s, operand2s, operand3s : unsigned(8 downto 0); --***************************************************************************** begin process (clk, reset, jmp, rom_command, interrupt) variable OPCODE : unsigned(4 downto 0); variable OPERAND1, OPERAND2, OPERAND3 : unsigned(8 downto 0); variable PC : integer; --***************************************************************************** procedure execute(OPCODE2 : unsigned (4 downto 0)) is begin -- loadi current takes in an 18 bit number and pads to -- the left the sign bit, this needs to be changed to -- seperate loadlow and loadhigh commands to get the -- full 32-bit input. if (OPCODE2 = loadi) then mux_sel <= "00"; W_sel <= '1'; O_sel <= '0'; for i in 18 to 31 loop imm(i) <= rom_command(17); end loop; -- i imm(17 downto 0) <= rom_command(17 downto 0); Rrf1_address <= OPERAND1; R1_sel <= '1'; alu_sel <= "000"; sh_sel <= "00"; Wrf_address <= OPERAND1; elsif (OPCODE2 = loadm) then mux_sel <= "10"; r_wEn <= '0'; O_sel <= '0'; W_sel <= '1'; Wrf_address <= OPERAND1; ram_address <= OPERAND2; elsif (OPCODE2 = store) then mux_sel<= "01"; r_wEn <= '1'; O_sel <= '0'; W_sel <= '0'; ram_address <= OPERAND1; else Wrf_address <= OPERAND1; Rrf1_address <= OPERAND2; Rrf2_address <= OPERAND3; mux_sel <= "01"; R1_sel <= '1'; R2_sel <= '1'; case OPCODE2 is when add => O_sel <= '0'; W_sel <= '1'; alu_sel <= "001"; sh_sel <= "00"; signChk <= '0'; when subt => O_sel <= '0'; W_sel <= '1'; R2_sel <= '1'; alu_sel <= "010"; sh_sel <= "00"; signChk <= '0'; when and_r => O_sel <= '0'; W_sel <= '1'; R2_sel <= '1'; alu_sel <= "011"; sh_sel <= "00"; signChk <= '0'; when xor_r => O_sel <= '0'; W_sel <= '1'; R2_sel <= '1'; alu_sel <= "100"; sh_sel <= "00"; signChk <= '0'; when or_r => O_sel <= '0'; W_sel <= '1'; R2_sel <= '1'; alu_sel <= "110"; sh_sel <= "00"; signChk <= '0'; when shl_r => O_sel <= '0'; W_sel <= '1'; R2_sel <= '0'; alu_sel <= "000"; sh_sel <= "10"; signChk <= '0'; when shr_r => O_sel <= '0'; W_sel <= '1'; R2_sel <= '0'; alu_sel <= "000"; sh_sel <= "01"; signChk <= '0'; when sign => O_sel <= '0'; W_sel <= '0'; alu_sel <= "000"; sh_sel <= "00"; signChk <= '1'; R2_sel <= '0'; when jnz => alu_sel <= "000"; sh_sel <= "00"; O_sel <= '0'; W_sel <= '0'; Zcheck <= '1'; signChk <= '0'; R2_sel <= '0'; when halt => alu_sel <= "000"; sh_sel <= "00"; W_sel <= '0'; O_sel <= '1'; haltsig <= '1'; signChk <= '0'; when others => NULL; end case; end if; end execute; --***************************************************************************** begin --***************************************************************************** -- reset if (reset = '1') then haltsig <= '0'; state <= S0; sub_state <= SS0; W_sel <= '0'; R1_sel <= '0'; R2_sel <= '0'; Wrf_address <= CZ_9; Rrf1_address <= CZ_9; Rrf2_address <= CZ_9; haltsig <= '0'; alu_sel <= "000"; mux_sel <= "00"; O_sel <= '0'; rom_address <= 0; ram_address <= "000000000"; Zcheck <= '0'; signChk <= '0'; --***************************************************************************** elsif (clk'event and clk = '1') then case state is -- RESET STATE when S0 => PC := 0; rom_address <= PC; imm <= "00000000000000000000000000000000"; state <= S1; when S1 => case sub_state is --FETCH STATE when SS0 => OPCODE := rom_command(31 downto 27); OPERAND1 := rom_command(26 downto 18); OPERAND2 := rom_command(17 downto 9); OPERAND3 := rom_command(8 downto 0); opcodes <= OPCODE; operand1s <= OPERAND1; operand2s <= OPERAND2; operand3s <= OPERAND3; sub_state <= SS1; state <= S1; -- WAIT STATE when SS2 => sub_state <= SS0; state <= S2; --EXECUTE STATE when SS1 => state <= S1; execute(OPCODE); sub_state <= SS2; when others => NULL; end case; when S2 => if(interrupt = '1') then state <= S3; end if; case sub_state is when SS0 => -- Zcheck <= '0'; W_sel <= '0'; -- mux_sel <= "01"; -- r_wEn <= '0'; -- sh_sel <= "00"; alu_sel <= "000"; if (haltsig = '1') then sub_state <= SS2; state <= S2; elsif (jmp = '1') then PC := conv_integer(rom_command(8 downto 0)); rom_address <= PC; sub_state <= SS1; state <= S2; elsif (sign_out = '1') then PC := conv_integer(rom_command(8 downto 0)); rom_address <= PC; sub_state <= SS1; state <= S2; else PC := PC + 1; rom_address <= PC; state <= S2; sub_state <= SS1; end if; when SS1 => signChk <= '0'; Zcheck <= '0'; W_sel <= '0'; mux_sel <= "01"; r_wEn <= '0'; sh_sel <= "00"; alu_sel <= "000"; sub_state <= SS0; state <= S1; when SS2 => W_sel <= '0'; sh_sel <= "00"; mux_sel <= "01"; r_wEn <= '0'; sub_state <= SS0; state <= S3; end case; when S3 => state <= S3; end case; end if; end process; end scpu_cntrl;