--- /dev/null
+-- The JTAG state machine
+-- This is implemented based on the IEEE 1149.1 standard
+
+library ieee;
+use ieee.std_logic_1164.ALL;
+
+use work.c4m_jtag.ALL;
+
+entity c4m_jtag_tap_fsm is
+ port (
+ -- The TAP signals
+ TCK: in std_logic;
+ TMS: in std_logic;
+ TRST_N: in std_logic;
+
+ -- The state outputs
+ STATE: out TAPSTATE_TYPE;
+ NEXT_STATE: out TAPSTATE_TYPE;
+ DRSTATE: out std_logic;
+ IRSTATE: out std_logic
+ );
+end c4m_jtag_tap_fsm;
+
+architecture rtl of c4m_jtag_tap_fsm is
+ signal S_STATE: TAPSTATE_TYPE;
+ signal S_NEXT_STATE: TAPSTATE_TYPE;
+ signal S_DRSTATE: std_logic;
+ signal S_IRSTATE: std_logic;
+ signal NEXT_DRSTATE: std_logic;
+ signal NEXT_IRSTATE: std_logic;
+begin
+ STATE <= S_STATE;
+ NEXT_STATE <= S_NEXT_STATE;
+ DRSTATE <= S_DRSTATE;
+ IRSTATE <= S_IRSTATE;
+
+ process (TCK, TRST_N)
+ begin
+ if TRST_N = '0' then
+ S_DRSTATE <= '0';
+ S_IRSTATE <= '0';
+ S_STATE <= TestLogicReset;
+ elsif rising_edge(TCK) then
+ S_STATE <= S_NEXT_STATE;
+ S_DRSTATE <= NEXT_DRSTATE;
+ S_IRSTATE <= NEXT_IRSTATE;
+ end if;
+ end process;
+
+ NEXT_DRSTATE <=
+ '0' when S_NEXT_STATE = TestLogicReset else
+ '0' when S_NEXT_STATE = RunTestIdle else
+ '1' when S_NEXT_STATE = SelectDRScan else
+ '0' when S_NEXT_STATE = SelectIRScan else
+ S_DRSTATE;
+ NEXT_IRSTATE <=
+ '0' when S_NEXT_STATE = TestLogicReset else
+ '0' when S_NEXT_STATE = RunTestIdle else
+ '0' when S_NEXT_STATE = SelectDRScan else
+ '1' when S_NEXT_STATE = SelectIRScan else
+ S_IRSTATE;
+
+ process (S_STATE, TMS)
+ begin
+ case S_STATE is
+ when TestLogicReset =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= RunTestIdle;
+ else
+ S_NEXT_STATE <= TestLogicReset;
+ end if;
+
+ when RunTestIdle =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= RunTestIdle;
+ else
+ S_NEXT_STATE <= SelectDRScan;
+ end if;
+
+ when SelectDRScan =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Capture;
+ else
+ S_NEXT_STATE <= SelectIRScan;
+ end if;
+
+ when SelectIRScan =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Capture;
+ else
+ S_NEXT_STATE <= TestLogicReset;
+ end if;
+
+ when Capture =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Shift;
+ else
+ S_NEXT_STATE <= Exit1;
+ end if;
+
+ when Shift =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Shift;
+ else
+ S_NEXT_STATE <= Exit1;
+ end if;
+
+ when Exit1 =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Pause;
+ else
+ S_NEXT_STATE <= Update;
+ end if;
+
+ when Pause =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Pause;
+ else
+ S_NEXT_STATE <= Exit2;
+ end if;
+
+ when Exit2 =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= Shift;
+ else
+ S_NEXT_STATE <= Update;
+ end if;
+
+ when Update =>
+ if (TMS = '0') then
+ S_NEXT_STATE <= RunTestIdle;
+ else
+ S_NEXT_STATE <= SelectDRScan;
+ end if;
+
+ when others =>
+ S_NEXT_STATE <= TestLogicReset;
+ end case;
+ end process;
+end rtl;