1 ----------------------------------------------------------------------------
2 -- Simple JTAG controller, enhanced version
4 -- $Id: jtag.vhdl 35 2008-09-05 23:31:00Z strubi $
6 -- (c) 2005, 2006, 2011
7 -- Martin Strubel // <hackfin@section5.ch>
8 ----------------------------------------------------------------------------
12 -- This module implements a JTAG controller with a instruction register (IR)
13 -- and a data register (DR).
14 -- Data is clocked into the IR register MSB first,
15 -- into the DR register LSB first.
17 -- The reason for this inconsistent behaviour is, that this controller
18 -- allows variable sizes of data registers, depending on the IR value.
20 -- (Actually, the Blackfin CPU JTAG controller does it the same odd way)
22 -- The IR and DR register size is specified in the parameters:
27 -- All special functionality must be encoded outside this module, using
29 -- There is one exception: The Instruction "1111" is reserved for the
30 -- IR_BYPASS mode. In this mode, the TDI bit is passed onto TDO with a delay
31 -- of one bit, according to the JTAG standard.
33 -- The design is tested using the JTAG library coming with the ICEbear
38 use ieee.std_logic_1164.
all;
39 use IEEE.std_logic_unsigned.
all;
40 use IEEE.numeric_std.
all; -- TO_INTEGER
45 entity JtagController
is
46 generic (IRSIZE
: natural
:= 4;
47 DRSIZE
: natural
:= 8);
51 tms
, -- Tap mode select
52 tdi
: in std_logic; -- Tap data in
53 tdo
: out std_logic; -- Tap data out
54 state
: out jtag_state_type
; -- JTAG machine state
55 -- Data register input:
56 dr_in
: in std_logic_vector (DRSIZE
-1 downto 0);
57 -- Configureable DR size:
58 msbpos
: in bitpos_type
;
59 -- Data register output:
60 dr_out
: out std_logic_vector (DRSIZE
-1 downto 0);
61 -- Instruction register:
62 ir_out
: out std_logic_vector (IRSIZE
-1 downto 0)
66 architecture behaviour
of JtagController
is
68 -- The only fixed instruction: All ones. Reserved for bypassing.
69 constant IR_BYPASS
: std_logic_vector (IRSIZE
-1 downto 0) :=
72 signal mystate
: jtag_state_type
:= TEST_LOGIC_RESET
;
73 signal next_state
: jtag_state_type
;
75 signal s_dr
: std_logic_vector (DRSIZE
-1 downto 0);
76 signal s_ir
: std_logic_vector (IRSIZE
-1 downto 0) :=
79 signal msb
: bitpos_type
;
81 -- Disabled: Buffered register
82 -- signal ir : std_logic_vector (IRSIZE-1 downto 0);
87 process (mystate
, tms
)
92 next_state
<= EXIT1_DR
;
94 next_state
<= SHIFT_DR
;
98 next_state
<= EXIT1_IR
;
100 next_state
<= SHIFT_IR
;
104 next_state
<= UPDATE_DR
;
106 next_state
<= PAUSE_DR
;
110 next_state
<= UPDATE_IR
;
112 next_state
<= PAUSE_IR
;
116 next_state
<= UPDATE_DR
;
118 next_state
<= SHIFT_DR
;
122 next_state
<= UPDATE_IR
;
124 next_state
<= SHIFT_IR
;
128 next_state
<= EXIT2_DR
;
130 next_state
<= PAUSE_DR
;
134 next_state
<= EXIT2_IR
;
136 next_state
<= PAUSE_IR
;
138 when RUN_TEST_IDLE
=>
140 next_state
<= SELECT_DR
;
142 next_state
<= RUN_TEST_IDLE
;
146 next_state
<= SELECT_IR
;
148 next_state
<= CAPTURE_DR
;
152 next_state
<= TEST_LOGIC_RESET
;
154 next_state
<= CAPTURE_IR
;
158 next_state
<= EXIT1_DR
;
160 next_state
<= SHIFT_DR
;
164 next_state
<= EXIT1_IR
;
166 next_state
<= SHIFT_IR
;
168 when TEST_LOGIC_RESET
=>
170 next_state
<= TEST_LOGIC_RESET
;
172 next_state
<= RUN_TEST_IDLE
;
176 next_state
<= SELECT_DR
;
178 next_state
<= RUN_TEST_IDLE
;
182 next_state
<= SELECT_DR
;
184 next_state
<= RUN_TEST_IDLE
;
190 -- When we're in BYPASS, use MSB 0
191 msb
<= 0 when s_ir
= IR_BYPASS
else msbpos
;
194 process (mystate
, s_ir
, s_dr
)
198 tdo
<= s_ir
(0); -- Shift out LSB
200 tdo
<= s_dr
(msb
); -- Take MSB
210 mystate
<= TEST_LOGIC_RESET
;
211 elsif rising_edge
(tck
) then
212 mystate
<= next_state
; -- Advance to next state
219 if rising_edge
(tck
) then
220 -- takes effect when entering the concerning state
222 -- When resetting, go into BYPASS mode
223 when TEST_LOGIC_RESET
=>
224 s_ir
<= (others => '1');
225 s_dr
<= (others => '0');
229 -- Mystate is the current state, process takes effect on rising TCK when IN
230 -- the concerning state.
233 s_ir
<= tdi
& s_ir
(IRSIZE
-1 downto 1); -- Shift in from MSB
235 s_dr
<= s_dr
(DRSIZE
-2 downto 0) & tdi
; -- likewise from LSB
237 -- We could move this BYPASS check to a higher level module. But since
238 -- it's a reserved command, we leave it in here.
239 if (s_ir
/= IR_BYPASS
) then
240 s_dr
<= dr_in
; -- Latch!
247 -- always assign state to output
248 -- We assign nextstate which is valid on the rising_edge of tck