VHDL source for simple processor

See section 6 of the notes for description

package commonConstants is
	constant wordSize: integer := 16;
	constant adrLength: integer := 16;
end package commonConstants;

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.commonConstants.all;

entity ram is port (
        reset, en, r_w: in STD_LOGIC;
        aBus: in STD_LOGIC_VECTOR(adrLength-1 downto 0);
        dBus: inout STD_LOGIC_VECTOR(wordSize-1 downto 0));
end ram;

architecture ramArch of ram is
constant resAdrLength: integer := 6; -- address length restricted within architecture
constant memSize: integer := 2**resAdrLength;
type ram_typ is array(0 to memSize-1) of STD_LOGIC_VECTOR(wordSize-1 downto 0);
signal ram: ram_typ;
begin
	process(reset, en, r_w, aBus, dBus) begin
	  	if reset = '1' then
		      	-- basic instruction check
	        	ram(0)  <= x"1a0f"; -- immediate load
			ram(1)  <= x"2010"; -- direct load
		        ram(2)  <= x"3030"; -- indirect load
		        ram(3)  <= x"4034"; -- direct store
		        ram(4)  <= x"0001"; -- negate
		        ram(5)  <= x"2034"; -- direct load
		        ram(6)  <= x"0001"; -- negate
		        ram(7)  <= x"5032"; -- indirect store
		        ram(8)  <= x"0001"; -- negate
		        ram(9)  <= x"1fff"; -- immediate load
		        ram(10) <= x"a008"; -- add
		        ram(11) <= x"700d"; -- brZero
		        ram(12) <= x"0000"; -- halt
		        ram(13) <= x"1400"; -- immediate load
		        ram(14) <= x"8010"; -- brPos
		        ram(15) <= x"0000"; -- halt
		        ram(16) <= x"0001"; -- negate
		        ram(17) <= x"9013"; -- brNeg
		        ram(18) <= x"0000"; -- halt
		        ram(19) <= x"6015"; -- branch
		        ram(20) <= x"0000"; -- halt
		        ram(21) <= x"8014"; -- brPos
		        ram(22) <= x"7014"; -- brZero
		        ram(23) <= x"0001"; -- negate
		        ram(24) <= x"9014"; -- brNeg
		        ram(25) <= x"0000"; -- halt
		        ram(48) <= x"0031"; -- pointer for iload
		        ram(49) <= x"5af0"; -- target of iload
		        ram(50) <= x"0033"; -- pointer for istore
		        ram(51) <= x"0000"; -- target of istore
		        ram(52) <= x"f5af"; -- target of dstore
		elsif en = '1' and r_w = '0' then
	  		ram(conv_integer(unsigned(aBus(resAdrLength-1 downto 0)))) <= dBus;
		end if;
	end process;
	dBus <= ram(conv_integer(unsigned(aBus(resAdrLength-1 downto 0))))
  			when reset = '0' and en = '1' and r_w = '1' else
			(dbus'range => 'Z');
end ramArch;

---------------------------------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
use work.commonConstants.all;

entity cpu is port (
    	clk, reset 	: in  std_logic;
    	m_en, m_rw	: out std_logic;    	
	aBus		: out std_logic_vector(adrLength-1 downto 0);
	dBus		: inout std_logic_vector(wordSize-1 downto 0);
	-- these signals "exported" so they can be monitored in post-P&R simulation
	pcX, iarX	: out std_logic_vector(adrLength-1 downto 0);
	iregX, accX, aluX	: out std_logic_vector(wordSize-1 downto 0));
end cpu;

architecture cpuArch of cpu is
type state_type is (
	reset_state, fetch, halt, negate, mload, dload, iload,
	dstore, istore, branch, brZero, brPos, brNeg, add
);
signal state: state_type;

type tick_type is (t0, t1, t2, t3, t4, t5, t6, t7);
signal tick: tick_type;

signal pc: 	std_logic_vector(adrLength-1 downto 0); -- program counter
signal iReg: 	std_logic_vector(wordSize-1 downto 0); -- instruction register
signal iar: 	std_logic_vector(adrLength-1 downto 0); -- indirect address register
signal acc: 	std_logic_vector(wordSize-1 downto 0); -- accumulator
signal alu: 	std_logic_vector(wordSize-1 downto 0); -- alu output

begin
	alu <= 	(not acc) + x"0001" when state = negate else
				acc + dbus when state = add else
				(alu'range => '0');
	pcX <= pc; iregX <= ireg; iarX <= iar; accX <= acc; aluX <= alu;

	process(clk) -- perform actions that occur on rising clock edges

	function nextTick(tick: tick_type) return tick_type is begin
		-- return next logical value for tick
		case tick is
		when t0 => return t1; when t1 => return t2; when t2 => return t3;
		when t3 => return t4; when t4 => return t5; when t5 => return t6;
		when t6 => return t7; when others => return t0;
		end case;
	end function nextTick;

	procedure decode is begin
		-- Instruction decoding.
		case iReg(15 downto 12) is
		when x"0" =>
			if iReg(11 downto 0) = x"000" then 
				state <= halt;
			elsif iReg(11 downto 0) = x"001" then 
				state <= negate;
			end if;
		when x"1" => 	state <= mload;
		when x"2" => 	state <= dload;
		when x"3" => 	state <= iload;
		when x"4" => 	state <= dstore;
		when x"5" => 	state <= istore;
		when x"6" => 	state <= branch;
		when x"7" => 	state <= brZero;	
		when x"8" => 	state <= brPos;
		when x"9" => 	state <= brNeg;
		when x"a" => 	state <= add;
		when others => state <= halt;
		end case;
	end procedure decode;
  
	procedure wrapup is begin
		-- Do this at end of every instruction
		state <= fetch; tick <= t0;
	end procedure wrapup;

	begin
	  	if clk'event and clk = '1' then
	  		if reset = '1' then 
				state <= reset_state; tick <= t0;
				pc <= (pc'range => '0'); iReg <= (iReg'range => '0');
				acc <= (acc'range => '0'); iar <= (iar'range => '0');
    			else
				tick <= nextTick(tick) ; -- advance time by default
				case state is
				when reset_state => state <= fetch; tick <= t0;

				when fetch => 	if tick = t1 then iReg <= dBus; end if;
									if tick = t2 then 
										decode; pc <= pc + '1'; tick <= t0;
									end if;
				when halt => tick <= t0; -- do nothing

				when negate => acc <= alu;	wrapup;

				-- load instructions
				when mload => 
					if iReg(11) = '0' then -- sign extension
						acc <= x"0" & ireg(11 downto 0); 
					else
						acc <= x"f" & ireg(11 downto 0);
					end if;
					wrapup;

				when dload =>
					if tick = t1 then acc <= dBus; end if;
					if tick = t2 then wrapup; end if;

				when iload =>
					if tick = t1 then iar <= dBus; end if;
					if tick = t4 then acc <= dBus; end if;
					if tick = t5 then wrapup; end if;

				-- store instructions			  	
				when dstore =>
					if tick = t4 then wrapup; end if;

				when istore =>
					if tick = t1 then iar <= dBus; end if;
					if tick = t7 then wrapup; end if;

				-- branch instructions
				when branch => 
					pc <= x"0" & iReg(11 downto 0);
					wrapup;
				when brZero => 
					if acc = x"0000" then pc <= x"0" & iReg(11 downto 0);	end if;
					wrapup;
				when brPos => 
					if acc(15) = '0' and acc /= x"0000" then 
						pc <= x"0" & iReg(11 downto 0);
					end if;
					wrapup;
				when brNeg => 
					if acc(15) = '1' then pc <= x"0" & iReg(11 downto 0);	end if;
					wrapup;

				-- arithmetic instructions
				when add =>
					if tick = t1 then acc <= alu; end if;
					if tick = t2 then wrapup; end if;

				when others => state <= halt;
				end case;
			end if;
  		end if;
	end process;

	process(clk) begin -- perform actions that occur on falling clock edges
		if clk'event and clk ='0' then
			if reset = '1' then
				m_en <= '0'; m_rw <= '1';
				aBus <= (aBus'range => '0'); dBus <= (dBus'range => 'Z');
			else
				case state is

				when fetch =>
					if tick = t0 then m_en <= '1'; aBus <= pc; end if;
					if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;

			  	when dload =>
					if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;
					if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;

			  	when iload =>
					if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;
					if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;
					if tick = t3 then m_en <= '1'; aBus <= iar; end if;
					if tick = t5 then m_en <= '0'; aBus <= (abus'range => '0'); end if;
					
			  	when dstore =>
					if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;
					if tick = t1 then m_rw <= '0'; dBus <= acc; end if;
					if tick = t3 then m_rw <= '1'; end if;
					if tick = t4 then 
						m_en <= '0'; aBus <= (abus'range => '0'); dBus <= (dBus'range => 'Z'); 
					end if;

				when istore =>
					if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;
					if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;
					if tick = t3 then m_en <= '1'; aBus <= iar; end if;
					if tick = t4 then m_rw <= '0'; dBus <= acc; end if;
					if tick = t6 then m_rw <= '1'; end if;
					if tick = t7 then 
						m_en <= '0'; aBus <= (abus'range => '0'); dBus <= (dBus'range => 'Z'); 
					end if;

				when add =>
					if tick = t0 then m_en <= '1'; aBus <= x"0" & iReg(11 downto 0); end if;
					if tick = t2 then m_en <= '0'; aBus <= (aBus'range => '0'); end if;

				when others => -- do nothing
				end case;
			end if;	
		end if;					
	end process;
end cpuArch;

-------------------------------

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use work.commonConstants.all;

entity top is port(
	clk, reset: in STD_LOGIC;
	mem_enX, mem_rwX : out std_logic;
	aBusX : out std_logic_vector(adrLength-1 downto 0);
	dBusX : out std_logic_vector(wordSize-1 downto 0);
	pcX, iarX : out std_logic_vector(adrLength-1 downto 0);
	iregX, accX, aluX : out std_logic_vector(wordSize-1 downto 0));
end top;

architecture topArch of top is

component ram port (
        reset, en, r_w: in STD_LOGIC;
        aBus: in STD_LOGIC_VECTOR(adrLength-1 downto 0);
        dBus: inout STD_LOGIC_VECTOR(wordSize-1 downto 0));
end component;

component cpu port (
    	clk, reset:	in  STD_LOGIC;
    	m_en, m_rw: out STD_LOGIC;    	
	aBus:	out STD_LOGIC_VECTOR(adrLength-1 downto 0);
	dBus:	inout STD_LOGIC_VECTOR(wordSize-1 downto 0);
	pcX, iarX : out std_logic_vector(wordSize-1 downto 0);
	iregX, accX, aluX : out std_logic_vector(wordSize-1 downto 0));
end component;

signal mem_en, mem_rw: STD_LOGIC;
signal aBus, dBus: STD_LOGIC_VECTOR(15 downto 0);
signal pc, ireg, iar, acc, alu: std_logic_vector(15 downto 0);

begin
	ramC: ram port map(reset, mem_en, mem_rw, aBus, dBus);
	cpuC: cpu port map(clk, reset, mem_en, mem_rw, aBus, dBus,
			pc, iar, ireg, acc, alu);
	mem_enX <= mem_en; mem_rwX <= mem_rw;
	aBusX <= aBus; dBusX <= dBus;
	pcX <= pc; iregX <= ireg; iarX <= iar; accX <= acc; aluX <= alu;
end topArch;