-- andy chou -- controller library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; entity ctrl is -- you will need to add more -- ports here as design grows port ( rst : in STD_LOGIC; start : in STD_LOGIC; clk : in STD_LOGIC; imm : out std_logic_vector(3 downto 0) ); end ctrl; architecture fsm of ctrl is type state_type is (s0,s1,s2,s3,s4,s5,s6,done); signal state : state_type; -- constants declared for ease of reading code 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"; -- as you add more code for your algorithms make sure to increase the -- array size. ie. 2 lines of code here, means array size of 0 to 1. type PM_BLOCK is array (0 to 1) of std_logic_vector(7 downto 0); constant PM : PM_BLOCK := ( -- This algorithm loads an immediate value of 3 and then stops "00110011", -- loadi 3 "11111111" -- halt ); begin process (clk) -- these variables declared here don't change. -- these are the only data allowed inside -- our otherwise pure FSM 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 -- don't forget to take care of rst if (clk'event and clk = '1') then -- -- steady state -- case state is when s0 => -- steady state PC := 0; imm <= "0000"; if start = '1' then state <= s1; else state <= s0; end if; when s1 => -- fetch instruction IR := PM(PC); OPCODE := IR(7 downto 4); ADDRESS:= IR(3 downto 0); state <= s2; when s2 => -- increment PC PC := PC + 1; state <= s4; when s4 => -- decode instruction case OPCODE IS when loadi => -- notice we can use -- the instruction state <= s5; when "1111" => -- and the machine code -- interchangeably state <= done; when others => state <= s1; end case; -- these states are the ones in which you actually -- start sending signals across -- to the datapath depending on what opcode is decoded. -- you add more states here. when s5 => -- loadi iiii imm <= address; -- set the immediate port -- to the lower_ir state <= s6; when s6 => -- go back for next instruction state <= s1; when done => -- stay here forever state <= done; when others => end case; end if; end process; end fsm;