-- Code courtesy of Ron A. -- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity FSM is port( clk:in std_logic; rst:in std_logic; -- Add your ports to communicate with the data path immediate:out std_logic_vector (3 downto 0) --Like this one ); end FSM; architecture FSM_arch of FSM is type state_type is (HomeState,FetchState,PCstate,OpcodeState, -- You will need to add lots of states here -- LoadImm_state ,Halt_state,waitstate,LoadImm_state2); signal current_state : state_type; signal next_state : state_type; constant mova : std_logic_vector(3 downto 0) := "0000"; constant movr : std_logic_vector(3 downto 0) := "0001"; constant loadmem : std_logic_vector(3 downto 0) := "0010"; constant loadi : std_logic_vector(3 downto 0) := "0011"; constant jz : std_logic_vector(3 downto 0) := "0101"; constant jmp : std_logic_vector(3 downto 0) := "0110"; constant add : std_logic_vector(3 downto 0) := "0111"; constant andr : std_logic_vector(3 downto 0) := "1001"; constant shr : std_logic_vector(3 downto 0) := "1010"; constant halt : std_logic_vector(3 downto 0) := "1111"; type PM_BLOCK is array (1 to 2) of std_logic_vector(7 downto 0); constant PM : PM_BLOCK := ( -- This is where you will eventually put your whole program -- You will need to change the index of the array each time you -- add an instruction. "00110001", -- This is the OPCODE for LOAD IMMEDIATE -- In this case, the immediate is "0001" "11111111" -- Halt ); begin state_register : process (rst, clk) begin if (rst = '1') then current_state <= HomeState; elsif (clk'event and clk='1') then current_state <= next_state; end if; end process state_register; comb_part : process (current_state) variable IR : std_logic_vector(7 downto 0); variable OPCODE : std_logic_vector( 3 downto 0); variable ADDRESS : std_logic_vector (3 downto 0); variable PC : integer; begin case current_state is when HomeState => -- steady state PC := 1; next_state <= FetchState; when FetchState => -- fetch instruction IR := PM(PC); OPCODE := IR(7 downto 4); ADDRESS:= IR(3 downto 0); next_state <= PCstate; when PCstate => -- increment PC PC := PC + 1; -- note that this increments the PC to -- one more than the one currently being -- executed. next_state <= OpcodeState; when OpcodeState => -- decode instruction case OPCODE IS when loadi => --See how you can use the constants --from earlier? otherwise, this would --read: when "0011" => next_state <= LoadImm_state; when halt => next_state <= halt_state; -- You need to fill in the rest here. when others => next_state <= FetchState; end case; -- There will be lots of other states here. -- Some instructions will only need one, some -- will need more. when LoadImm_state => --Accumulator=Immediate immediate <= Address; -- Here you need to set up the communications with the -- datapath to make sure immediate gets into the accumulator next_state <= LoadImm_state2; when LoadImm_state2 => -- This is also going to need some signals to be set next_state <= waitstate; when halt_state => next_state <= halt_state; -- Wait forever when waitstate => -- Set the accumulator to not load next_state <= FetchState; when others => null; end case; end process comb_part; end FSM_arch;