jtag: Apply Martin Strubel JTAG implementation for ZPU
[zpu.git] / zpu / hdl / tap / tap.vhd
blob41dc07b5370e5488fd31a13f3c13599a9bdcc135
1 -- Example Test Access Port (TAP) controller implementation
2 -- (c) 2005-2011 Martin Strubel <hackfin@section5.ch>
4 -- General behaviour summary:
6 -- * JtagController entity decodes the TMS and TDI sequences
7 -- * IR and DR are decoded by this TAP controller
8 -- * Signals to a CPU core are generated by the TAP. See
9 -- "Core emulation signals" below. These are mapped into a control register:
10 -- emuctl [W]
11 -- * Signals from a CPU core are mapped into a status register:
12 -- emustat [R]
14 -- Note: Fixed size IR register is clocked in LSB first,
15 -- Variable size DR register is clocked in MSB first.
17 -- The default EMUIR value on a state machine reset is set to
18 -- INS_NOP, which should be defined properly by the parent module.
19 -- This is necessary for the core to not run any spurious command when
20 -- a breakpoint was hit and the JTAG state machine enters Run-Test-Idle.
22 -- This TAP is supported by a generic software library as part of the
23 -- ICEbear software suite.
25 library ieee;
26 use ieee.std_logic_1164.all;
27 use ieee.numeric_std.all;
29 library work;
30 use work.jtag.all;
31 -- TAP register definitions (generated):
32 use work.tap_registers.all;
34 entity tap is
35 generic (EMUDAT_SIZE : natural := 32;
36 EMUIR_SIZE : natural := 8;
37 IDCODE : std_logic_vector(32-1 downto 0) := x"deadbeef";
38 INS_NOP : std_logic_vector(8-1 downto 0) := x"00");
39 port (
40 -- JTAG signals:
41 tck, trst, tms, tdi : in std_logic;
42 tdo : out std_logic;
43 -- Core <-> TAP signals:
44 core_reset : out std_logic; -- Reset core logic
45 emuexec : out std_logic; -- Execute opcode on rising edge
46 emurequest : out std_logic; -- Emulation request to core
47 emuack : in std_logic; -- Core has acknowledged EMULATION request
48 emurdy : in std_logic; -- Core ready to execute next instruction
49 pulse : in std_logic; -- Pulse event counter
50 -- PC of possibly running core. Allows to access PC without
51 -- entering emulation.
52 dbgpc : in std_logic_vector(EMUDAT_SIZE-1 downto 0); -- PC
54 -- Extra status bits, core dependent
55 exstat : in std_logic_vector(7 downto 0);
57 emudata_i : in std_logic_vector(EMUDAT_SIZE-1 downto 0);
58 emudata_o : out std_logic_vector(EMUDAT_SIZE-1 downto 0);
59 -- Not implemented in this version
60 -- emudat_wr : in std_logic;
61 -- emudat_rd : in std_logic;
62 emuir : out std_logic_vector(EMUIR_SIZE-1 downto 0)
64 end tap;
66 architecture behaviour of tap is
68 -- Use generated registers from tap_pkg.vhd
70 -- Note: all ones is always reserved for BYPASS
71 -- all zeros is normally reserved for EXTEST
73 signal jtag_state : jtag_state_type;
75 signal exec : std_logic := '0';
77 -- Emulation control/status registers:
78 signal emustat : std_logic_vector(16-1 downto 0);
79 signal emuctl : std_logic_vector(16-1 downto 0) := x"0000";
81 -- Core emulation signals:
83 signal dr_in : std_logic_vector(EMUDAT_SIZE-1 downto 0);
84 signal dr_out : std_logic_vector(EMUDAT_SIZE-1 downto 0);
86 signal count1 : unsigned(32-1 downto 0);
87 signal count1_reset : std_logic;
88 signal count2 : unsigned(16-1 downto 0);
90 signal ir : std_logic_vector(4-1 downto 0);
92 -- Position of MSB of data register when not in BYPASS
93 -- (defines length of DR register). See also jtag_config.vhd
94 signal msbpos : bitpos_type := 31;
96 -- Emulation auxiliaries:
98 -- Emulation data register for exchange between core and JTAG:
99 signal emudat_i : std_logic_vector(EMUDAT_SIZE-1 downto 0);
100 signal emudat_o : std_logic_vector(EMUDAT_SIZE-1 downto 0);
101 -- These signals are just stubs. Not implemented in this version.
102 -- signal emudat_rxf : std_logic; -- Receive full
103 -- signal emudat_txe : std_logic := '0'; -- Transmit empty
104 -- signal emudat_ovr : std_logic := '0'; -- Overrun
105 -- signal emudat_unr : std_logic := '0'; -- Underrun
107 begin
108 i_jtag : JtagController
109 port map (
110 tck => tck,
111 tms => tms,
112 tdi => tdi,
113 tdo => tdo,
114 trst => trst,
115 state => jtag_state,
116 dr_out => dr_out,
117 msbpos => msbpos,
118 dr_in => dr_in,
119 ir_out => ir
122 -- Select DR register according to supported IRs
123 -- We sample this with tck to avoid gated clock issues
125 select_dr:
126 process (tck)
127 begin
128 if rising_edge(tck) then
129 case ir is
130 when TAP_IDCODE =>
131 dr_in <= IDCODE;
132 msbpos <= 31;
133 when TAP_EMUDATA =>
134 dr_in <= emudata_i;
135 msbpos <= emudata_i'length - 1;
136 when TAP_EMUSTAT =>
137 dr_in(emustat'length-1 downto 0) <= emustat;
138 msbpos <= emustat'length - 1;
139 when TAP_DBGPC =>
140 dr_in <= dbgpc;
141 msbpos <= dbgpc'length - 1;
142 when TAP_COUNT1 =>
143 dr_in(count1'length-1 downto 0) <= std_logic_vector(count1);
144 msbpos <= count1'length - 1;
145 when TAP_COUNT2 =>
146 dr_in(count2'length-1 downto 0) <= std_logic_vector(count2);
147 msbpos <= count2'length - 1;
148 when others =>
149 dr_in <= (others => 'X');
150 msbpos <= 31;
151 end case;
152 end if;
153 end process;
156 -- NOTE: action is being taken when ENTERING the concerning state
157 -- on rising edge of tck.
159 -- exec is the signal sent to the core. It is like an IRQ event, thus
160 -- it must be properly treated as an exception (edge sensitive)
161 -- inside the core logic.
163 decode_scanchain_w:
164 process (tck)
165 begin
166 if rising_edge(tck) then
167 count1_reset <= '0';
168 exec <= '0';
169 case jtag_state is
170 when UPDATE_DR =>
171 if ir = TAP_EMUCTRL then
172 emuctl <= dr_out(15 downto 0);
173 elsif ir = TAP_EMUDATA then
174 emudat_o <= dr_out;
175 elsif ir = TAP_EMUIR then
176 emuir <= dr_out(EMUIR_SIZE-1 downto 0);
177 end if;
178 when TEST_LOGIC_RESET =>
179 count1_reset <= '1';
180 count2 <= (others => '0');
181 emuctl <= (others => '0');
182 emudat_o <= (others => '0');
183 -- Important to reset the EMUIR to NOP for sane JTAG operation:
184 emuir <= INS_NOP;
185 when RUN_TEST_IDLE =>
186 count2 <= count2 + 1;
187 exec <= '1';
188 when others =>
189 end case;
190 end if;
191 end process;
193 pulse_count:
194 process (count1_reset, pulse)
195 begin
196 if count1_reset = '1' then
197 count1 <= (others => '0');
198 elsif rising_edge(pulse) then
199 count1 <= count1 + 1;
200 end if;
201 end process;
203 emuexec <= exec;
204 emurequest <= emuctl(0);
205 core_reset <= emuctl(15);
207 -- Registers:
208 emudata_o <= emudat_o;
210 -- FIXME:
211 -- These mappings should probably move to glue between TAP and core
212 -- to be more generic.
214 emustat <= exstat &
215 "0000" & "00" & emurdy & emuack;
217 end behaviour;