../src/pulp-platform_riscv-dbg_0.1_0/pulp_riscv_dbg/src/dmi_jtag.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: axi_riscv_debug_module.sv
12: * Author: Florian Zaruba
13: * Date: 19.7.2018
14: *
15: * Description: JTAG DMI (debug module interface)
16: *
17: */
18:
19: module dmi_jtag #(
20: parameter logic [31:0] IdcodeValue = 32'h00000001
21: ) (
22: input logic clk_i, // DMI Clock
23: input logic rst_ni, // Asynchronous reset active low
24: input logic testmode_i,
25:
26: output logic dmi_rst_no, // hard reset
27: output dm::dmi_req_t dmi_req_o,
28: output logic dmi_req_valid_o,
29: input logic dmi_req_ready_i,
30:
31: input dm::dmi_resp_t dmi_resp_i,
32: output logic dmi_resp_ready_o,
33: input logic dmi_resp_valid_i,
34:
35: input logic tck_i, // JTAG test clock pad
36: input logic tms_i, // JTAG test mode select pad
37: input logic trst_ni, // JTAG test reset pad
38: input logic td_i, // JTAG test data input pad
39: output logic td_o, // JTAG test data output pad
40: output logic tdo_oe_o // Data out output enable
41: );
42: assign dmi_rst_no = rst_ni;
43:
44: logic test_logic_reset;
45: logic shift_dr;
46: logic update_dr;
47: logic capture_dr;
48: logic dmi_access;
49: logic dtmcs_select;
50: logic dmi_reset;
51: logic dmi_tdi;
52: logic dmi_tdo;
53:
54: dm::dmi_req_t dmi_req;
55: logic dmi_req_ready;
56: logic dmi_req_valid;
57:
58: dm::dmi_resp_t dmi_resp;
59: logic dmi_resp_valid;
60: logic dmi_resp_ready;
61:
62: typedef struct packed {
63: logic [6:0] address;
64: logic [31:0] data;
65: logic [1:0] op;
66: } dmi_t;
67:
68: typedef enum logic [1:0] {
69: DMINoError = 2'h0, DMIReservedError = 2'h1,
70: DMIOPFailed = 2'h2, DMIBusy = 2'h3
71: } dmi_error_e;
72:
73: typedef enum logic [2:0] { Idle, Read, WaitReadValid, Write, WaitWriteValid } state_e;
74: state_e state_d, state_q;
75:
76: logic [$bits(dmi_t)-1:0] dr_d, dr_q;
77: logic [6:0] address_d, address_q;
78: logic [31:0] data_d, data_q;
79:
80: dmi_t dmi;
81: assign dmi = dmi_t'(dr_q);
82: assign dmi_req.addr = address_q;
83: assign dmi_req.data = data_q;
84: assign dmi_req.op = (state_q == Write) ? dm::DTM_WRITE : dm::DTM_READ;
85: // we'will always be ready to accept the data we requested
86: assign dmi_resp_ready = 1'b1;
87:
88: logic error_dmi_busy;
89: dmi_error_e error_d, error_q;
90:
91: always_comb begin : p_fsm
92: error_dmi_busy = 1'b0;
93: // default assignments
94: state_d = state_q;
95: address_d = address_q;
96: data_d = data_q;
97: error_d = error_q;
98:
99: dmi_req_valid = 1'b0;
100:
101: unique case (state_q)
102: Idle: begin
103: // make sure that no error is sticky
104: if (dmi_access && update_dr && (error_q == DMINoError)) begin
105: // save address and value
106: address_d = dmi.address;
107: data_d = dmi.data;
108: if (dm::dtm_op_e'(dmi.op) == dm::DTM_READ) begin
109: state_d = Read;
110: end else if (dm::dtm_op_e'(dmi.op) == dm::DTM_WRITE) begin
111: state_d = Write;
112: end
113: // else this is a nop and we can stay here
114: end
115: end
116:
117: Read: begin
118: dmi_req_valid = 1'b1;
119: if (dmi_req_ready) begin
120: state_d = WaitReadValid;
121: end
122: end
123:
124: WaitReadValid: begin
125: // load data into register and shift out
126: if (dmi_resp_valid) begin
127: data_d = dmi_resp.data;
128: state_d = Idle;
129: end
130: end
131:
132: Write: begin
133: dmi_req_valid = 1'b1;
134: // got a valid answer go back to idle
135: if (dmi_req_ready) begin
136: state_d = Idle;
137: end
138: end
139:
140: default: begin
141: // just wait for idle here
142: if (dmi_resp_valid) begin
143: state_d = Idle;
144: end
145: end
146: endcase
147:
148: // update_dr means we got another request but we didn't finish
149: // the one in progress, this state is sticky
150: if (update_dr && state_q != Idle) begin
151: error_dmi_busy = 1'b1;
152: end
153:
154: // if capture_dr goes high while we are in the read state
155: // or in the corresponding wait state we are not giving back a valid word
156: // -> throw an error
157: if (capture_dr && state_q inside {Read, WaitReadValid}) begin
158: error_dmi_busy = 1'b1;
159: end
160:
161: if (error_dmi_busy) begin
162: error_d = DMIBusy;
163: end
164: // clear sticky error flag
165: if (dmi_reset && dtmcs_select) begin
166: error_d = DMINoError;
167: end
168: end
169:
170: // shift register
171: assign dmi_tdo = dr_q[0];
172:
173: always_comb begin : p_shift
174: dr_d = dr_q;
175:
176: if (capture_dr) begin
177: if (dmi_access) begin
178: if (error_q == DMINoError && !error_dmi_busy) begin
179: dr_d = {address_q, data_q, DMINoError};
180: // DMI was busy, report an error
181: end else if (error_q == DMIBusy || error_dmi_busy) begin
182: dr_d = {address_q, data_q, DMIBusy};
183: end
184: end
185: end
186:
187: if (shift_dr) begin
188: if (dmi_access) begin
189: dr_d = {dmi_tdi, dr_q[$bits(dr_q)-1:1]};
190: end
191: end
192:
193: if (test_logic_reset) begin
194: dr_d = '0;
195: end
196: end
197:
198: always_ff @(posedge tck_i or negedge trst_ni) begin : p_regs
199: if (!trst_ni) begin
200: dr_q <= '0;
201: state_q <= Idle;
202: address_q <= '0;
203: data_q <= '0;
204: error_q <= DMINoError;
205: end else begin
206: dr_q <= dr_d;
207: state_q <= state_d;
208: address_q <= address_d;
209: data_q <= data_d;
210: error_q <= error_d;
211: end
212: end
213:
214: // ---------
215: // TAP
216: // ---------
217: dmi_jtag_tap #(
218: .IrLength (5),
219: .IdcodeValue(IdcodeValue)
220: ) i_dmi_jtag_tap (
221: .tck_i,
222: .tms_i,
223: .trst_ni,
224: .td_i,
225: .td_o,
226: .tdo_oe_o,
227: .testmode_i,
228: .test_logic_reset_o ( test_logic_reset ),
229: .shift_dr_o ( shift_dr ),
230: .update_dr_o ( update_dr ),
231: .capture_dr_o ( capture_dr ),
232: .dmi_access_o ( dmi_access ),
233: .dtmcs_select_o ( dtmcs_select ),
234: .dmi_reset_o ( dmi_reset ),
235: .dmi_error_i ( error_q ),
236: .dmi_tdi_o ( dmi_tdi ),
237: .dmi_tdo_i ( dmi_tdo )
238: );
239:
240: // ---------
241: // CDC
242: // ---------
243: dmi_cdc i_dmi_cdc (
244: // JTAG side (master side)
245: .tck_i,
246: .trst_ni,
247: .jtag_dmi_req_i ( dmi_req ),
248: .jtag_dmi_ready_o ( dmi_req_ready ),
249: .jtag_dmi_valid_i ( dmi_req_valid ),
250: .jtag_dmi_resp_o ( dmi_resp ),
251: .jtag_dmi_valid_o ( dmi_resp_valid ),
252: .jtag_dmi_ready_i ( dmi_resp_ready ),
253: // core side
254: .clk_i,
255: .rst_ni,
256: .core_dmi_req_o ( dmi_req_o ),
257: .core_dmi_valid_o ( dmi_req_valid_o ),
258: .core_dmi_ready_i ( dmi_req_ready_i ),
259: .core_dmi_resp_i ( dmi_resp_i ),
260: .core_dmi_ready_o ( dmi_resp_ready_o ),
261: .core_dmi_valid_i ( dmi_resp_valid_i )
262: );
263:
264: endmodule : dmi_jtag
265: