../src/lowrisc_ip_rv_dm_0.1/rtl/rv_dm.sv Cov: 99.6%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4:
5: // Top-level debug module (DM)
6: //
7: // This module implements the RISC-V debug specification version 0.13,
8: //
9: // This toplevel wraps the PULP debug module available from
10: // https://github.com/pulp-platform/riscv-dbg to match the needs of
11: // the TL-UL-based lowRISC chip design.
12:
13: `include "prim_assert.sv"
14:
15: module rv_dm #(
16: parameter int NrHarts = 1,
17: parameter logic [31:0] IdcodeValue = 32'h 0000_0001
18: ) (
19: input logic clk_i, // clock
20: input logic rst_ni, // asynchronous reset active low, connect PoR
21: // here, not the system reset
22: input logic testmode_i,
23: output logic ndmreset_o, // non-debug module reset
24: output logic dmactive_o, // debug module is active
25: output logic [NrHarts-1:0] debug_req_o, // async debug request
26: input logic [NrHarts-1:0] unavailable_i, // communicate whether the hart is unavailable
27: // (e.g.: power down)
28:
29: // bus device with debug memory, for an execution based technique
30: input tlul_pkg::tl_h2d_t tl_d_i,
31: output tlul_pkg::tl_d2h_t tl_d_o,
32:
33: // bus host, for system bus accesses
34: output tlul_pkg::tl_h2d_t tl_h_o,
35: input tlul_pkg::tl_d2h_t tl_h_i,
36:
37: input logic tck_i, // JTAG test clock pad
38: input logic tms_i, // JTAG test mode select pad
39: input logic trst_ni, // JTAG test reset pad
40: input logic td_i, // JTAG test data input pad
41: output logic td_o, // JTAG test data output pad
42: output logic tdo_oe_o // Data out output enable
43: );
44:
45: `ASSERT_INIT(paramCheckNrHarts, NrHarts > 0)
46:
47: // Currently only 32 bit busses are supported by our TL-UL IP
48: localparam int BusWidth = 32;
49: // all harts have contiguous IDs
50: localparam logic [NrHarts-1:0] SelectableHarts = {NrHarts{1'b1}};
51:
52: // Debug CSRs
53: dm::hartinfo_t [NrHarts-1:0] hartinfo;
54: logic [NrHarts-1:0] halted;
55: // logic [NrHarts-1:0] running;
56: logic [NrHarts-1:0] resumeack;
57: logic [NrHarts-1:0] haltreq;
58: logic [NrHarts-1:0] resumereq;
59: logic clear_resumeack;
60: logic cmd_valid;
61: dm::command_t cmd;
62:
63: logic cmderror_valid;
64: dm::cmderr_e cmderror;
65: logic cmdbusy;
66: logic [dm::ProgBufSize-1:0][31:0] progbuf;
67: logic [dm::DataCount-1:0][31:0] data_csrs_mem;
68: logic [dm::DataCount-1:0][31:0] data_mem_csrs;
69: logic data_valid;
70: logic [19:0] hartsel;
71: // System Bus Access Module
72: logic [BusWidth-1:0] sbaddress_csrs_sba;
73: logic [BusWidth-1:0] sbaddress_sba_csrs;
74: logic sbaddress_write_valid;
75: logic sbreadonaddr;
76: logic sbautoincrement;
77: logic [2:0] sbaccess;
78: logic sbreadondata;
79: logic [BusWidth-1:0] sbdata_write;
80: logic sbdata_read_valid;
81: logic sbdata_write_valid;
82: logic [BusWidth-1:0] sbdata_read;
83: logic sbdata_valid;
84: logic sbbusy;
85: logic sberror_valid;
86: logic [2:0] sberror;
87:
88: dm::dmi_req_t dmi_req;
89: dm::dmi_resp_t dmi_rsp;
90: logic dmi_req_valid, dmi_req_ready;
91: logic dmi_rsp_valid, dmi_rsp_ready;
92: logic dmi_rst_n;
93:
94: // static debug hartinfo
95: localparam dm::hartinfo_t DebugHartInfo = '{
96: zero1: '0,
97: nscratch: 2, // Debug module needs at least two scratch regs
98: zero0: 0,
99: dataaccess: 1'b1, // data registers are memory mapped in the debugger
100: datasize: dm::DataCount,
101: dataaddr: dm::DataAddr
102: };
103: for (genvar i = 0; i < NrHarts; i++) begin : gen_dm_hart_ctrl
104: assign hartinfo[i] = DebugHartInfo;
105: end
106:
107: dm_csrs #(
108: .NrHarts(NrHarts),
109: .BusWidth(BusWidth),
110: .SelectableHarts(SelectableHarts)
111: ) i_dm_csrs (
112: .clk_i ( clk_i ),
113: .rst_ni ( rst_ni ),
114: .testmode_i ( testmode_i ),
115: .dmi_rst_ni ( dmi_rst_n ),
116: .dmi_req_valid_i ( dmi_req_valid ),
117: .dmi_req_ready_o ( dmi_req_ready ),
118: .dmi_req_i ( dmi_req ),
119: .dmi_resp_valid_o ( dmi_rsp_valid ),
120: .dmi_resp_ready_i ( dmi_rsp_ready ),
121: .dmi_resp_o ( dmi_rsp ),
122: .ndmreset_o ( ndmreset_o ),
123: .dmactive_o ( dmactive_o ),
124: .hartsel_o ( hartsel ),
125: .hartinfo_i ( hartinfo ),
126: .halted_i ( halted ),
127: .unavailable_i,
128: .resumeack_i ( resumeack ),
129: .haltreq_o ( haltreq ),
130: .resumereq_o ( resumereq ),
131: .clear_resumeack_o ( clear_resumeack ),
132: .cmd_valid_o ( cmd_valid ),
133: .cmd_o ( cmd ),
134: .cmderror_valid_i ( cmderror_valid ),
135: .cmderror_i ( cmderror ),
136: .cmdbusy_i ( cmdbusy ),
137: .progbuf_o ( progbuf ),
138: .data_i ( data_mem_csrs ),
139: .data_valid_i ( data_valid ),
140: .data_o ( data_csrs_mem ),
141: .sbaddress_o ( sbaddress_csrs_sba ),
142: .sbaddress_i ( sbaddress_sba_csrs ),
143: .sbaddress_write_valid_o ( sbaddress_write_valid ),
144: .sbreadonaddr_o ( sbreadonaddr ),
145: .sbautoincrement_o ( sbautoincrement ),
146: .sbaccess_o ( sbaccess ),
147: .sbreadondata_o ( sbreadondata ),
148: .sbdata_o ( sbdata_write ),
149: .sbdata_read_valid_o ( sbdata_read_valid ),
150: .sbdata_write_valid_o ( sbdata_write_valid ),
151: .sbdata_i ( sbdata_read ),
152: .sbdata_valid_i ( sbdata_valid ),
153: .sbbusy_i ( sbbusy ),
154: .sberror_valid_i ( sberror_valid ),
155: .sberror_i ( sberror )
156: );
157:
158: logic master_req;
159: logic [BusWidth-1:0] master_add;
160: logic master_we;
161: logic [BusWidth-1:0] master_wdata;
162: logic [BusWidth/8-1:0] master_be;
163: logic master_gnt;
164: logic master_r_valid;
165: logic [BusWidth-1:0] master_r_rdata;
166: logic master_r_err;
167:
168: dm_sba #(
169: .BusWidth(BusWidth)
170: ) i_dm_sba (
171: .clk_i ( clk_i ),
172: .rst_ni ( rst_ni ),
173: .master_req_o ( master_req ),
174: .master_add_o ( master_add ),
175: .master_we_o ( master_we ),
176: .master_wdata_o ( master_wdata ),
177: .master_be_o ( master_be ),
178: .master_gnt_i ( master_gnt ),
179: .master_r_valid_i ( master_r_valid ),
180: .master_r_rdata_i ( master_r_rdata ),
181: .dmactive_i ( dmactive_o ),
182: .sbaddress_i ( sbaddress_csrs_sba ),
183: .sbaddress_o ( sbaddress_sba_csrs ),
184: .sbaddress_write_valid_i ( sbaddress_write_valid ),
185: .sbreadonaddr_i ( sbreadonaddr ),
186: .sbautoincrement_i ( sbautoincrement ),
187: .sbaccess_i ( sbaccess ),
188: .sbreadondata_i ( sbreadondata ),
189: .sbdata_i ( sbdata_write ),
190: .sbdata_read_valid_i ( sbdata_read_valid ),
191: .sbdata_write_valid_i ( sbdata_write_valid ),
192: .sbdata_o ( sbdata_read ),
193: .sbdata_valid_o ( sbdata_valid ),
194: .sbbusy_o ( sbbusy ),
195: .sberror_valid_o ( sberror_valid ),
196: .sberror_o ( sberror )
197: );
198:
199: tlul_adapter_host #(
200: .MAX_REQS(1)
201: ) tl_adapter_host_sba (
202: .clk_i,
203: .rst_ni,
204: .req_i (master_req),
205: .gnt_o (master_gnt),
206: .addr_i (master_add),
207: .we_i (master_we),
208: .wdata_i (master_wdata),
209: .be_i (master_be),
210: .valid_o (master_r_valid),
211: .rdata_o (master_r_rdata),
212: .err_o (master_r_err),
213: .tl_o (tl_h_o),
214: .tl_i (tl_h_i)
215: );
216:
217: // DBG doesn't handle error responses so raise assertion if we see one
218: `ASSERT(dbgNoErrorResponse, master_r_valid |-> !master_r_err)
219:
220: localparam int unsigned AddressWidthWords = BusWidth - $clog2(BusWidth/8);
221:
222: logic req;
223: logic we;
224: logic [BusWidth/8-1:0] be;
225: logic [BusWidth-1:0] wdata;
226: logic [BusWidth-1:0] rdata;
227: logic rvalid;
228:
229: logic [BusWidth-1:0] addr_b;
230: logic [AddressWidthWords-1:0] addr_w;
231:
232: // TODO: The tlul_adapter_sram give us a bitwise write mask currently,
233: // but dm_mem only supports byte write masks. Disable sub-word access in the
234: // adapter for now until we figure out a good strategy to deal with this.
235: assign be = {BusWidth/8{1'b1}};
236:
237: assign addr_b = {addr_w, {$clog2(BusWidth/8){1'b0}}};
238:
239: dm_mem #(
240: .NrHarts(NrHarts),
241: .BusWidth(BusWidth),
242: .SelectableHarts(SelectableHarts)
243: ) i_dm_mem (
244: .clk_i ( clk_i ),
245: .rst_ni ( rst_ni ),
246: .debug_req_o ( debug_req_o ),
247: .hartsel_i ( hartsel ),
248: .haltreq_i ( haltreq ),
249: .resumereq_i ( resumereq ),
250: .clear_resumeack_i ( clear_resumeack ),
251: .halted_o ( halted ),
252: .resuming_o ( resumeack ),
253: .cmd_valid_i ( cmd_valid ),
254: .cmd_i ( cmd ),
255: .cmderror_valid_o ( cmderror_valid ),
256: .cmderror_o ( cmderror ),
257: .cmdbusy_o ( cmdbusy ),
258: .progbuf_i ( progbuf ),
259: .data_i ( data_csrs_mem ),
260: .data_o ( data_mem_csrs ),
261: .data_valid_o ( data_valid ),
262: .req_i ( req ),
263: .we_i ( we ),
264: .addr_i ( addr_b ),
265: .wdata_i ( wdata ),
266: .be_i ( be ),
267: .rdata_o ( rdata )
268: );
269:
270: // Bound-in DPI module replaces the TAP
271: `ifndef DMIDirectTAP
272: // JTAG TAP
273: dmi_jtag #(
274: .IdcodeValue (IdcodeValue)
275: ) dap (
276: .clk_i (clk_i),
277: .rst_ni (rst_ni),
278: .testmode_i (testmode_i),
279:
280: .dmi_rst_no (dmi_rst_n),
281: .dmi_req_o (dmi_req),
282: .dmi_req_valid_o (dmi_req_valid),
283: .dmi_req_ready_i (dmi_req_ready),
284:
285: .dmi_resp_i (dmi_rsp ),
286: .dmi_resp_ready_o (dmi_rsp_ready),
287: .dmi_resp_valid_i (dmi_rsp_valid),
288:
289: //JTAG
290: .tck_i,
291: .tms_i,
292: .trst_ni,
293: .td_i,
294: .td_o,
295: .tdo_oe_o
296: );
297: `endif
298:
299: tlul_adapter_sram #(
300: .SramAw(AddressWidthWords),
301: .SramDw(BusWidth),
302: .Outstanding(1),
303: .ByteAccess(0)
304: ) tl_adapter_device_mem (
305: .clk_i,
306: .rst_ni,
307:
308: .req_o (req),
309: .gnt_i (1'b1),
310: .we_o (we),
311: .addr_o (addr_w),
312: .wdata_o (wdata),
313: .wmask_o (),
314: .rdata_i (rdata),
315: .rvalid_i (rvalid),
316: .rerror_i (2'b00),
317:
318: .tl_o (tl_d_o),
319: .tl_i (tl_d_i)
320: );
321:
322: always_ff @(posedge clk_i or negedge rst_ni) begin
323: if (!rst_ni) begin
324: rvalid <= '0;
325: end else begin
326: rvalid <= req & ~we;
327: end
328: end
329:
330: endmodule
331: