
\begin{minted}{vhdl}
library ieee;
use ieee.STD_LOGIC_1164.all;

entity serial_pattern_match is
	port (CLOCK_50 : in std_logic; -- 50MHz internal clock.
	btn : in std_logic; -- Manual clock signal using external PUSHBUTTON's rising edge. Inverted LOGIC.
	reset : in std_logic; -- RESET signal tied to external PUSHBUTTON. Inverted LOGIC.
	data : in std_logic; -- Current DATA bit set using external switch.
			
	LEDG7 : out std_logic; -- Indicates successful pattern detection when HIGH.
	LEDR : out std_logic_vector(7 downto 0)); -- Indicates current STATE 
end entity;

architecture rtl of serial_pattern_match is
	type stateType is (U,Q7,Q6,Q5,Q4,Q3,Q2,Q1,Q0); -- 8 states are needed to implement the Moore-machine.
	signal state : stateType;
	signal prevBtn : std_logic; -- Used to detect rising edge on 'btn'. 
	        -- Since we can't edge-trigger directly on a non-internal-clock signal, 
        -- we use a synchronous flip-flop to detect if a rising edge has occured since last internal-clock cycle.
begin
	---------------------------------------------------------------------------------------------
	-- Process: proc_moore_machine
	-- Description: Moore-machine implementation of algorithm detecting a specific pattern in a data-stream. 
	-- 				Pattern is (in chronological order ->): 1011001.
	
	-- Input(s)	    : CLOCK_50, btn, reset, data
	-- Output(s)	    : LEDG7, LEDR
	-- Internal Signals     : state, prevBtn
	---------------------------------------------------------------------------------------------
	proc_moore_machine:process(CLOCK_50, reset)
	begin
		if reset = '0' then -- asynchronous reset.
			state <= Q0; -- load inital state.
			LEDR <= (others => '0'); -- set all indicator LEDs LOW.
			LEDG7 <= '0';
		elsif (prevBtn = '0' AND btn = '1') then  -- if rising_edge(btn) then 
			case state is 
				when Q0 =>
					LEDR <= "00000001";
					if data = '1' then 
						state <= Q1;
						LEDR <= "00000010";
					else
						-- stay in current state.
					end if;
				when Q1 =>
					if data = '0' then 
						state <= Q2;
						LEDR <= "00000100";
					else
						-- stay in current state.
					end if;
				when Q2 =>
					if data = '1' then 
						state <= Q3;
						LEDR <= "00001000";
					else
						state <= Q0;
					end if;
				when Q3 =>
					if data = '1' then 
						state <= Q4;
						LEDR <= "00010000";
					else
						state <= Q2;
					end if;
				when Q4 =>
					if data = '1' then 
						state <= Q1;
					else
						state <= Q5;
						LEDR <= "00100000";
					end if;
				when Q5 =>
					if data = '1' then 
						state <= Q1;
					else
						state <= Q6;
						LEDR <= "01000000";
					end if;
				when Q6 =>
					if data = '1' then 
						state <= Q7;
						LEDR <= "10000000";
						LEDG7 <= '1'; -- Transition to last state means full sequence detected!
					else
						state <= Q0;
					end if;
				when Q7 =>
					if data = '1' then 
						state <= Q1;
						LEDG7 <= '0';
						LEDR <= "00000010";
					else
						state <= Q2;
						LEDG7 <= '0';
						LEDR <= "00000100";
					end if;
				when others => -- when 'U'
					-- do nothing
			end case;
		end if;
	end process;
	
	---------------------------------------------------------------------------------------------
	-- Process: proc_rising_edge_detect
	-- Description: Saves last PUSHBUTTON state.
	--              Allows detection of state change through comparison with current state.

	-- Input(s)		: btn
	-- Internal Signals	: prevBtn
	---------------------------------------------------------------------------------------------
	proc_rising_edge_detect:process(CLOCK_50)
	begin
		if rising_edge(CLOCK_50) then 
			prevBtn <= btn;
		end if;
	end process;
end architecture;	

\end{minted}

