hw/vendor/pulp_riscv_dbg/src/dmi_jtag_tap.sv Cov: 100%
1: /* Copyright 2018 ETH Zurich and University of Bologna.
2: * Copyright and related rights are licensed under the Solderpad Hardware
3: * License, Version 0.51 (the “License”); you may not use this file except in
4: * compliance with the License. You may obtain a copy of the License at
5: * http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6: * or agreed to in writing, software, hardware and materials distributed under
7: * this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
8: * CONDITIONS OF ANY KIND, either express or implied. See the License for the
9: * specific language governing permissions and limitations under the License.
10: *
11: * File: dmi_jtag_tap.sv
12: * Author: Florian Zaruba
13: * Date: 19.7.2018
14: *
15: * Description: JTAG TAP for DMI (according to debug spec 0.13)
16: *
17: */
18:
19: module dmi_jtag_tap #(
20: parameter int unsigned IrLength = 5,
21: // JTAG IDCODE Value
22: parameter logic [31:0] IdcodeValue = 32'h00000001
23: // xxxx version
24: // xxxxxxxxxxxxxxxx part number
25: // xxxxxxxxxxx manufacturer id
26: // 1 required by standard
27: ) (
28: input logic tck_i, // JTAG test clock pad
29: input logic tms_i, // JTAG test mode select pad
30: input logic trst_ni, // JTAG test reset pad
31: input logic td_i, // JTAG test data input pad
32: output logic td_o, // JTAG test data output pad
33: output logic tdo_oe_o, // Data out output enable
34: input logic testmode_i,
35: output logic test_logic_reset_o,
36: output logic shift_dr_o,
37: output logic update_dr_o,
38: output logic capture_dr_o,
39:
40: // we want to access DMI register
41: output logic dmi_access_o,
42: // JTAG is interested in writing the DTM CSR register
43: output logic dtmcs_select_o,
44: // clear error state
45: output logic dmi_reset_o,
46: input logic [1:0] dmi_error_i,
47: // test data to submodule
48: output logic dmi_tdi_o,
49: // test data in from submodule
50: input logic dmi_tdo_i
51: );
52:
53: // to submodule
54: assign dmi_tdi_o = td_i;
55:
56: typedef enum logic [3:0] {
57: TestLogicReset, RunTestIdle, SelectDrScan,
58: CaptureDr, ShiftDr, Exit1Dr, PauseDr, Exit2Dr,
59: UpdateDr, SelectIrScan, CaptureIr, ShiftIr,
60: Exit1Ir, PauseIr, Exit2Ir, UpdateIr
61: } tap_state_e;
62:
63: tap_state_e tap_state_q, tap_state_d;
64:
65: typedef enum logic [IrLength-1:0] {
66: BYPASS0 = 'h0,
67: IDCODE = 'h1,
68: DTMCSR = 'h10,
69: DMIACCESS = 'h11,
70: BYPASS1 = 'h1f
71: } ir_reg_e;
72:
73: typedef struct packed {
74: logic [31:18] zero1;
75: logic dmihardreset;
76: logic dmireset;
77: logic zero0;
78: logic [14:12] idle;
79: logic [11:10] dmistat;
80: logic [9:4] abits;
81: logic [3:0] version;
82: } dtmcs_t;
83:
84: // ----------------
85: // IR logic
86: // ----------------
87:
88: // shift register
89: logic [IrLength-1:0] jtag_ir_shift_d, jtag_ir_shift_q;
90: // IR register -> this gets captured from shift register upon update_ir
91: ir_reg_e jtag_ir_d, jtag_ir_q;
92: logic capture_ir, shift_ir, update_ir; // pause_ir
93:
94: always_comb begin : p_jtag
95: jtag_ir_shift_d = jtag_ir_shift_q;
96: jtag_ir_d = jtag_ir_q;
97:
98: // IR shift register
99: if (shift_ir) begin
100: jtag_ir_shift_d = {td_i, jtag_ir_shift_q[IrLength-1:1]};
101: end
102:
103: // capture IR register
104: if (capture_ir) begin
105: jtag_ir_shift_d = IrLength'(4'b0101);
106: end
107:
108: // update IR register
109: if (update_ir) begin
110: jtag_ir_d = ir_reg_e'(jtag_ir_shift_q);
111: end
112:
113: // synchronous test-logic reset
114: if (test_logic_reset_o) begin
115: jtag_ir_shift_d = '0;
116: jtag_ir_d = IDCODE;
117: end
118: end
119:
120: always_ff @(posedge tck_i, negedge trst_ni) begin : p_jtag_ir_reg
121: if (!trst_ni) begin
122: jtag_ir_shift_q <= '0;
123: jtag_ir_q <= IDCODE;
124: end else begin
125: jtag_ir_shift_q <= jtag_ir_shift_d;
126: jtag_ir_q <= jtag_ir_d;
127: end
128: end
129:
130: // ----------------
131: // TAP DR Regs
132: // ----------------
133: // - Bypass
134: // - IDCODE
135: // - DTM CS
136: logic [31:0] idcode_d, idcode_q;
137: logic idcode_select;
138: logic bypass_select;
139: dtmcs_t dtmcs_d, dtmcs_q;
140: logic bypass_d, bypass_q; // this is a 1-bit register
141:
142: assign dmi_reset_o = dtmcs_q.dmireset;
143:
144: always_comb begin
145: idcode_d = idcode_q;
146: bypass_d = bypass_q;
147: dtmcs_d = dtmcs_q;
148:
149: if (capture_dr_o) begin
150: if (idcode_select) idcode_d = IdcodeValue;
151: if (bypass_select) bypass_d = 1'b0;
152: if (dtmcs_select_o) begin
153: dtmcs_d = '{
154: zero1 : '0,
155: dmihardreset : 1'b0,
156: dmireset : 1'b0,
157: zero0 : '0,
158: idle : 3'd1, // 1: Enter Run-Test/Idle and leave it immediately
159: dmistat : dmi_error_i, // 0: No error, 1: Op failed, 2: too fast
160: abits : 6'd7, // The size of address in dmi
161: version : 4'd1 // Version described in spec version 0.13 (and later?)
162: };
163: end
164: end
165:
166: if (shift_dr_o) begin
167: if (idcode_select) idcode_d = {td_i, 31'(idcode_q >> 1)};
168: if (bypass_select) bypass_d = td_i;
169: if (dtmcs_select_o) dtmcs_d = {td_i, 31'(dtmcs_q >> 1)};
170: end
171:
172: if (test_logic_reset_o) begin
173: idcode_d = IdcodeValue;
174: bypass_d = 1'b0;
175: end
176: end
177:
178: // ----------------
179: // Data reg select
180: // ----------------
181: always_comb begin : p_data_reg_sel
182: dmi_access_o = 1'b0;
183: dtmcs_select_o = 1'b0;
184: idcode_select = 1'b0;
185: bypass_select = 1'b0;
186: unique case (jtag_ir_q)
187: BYPASS0: bypass_select = 1'b1;
188: IDCODE: idcode_select = 1'b1;
189: DTMCSR: dtmcs_select_o = 1'b1;
190: DMIACCESS: dmi_access_o = 1'b1;
191: BYPASS1: bypass_select = 1'b1;
192: default: bypass_select = 1'b1;
193: endcase
194: end
195:
196: // ----------------
197: // Output select
198: // ----------------
199: logic tdo_mux;
200:
201: always_comb begin : p_out_sel
202: // we are shifting out the IR register
203: if (shift_ir) begin
204: tdo_mux = jtag_ir_shift_q[0];
205: // here we are shifting the DR register
206: end else begin
207: unique case (jtag_ir_q)
208: IDCODE: tdo_mux = idcode_q[0]; // Reading ID code
209: DTMCSR: tdo_mux = dtmcs_q.version[0];
210: DMIACCESS: tdo_mux = dmi_tdo_i; // Read from DMI TDO
211: default: tdo_mux = bypass_q; // BYPASS instruction
212: endcase
213: end
214: end
215:
216: // ----------------
217: // DFT
218: // ----------------
219: logic tck_n;
220:
221: prim_clock_inverter #(
222: .HasScanMode(1'b1)
223: ) i_tck_inv (
224: .clk_i ( tck_i ),
225: .clk_no ( tck_n ),
226: .scanmode_i ( testmode_i )
227: );
228:
229: // TDO changes state at negative edge of TCK
230: always_ff @(posedge tck_n, negedge trst_ni) begin : p_tdo_regs
231: if (!trst_ni) begin
232: td_o <= 1'b0;
233: tdo_oe_o <= 1'b0;
234: end else begin
235: td_o <= tdo_mux;
236: tdo_oe_o <= (shift_ir | shift_dr_o);
237: end
238: end
239: // ----------------
240: // TAP FSM
241: // ----------------
242: // Determination of next state; purely combinatorial
243: always_comb begin : p_tap_fsm
244:
245: test_logic_reset_o = 1'b0;
246:
247: capture_dr_o = 1'b0;
248: shift_dr_o = 1'b0;
249: update_dr_o = 1'b0;
250:
251: capture_ir = 1'b0;
252: shift_ir = 1'b0;
253: // pause_ir = 1'b0; unused
254: update_ir = 1'b0;
255:
256: unique case (tap_state_q)
257: TestLogicReset: begin
258: tap_state_d = (tms_i) ? TestLogicReset : RunTestIdle;
259: test_logic_reset_o = 1'b1;
260: end
261: RunTestIdle: begin
262: tap_state_d = (tms_i) ? SelectDrScan : RunTestIdle;
263: end
264: // DR Path
265: SelectDrScan: begin
266: tap_state_d = (tms_i) ? SelectIrScan : CaptureDr;
267: end
268: CaptureDr: begin
269: capture_dr_o = 1'b1;
270: tap_state_d = (tms_i) ? Exit1Dr : ShiftDr;
271: end
272: ShiftDr: begin
273: shift_dr_o = 1'b1;
274: tap_state_d = (tms_i) ? Exit1Dr : ShiftDr;
275: end
276: Exit1Dr: begin
277: tap_state_d = (tms_i) ? UpdateDr : PauseDr;
278: end
279: PauseDr: begin
280: tap_state_d = (tms_i) ? Exit2Dr : PauseDr;
281: end
282: Exit2Dr: begin
283: tap_state_d = (tms_i) ? UpdateDr : ShiftDr;
284: end
285: UpdateDr: begin
286: update_dr_o = 1'b1;
287: tap_state_d = (tms_i) ? SelectDrScan : RunTestIdle;
288: end
289: // IR Path
290: SelectIrScan: begin
291: tap_state_d = (tms_i) ? TestLogicReset : CaptureIr;
292: end
293: // In this controller state, the shift register bank in the
294: // Instruction Register parallel loads a pattern of fixed values on
295: // the rising edge of TCK. The last two significant bits must always
296: // be "01".
297: CaptureIr: begin
298: capture_ir = 1'b1;
299: tap_state_d = (tms_i) ? Exit1Ir : ShiftIr;
300: end
301: // In this controller state, the instruction register gets connected
302: // between TDI and TDO, and the captured pattern gets shifted on
303: // each rising edge of TCK. The instruction available on the TDI
304: // pin is also shifted in to the instruction register.
305: ShiftIr: begin
306: shift_ir = 1'b1;
307: tap_state_d = (tms_i) ? Exit1Ir : ShiftIr;
308: end
309: Exit1Ir: begin
310: tap_state_d = (tms_i) ? UpdateIr : PauseIr;
311: end
312: PauseIr: begin
313: // pause_ir = 1'b1; // unused
314: tap_state_d = (tms_i) ? Exit2Ir : PauseIr;
315: end
316: Exit2Ir: begin
317: tap_state_d = (tms_i) ? UpdateIr : ShiftIr;
318: end
319: // In this controller state, the instruction in the instruction
320: // shift register is latched to the latch bank of the Instruction
321: // Register on every falling edge of TCK. This instruction becomes
322: // the current instruction once it is latched.
323: UpdateIr: begin
324: update_ir = 1'b1;
325: tap_state_d = (tms_i) ? SelectDrScan : RunTestIdle;
326: end
327: default: ; // can't actually happen since case is full
328: endcase
329: end
330:
331: always_ff @(posedge tck_i or negedge trst_ni) begin : p_regs
332: if (!trst_ni) begin
333: tap_state_q <= RunTestIdle;
334: idcode_q <= IdcodeValue;
335: bypass_q <= 1'b0;
336: dtmcs_q <= '0;
337: end else begin
338: tap_state_q <= tap_state_d;
339: idcode_q <= idcode_d;
340: bypass_q <= bypass_d;
341: dtmcs_q <= dtmcs_d;
342: end
343: end
344:
345: endmodule : dmi_jtag_tap
346: