Don't use tri-state logic for TDO; introduce TDO_EN signal to indicate when TDO is...
[c4m-jtag.git] / rtl / vhdl / c4m_jtag_idblock.vhdl
1 -- The JTAG id and bypass handling block
2
3 library ieee;
4 use ieee.std_logic_1164.ALL;
5
6 use work.c4m_jtag.ALL;
7
8 entity c4m_jtag_idblock is
9 generic (
10 IR_WIDTH: integer := 2;
11
12 PART_NUMBER: std_logic_vector(15 downto 0);
13 VERSION: std_logic_vector(3 downto 0) := "0100";
14 MANUFACTURER: std_logic_vector(10 downto 0)
15 );
16 port (
17 -- needed TAP signals
18 TCK: in std_logic;
19 TDI: in std_logic;
20 TDO: out std_logic;
21 TDO_EN: out std_logic := '0';
22
23 -- JTAG state
24 STATE: in TAPSTATE_TYPE;
25 NEXT_STATE: in TAPSTATE_TYPE;
26 DRSTATE: in std_logic;
27
28 -- The instruction
29 IR: in std_logic_vector(IR_WIDTH-1 downto 0)
30 );
31 end c4m_jtag_idblock;
32
33 architecture rtl of c4m_jtag_idblock is
34 constant IDCODE: std_logic_vector(31 downto 0) := VERSION & PART_NUMBER & MANUFACTURER & "1";
35
36 signal SR_ID: std_logic_vector(31 downto 0);
37 signal EN_TDO: boolean;
38
39 constant CMD_IDCODE: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_idcode(IR_WIDTH);
40 constant CMD_BYPASS: std_logic_vector(IR_WIDTH-1 downto 0) := c4m_jtag_cmd_bypass(IR_WIDTH);
41 begin
42 process (TCK)
43 begin
44 if rising_edge(TCK) then
45 if DRSTATE = '1' then
46 case STATE is
47 when Capture =>
48 SR_ID <= IDCODE;
49
50 when Shift =>
51 if IR = CMD_IDCODE then
52 SR_ID(30 downto 0) <= SR_ID(31 downto 1);
53 SR_ID(31) <= TDI;
54 elsif IR = CMD_BYPASS then
55 SR_ID(0) <= TDI;
56 else
57 null;
58 end if;
59
60 when others =>
61 null;
62 end case;
63 end if;
64 end if;
65 end process;
66
67 EN_TDO <= STATE = Shift and DRSTATE = '1' and (IR = CMD_IDCODE or IR = CMD_BYPASS);
68 TDO <= SR_ID(0) when EN_TDO else
69 '0';
70 TDO_EN <= '1' when EN_TDO else
71 '0';
72 end rtl;