library ieee;
use ieee.std_logic_1164.all;

entity tap_control is port(
	trst, tms, tck:			in std_logic;
	reset,enable,select_1:		out std_logic;
	clk_ir,sfir,udir:	out std_logic;
	clk_dr,sfdr,uddr:	out std_logic);
end tap_control;
	
architecture arch1 of tap_control is
	type StateType is (test_logic_reset,run_test_idle,
	select_dr,capture_dr,shift_dr,exit1_dr,pause_dr,exit2_dr,update_dr,
	select_ir,capture_ir,shift_ir,exit1_ir,pause_ir,exit2_ir,update_ir);
	signal present_state,next_state : StateType;
begin
state_comb:process(tms,trst,tck,present_state)
begin
	if (trst = '0') then
		next_state <= test_logic_reset;
	else
		case present_state is
			when test_logic_reset => 
			  reset <= '0'; enable <= '0'; select_1 <= '1'; 
			  clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			  clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
			if (tms = '0') then
				next_state <= run_test_idle;
			else
				next_state <= test_logic_reset;
			end if;

			when run_test_idle =>
			   reset <= '1'; enable <= '0'; select_1 <= '1'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
			if (tms = '1') then
				next_state <= select_dr;
			else
				next_state <= run_test_idle;
			end if;

			when select_dr =>
			   reset <= '1'; enable <= '0'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '0') then
					next_state <= capture_dr;
				else
					next_state <= select_ir;
				end if;

			when capture_dr =>
			   reset <= '1'; enable <= '0'; select_1 <= '1'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '0') then
					next_state <= shift_dr;
				else
					next_state <= exit1_dr;
				end if;

			when shift_dr =>
			   reset <= '1'; enable <= '1'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   sfdr <= '1'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= exit1_dr;
				else
					next_state <= shift_dr;
				end if;

			when exit1_dr =>
			   reset <= '1'; enable <= '0'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '0') then
					next_state <= pause_dr;
				else
					next_state <= update_dr;
				end if;

			when pause_dr =>
			   reset <= '1'; enable <= '0'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= exit2_dr;
				else
					next_state <= pause_dr;
				end if;

			when exit2_dr =>
			  reset <= '1'; enable <= '1'; select_1 <= '0'; 
			  clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			  clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= update_dr;
				else
					next_state <= shift_dr;
				end if;

			when update_dr =>
			   reset <= '1'; enable <= '0'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '1'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= select_dr;
				else
					next_state <= run_test_idle;
				end if;

			when select_ir =>
			  reset <= '1'; enable <= '0'; select_1 <= '0'; 
			  clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			  clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '0') then
					next_state <= capture_ir;
				else
					next_state <= test_logic_reset;
				end if;

			when capture_ir =>
			   reset <= '1'; enable <= '0'; select_1 <= '1'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '0') then
					next_state <= shift_ir;
				else
					next_state <= exit1_ir;
				end if;

			when shift_ir =>
			   reset <= '1'; enable <= '1'; select_1 <= '1'; 
			   sfir <= '1'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= exit1_ir;
				else
					next_state <= shift_ir;
				end if;

			when exit1_ir =>
			   reset <= '1'; enable <= '0'; select_1 <= '0'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if(tms = '0') then
					next_state <= pause_ir;
				else
					next_state <= update_ir;
				end if;

			when pause_ir =>
			   reset <= '1'; enable <= '0'; select_1 <= '1'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= exit2_ir;
				else
					next_state <= pause_ir;
				end if;

			when exit2_ir =>
			   reset <= '1'; enable <= '1'; select_1 <= '1'; 
			   clk_ir <= '1'; sfir <= '0'; udir <= '0'; 
			   clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= update_ir;
				else
					next_state <= shift_ir;
				end if;

			when update_ir =>
			reset <= '1'; enable <= '0'; select_1 <= '1'; 
			clk_ir <= '1'; sfir <= '0'; udir <= '1'; 
			clk_dr <= '1'; sfdr <= '0'; uddr <= '0'; 
				if (tms = '1') then
					next_state <= select_dr;
				else
					next_state <= run_test_idle;
				end if;
 
		end case;
	end if;
end process state_comb;
state_clocked:process(tck) begin
	if rising_edge(tck) then
		present_state <= next_state;
	end if;
end process state_clocked;
end arch1;
