1 |
5 |
sergeykhbr |
--!
|
2 |
|
|
--! Copyright 2018 Sergey Khabarov, sergeykhbr@gmail.com
|
3 |
|
|
--!
|
4 |
|
|
--! Licensed under the Apache License, Version 2.0 (the "License");
|
5 |
|
|
--! you may not use this file except in compliance with the License.
|
6 |
|
|
--! You may obtain a copy of the License at
|
7 |
|
|
--!
|
8 |
|
|
--! http://www.apache.org/licenses/LICENSE-2.0
|
9 |
|
|
--! Unless required by applicable law or agreed to in writing, software
|
10 |
|
|
--! distributed under the License is distributed on an "AS IS" BASIS,
|
11 |
|
|
--! WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12 |
|
|
--! See the License for the specific language governing permissions and
|
13 |
|
|
--! limitations under the License.
|
14 |
|
|
--!
|
15 |
|
|
|
16 |
|
|
library ieee;
|
17 |
|
|
use ieee.std_logic_1164.all;
|
18 |
|
|
library commonlib;
|
19 |
|
|
use commonlib.types_common.all;
|
20 |
|
|
|
21 |
|
|
entity dcom_jtag is
|
22 |
|
|
generic (
|
23 |
|
|
irlen : integer range 2 to 8 := 2;
|
24 |
|
|
idcode : integer range 0 to 255 := 9;
|
25 |
|
|
ainst : integer range 0 to 255 := 2; -- IR rw,address,size (35 bits)
|
26 |
|
|
dinst : integer range 0 to 255 := 3; -- IR data (32 bits)
|
27 |
|
|
id : std_logic_vector(31 downto 0) := X"01040093");
|
28 |
|
|
port (
|
29 |
|
|
rst : in std_ulogic;
|
30 |
|
|
tck : in std_ulogic;
|
31 |
|
|
tms : in std_ulogic;
|
32 |
|
|
tdi : in std_ulogic;
|
33 |
|
|
tdo : out std_ulogic;
|
34 |
|
|
tapi_tdo : in std_ulogic;
|
35 |
|
|
tapo_tck : out std_ulogic;
|
36 |
|
|
tapo_tdi : out std_ulogic;
|
37 |
|
|
tapo_inst : out std_logic_vector(7 downto 0);
|
38 |
|
|
tapo_rst : out std_ulogic;
|
39 |
|
|
tapo_capt : out std_ulogic;
|
40 |
|
|
tapo_shft : out std_ulogic;
|
41 |
|
|
tapo_upd : out std_ulogic;
|
42 |
|
|
tapo_xsel1 : out std_ulogic;
|
43 |
|
|
tapo_xsel2 : out std_ulogic
|
44 |
|
|
);
|
45 |
|
|
end;
|
46 |
|
|
|
47 |
|
|
|
48 |
|
|
architecture rtl of dcom_jtag is
|
49 |
|
|
|
50 |
|
|
type ltap_out_type is record
|
51 |
|
|
tck : std_ulogic;
|
52 |
|
|
tdi : std_ulogic;
|
53 |
|
|
inst : std_logic_vector(7 downto 0);
|
54 |
|
|
asel : std_ulogic;
|
55 |
|
|
dsel : std_ulogic;
|
56 |
|
|
reset : std_ulogic;
|
57 |
|
|
capt : std_ulogic;
|
58 |
|
|
shift : std_ulogic;
|
59 |
|
|
upd : std_ulogic;
|
60 |
|
|
end record;
|
61 |
|
|
|
62 |
|
|
constant BYPASS : std_logic_vector(irlen-1 downto 0) := (others => '1');
|
63 |
|
|
constant IDCODE_I : std_logic_vector(irlen-1 downto 0) := conv_std_logic_vector(idcode, irlen);
|
64 |
|
|
|
65 |
|
|
type state_type is (test_rst, run_idle, select_dr, capture_dr, shift_dr, exit1_dr,
|
66 |
|
|
pause_dr, exit2_dr, update_dr, select_ir, capture_ir, shift_ir,
|
67 |
|
|
exit1_ir, pause_ir, exit2_ir, update_ir);
|
68 |
|
|
|
69 |
|
|
type reg_type is record
|
70 |
|
|
state : state_type;
|
71 |
|
|
inst : std_logic_vector(irlen-1 downto 0);
|
72 |
|
|
shft : std_logic_vector(31 downto 0);
|
73 |
|
|
tdo : std_ulogic;
|
74 |
|
|
sel_user1 : std_logic;
|
75 |
|
|
sel_user2 : std_logic;
|
76 |
|
|
end record;
|
77 |
|
|
|
78 |
|
|
signal r, rin : reg_type;
|
79 |
|
|
|
80 |
|
|
begin
|
81 |
|
|
|
82 |
|
|
comb : process(tck, tms, tdi, tapi_tdo, r)
|
83 |
|
|
variable v : reg_type;
|
84 |
|
|
variable vtapo : ltap_out_type;
|
85 |
|
|
variable vtdo : std_ulogic;
|
86 |
|
|
begin
|
87 |
|
|
|
88 |
|
|
v := r;
|
89 |
|
|
vtapo.tck := tck;
|
90 |
|
|
vtapo.reset := '0';
|
91 |
|
|
vtapo.tdi := tdi;
|
92 |
|
|
vtapo.inst := (others => '0');
|
93 |
|
|
vtapo.inst(irlen-1 downto 0) := r.inst;
|
94 |
|
|
vtapo.capt := '0';
|
95 |
|
|
vtapo.upd := '0';
|
96 |
|
|
vtapo.shift := '0';
|
97 |
|
|
vtapo.asel := '0';
|
98 |
|
|
vtapo.dsel := '0';
|
99 |
|
|
if (r.inst = IDCODE_I) or (r.inst = BYPASS) then v.tdo := r.shft(0);
|
100 |
|
|
else v.tdo := tapi_tdo; end if;
|
101 |
|
|
|
102 |
|
|
case r.state is
|
103 |
|
|
when test_rst => if tms = '0' then v.state := run_idle; end if;
|
104 |
|
|
when run_idle => if tms = '1' then v.state := select_dr; end if;
|
105 |
|
|
when select_dr => if tms = '0' then v.state := capture_dr; else v.state := select_ir; end if;
|
106 |
|
|
when capture_dr => if tms = '0' then v.state := shift_dr; else v.state := exit1_dr; end if;
|
107 |
|
|
when shift_dr => if tms = '1' then v.state := exit1_dr; end if;
|
108 |
|
|
when exit1_dr => if tms = '0' then v.state := pause_dr; else v.state := update_dr; end if;
|
109 |
|
|
when pause_dr => if tms = '1' then v.state := exit2_dr; end if;
|
110 |
|
|
when exit2_dr => if tms = '0' then v.state := shift_dr; else v.state := update_dr; end if;
|
111 |
|
|
when update_dr => if tms = '0' then v.state := run_idle; else v.state := select_dr; end if;
|
112 |
|
|
when select_ir => if tms = '0' then v.state := capture_ir; else v.state := test_rst; end if;
|
113 |
|
|
when capture_ir => if tms = '0' then v.state := shift_ir; else v.state := exit1_ir; end if;
|
114 |
|
|
when shift_ir => if tms = '1' then v.state := exit1_ir; end if;
|
115 |
|
|
when exit1_ir => if tms = '0' then v.state := pause_ir; else v.state := update_ir; end if;
|
116 |
|
|
when pause_ir => if tms = '1' then v.state := exit2_ir; end if;
|
117 |
|
|
when exit2_ir => if tms = '0' then v.state := shift_ir; else v.state := update_ir; end if;
|
118 |
|
|
when update_ir => if tms = '0' then v.state := run_idle; else v.state := select_dr; end if;
|
119 |
|
|
end case;
|
120 |
|
|
|
121 |
|
|
case r.state is
|
122 |
|
|
when test_rst =>
|
123 |
|
|
vtapo.reset := '1'; v.inst := IDCODE_I;
|
124 |
|
|
when capture_dr =>
|
125 |
|
|
vtapo.capt := '1';
|
126 |
|
|
if r.inst = BYPASS then v.shft(0) := '0'; end if;
|
127 |
|
|
if r.inst = IDCODE_I then v.shft := id; end if;
|
128 |
|
|
when shift_dr =>
|
129 |
|
|
vtapo.shift := '1';
|
130 |
|
|
if r.inst = BYPASS then v.shft(0) := tdi; end if;
|
131 |
|
|
if r.inst = IDCODE_I then v.shft := tdi & r.shft(31 downto 1); end if;
|
132 |
|
|
when update_dr =>
|
133 |
|
|
vtapo.upd := '1';
|
134 |
|
|
v.sel_user1 := '0';
|
135 |
|
|
v.sel_user2 := '0';
|
136 |
|
|
when capture_ir =>
|
137 |
|
|
v.shft(irlen-1 downto 2) := r.inst(irlen-1 downto 2);
|
138 |
|
|
v.shft(1 downto 0) := "01";
|
139 |
|
|
v.sel_user1 := '0';
|
140 |
|
|
v.sel_user2 := '0';
|
141 |
|
|
when shift_ir =>
|
142 |
|
|
v.shft(irlen-1 downto 0) := tdi & r.shft(irlen-1 downto 1);
|
143 |
|
|
when update_ir =>
|
144 |
|
|
v.inst := r.shft(irlen-1 downto 0);
|
145 |
|
|
if r.shft(irlen-1 downto 0) = conv_std_logic_vector(ainst, irlen) then
|
146 |
|
|
v.sel_user1 := '1';
|
147 |
|
|
v.sel_user2 := '0';
|
148 |
|
|
elsif r.shft(irlen-1 downto 0) = conv_std_logic_vector(dinst, irlen) then
|
149 |
|
|
v.sel_user1 := '0';
|
150 |
|
|
v.sel_user2 := '1';
|
151 |
|
|
else
|
152 |
|
|
v.sel_user1 := '0';
|
153 |
|
|
v.sel_user2 := '0';
|
154 |
|
|
end if;
|
155 |
|
|
when others =>
|
156 |
|
|
end case;
|
157 |
|
|
|
158 |
|
|
rin <= v;
|
159 |
|
|
|
160 |
|
|
tdo <= r.tdo;
|
161 |
|
|
tapo_tck <= tck;
|
162 |
|
|
--if (r.sel_user1 or r.sel_user2)='1' then tapo_tck <= tck;
|
163 |
|
|
--else tapo_tck <= '1'; end if;
|
164 |
|
|
tapo_tdi <= tdi;
|
165 |
|
|
tapo_inst <= vtapo.inst;
|
166 |
|
|
tapo_rst <= vtapo.reset;
|
167 |
|
|
tapo_capt <= vtapo.capt;
|
168 |
|
|
tapo_shft <= vtapo.shift;
|
169 |
|
|
tapo_upd <= vtapo.upd;
|
170 |
|
|
tapo_xsel1 <= r.sel_user1;
|
171 |
|
|
tapo_xsel2 <= r.sel_user2;
|
172 |
|
|
end process;
|
173 |
|
|
|
174 |
|
|
posreg : process(tck, rst) begin
|
175 |
|
|
if rising_edge(tck) then
|
176 |
|
|
r.state <= rin.state;
|
177 |
|
|
r.shft <= rin.shft;
|
178 |
|
|
end if;
|
179 |
|
|
if rst = '0' then
|
180 |
|
|
r.state <= test_rst;
|
181 |
|
|
r.shft <= id;
|
182 |
|
|
end if;
|
183 |
|
|
end process;
|
184 |
|
|
|
185 |
|
|
negreg : process(tck, rst) begin
|
186 |
|
|
if falling_edge(tck) then
|
187 |
|
|
r.inst <= rin.inst;
|
188 |
|
|
r.tdo <= rin.tdo;
|
189 |
|
|
r.sel_user1 <= rin.sel_user1;
|
190 |
|
|
r.sel_user2 <= rin.sel_user2;
|
191 |
|
|
end if;
|
192 |
|
|
if rst = '0' then
|
193 |
|
|
r.inst <= IDCODE_I;
|
194 |
|
|
r.sel_user1 <= '0';
|
195 |
|
|
r.sel_user2 <= '0';
|
196 |
|
|
end if;
|
197 |
|
|
end process;
|
198 |
|
|
|
199 |
|
|
|
200 |
|
|
end;
|