hw/vendor/pulp_riscv_dbg/src/dm_csrs.sv Cov: 98%
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: dm_csrs.sv
12: * Author: Florian Zaruba
13: * Date: 30.6.2018
14: *
15: * Description: Debug CSRs. Communication over Debug Transport Module (DTM)
16: */
17:
18: module dm_csrs #(
19: parameter int unsigned NrHarts = 1,
20: parameter int unsigned BusWidth = 32,
21: parameter logic [NrHarts-1:0] SelectableHarts = {NrHarts{1'b1}}
22: ) (
23: input logic clk_i, // Clock
24: input logic rst_ni, // Asynchronous reset active low
25: input logic testmode_i,
26: input logic dmi_rst_ni, // Debug Module Intf reset active-low
27: input logic dmi_req_valid_i,
28: output logic dmi_req_ready_o,
29: input dm::dmi_req_t dmi_req_i,
30: // every request needs a response one cycle later
31: output logic dmi_resp_valid_o,
32: input logic dmi_resp_ready_i,
33: output dm::dmi_resp_t dmi_resp_o,
34: // global ctrl
35: output logic ndmreset_o, // non-debug module reset active-high
36: output logic dmactive_o, // 1 -> debug-module is active,
37: // 0 -> synchronous re-set
38: // hart status
39: input dm::hartinfo_t [NrHarts-1:0] hartinfo_i, // static hartinfo
40: input logic [NrHarts-1:0] halted_i, // hart is halted
41: input logic [NrHarts-1:0] unavailable_i, // e.g.: powered down
42: input logic [NrHarts-1:0] resumeack_i, // hart acknowledged resume request
43: // hart control
44: output logic [19:0] hartsel_o, // hartselect to ctrl module
45: output logic [NrHarts-1:0] haltreq_o, // request to halt a hart
46: output logic [NrHarts-1:0] resumereq_o, // request hart to resume
47: output logic clear_resumeack_o,
48:
49: output logic cmd_valid_o, // debugger writing to cmd field
50: output dm::command_t cmd_o, // abstract command
51: input logic cmderror_valid_i, // an error occured
52: input dm::cmderr_e cmderror_i, // this error occured
53: input logic cmdbusy_i, // cmd is currently busy executing
54:
55: output logic [dm::ProgBufSize-1:0][31:0] progbuf_o, // to system bus
56: output logic [dm::DataCount-1:0][31:0] data_o,
57:
58: input logic [dm::DataCount-1:0][31:0] data_i,
59: input logic data_valid_i,
60: // system bus access module (SBA)
61: output logic [BusWidth-1:0] sbaddress_o,
62: input logic [BusWidth-1:0] sbaddress_i,
63: output logic sbaddress_write_valid_o,
64: // control signals in
65: output logic sbreadonaddr_o,
66: output logic sbautoincrement_o,
67: output logic [2:0] sbaccess_o,
68: // data out
69: output logic sbreadondata_o,
70: output logic [BusWidth-1:0] sbdata_o,
71: output logic sbdata_read_valid_o,
72: output logic sbdata_write_valid_o,
73: // read data in
74: input logic [BusWidth-1:0] sbdata_i,
75: input logic sbdata_valid_i,
76: // control signals
77: input logic sbbusy_i,
78: input logic sberror_valid_i, // bus error occurred
79: input logic [2:0] sberror_i // bus error occurred
80: );
81:
82: // the amount of bits we need to represent all harts
83: localparam int unsigned HartSelLen = (NrHarts == 1) ? 1 : $clog2(NrHarts);
84: localparam int unsigned NrHartsAligned = 2**HartSelLen;
85:
86: dm::dtm_op_e dtm_op;
87: assign dtm_op = dm::dtm_op_e'(dmi_req_i.op);
88:
89: logic [31:0] resp_queue_data;
90:
91: localparam dm::dm_csr_e DataEnd = dm::dm_csr_e'((dm::Data0 + {4'b0, dm::DataCount}));
92: localparam dm::dm_csr_e ProgBufEnd = dm::dm_csr_e'((dm::ProgBuf0 + {4'b0, dm::ProgBufSize}));
93:
94: logic [31:0] haltsum0, haltsum1, haltsum2, haltsum3;
95: logic [((NrHarts-1)/2**5 + 1) * 32 - 1 : 0] halted;
96: logic [(NrHarts-1)/2**5:0][31:0] halted_reshaped0;
97: logic [NrHarts/2**10:0][31:0] halted_reshaped1;
98: logic [NrHarts/2**15:0][31:0] halted_reshaped2;
99: logic [(NrHarts/2**10+1)*32-1:0] halted_flat1;
100: logic [(NrHarts/2**15+1)*32-1:0] halted_flat2;
101: logic [32-1:0] halted_flat3;
102:
103: // haltsum0
104: logic [14:0] hartsel_idx0;
105: always_comb begin : p_haltsum0
106: halted = '0;
107: haltsum0 = '0;
108: hartsel_idx0 = hartsel_o[19:5];
109: halted[NrHarts-1:0] = halted_i;
110: halted_reshaped0 = halted;
111: if (hartsel_idx0 < 15'((NrHarts-1)/2**5+1)) begin
112: haltsum0 = halted_reshaped0[hartsel_idx0];
113: end
114: end
115:
116: // haltsum1
117: logic [9:0] hartsel_idx1;
118: always_comb begin : p_reduction1
119: halted_flat1 = '0;
120: haltsum1 = '0;
121: hartsel_idx1 = hartsel_o[19:10];
122:
123: for (int unsigned k = 0; k < NrHarts/2**5+1; k++) begin
124: halted_flat1[k] = |halted_reshaped0[k];
125: end
126: halted_reshaped1 = halted_flat1;
127:
128: if (hartsel_idx1 < 10'((NrHarts/2**10+1))) begin
129: haltsum1 = halted_reshaped1[hartsel_idx1];
130: end
131: end
132:
133: // haltsum2
134: logic [4:0] hartsel_idx2;
135: always_comb begin : p_reduction2
136: halted_flat2 = '0;
137: haltsum2 = '0;
138: hartsel_idx2 = hartsel_o[19:15];
139:
140: for (int unsigned k = 0; k < NrHarts/2**10+1; k++) begin
141: halted_flat2[k] = |halted_reshaped1[k];
142: end
143: halted_reshaped2 = halted_flat2;
144:
145: if (hartsel_idx2 < 5'((NrHarts/2**15+1))) begin
146: haltsum2 = halted_reshaped2[hartsel_idx2];
147: end
148: end
149:
150: // haltsum3
151: always_comb begin : p_reduction3
152: halted_flat3 = '0;
153: for (int unsigned k = 0; k < NrHarts/2**15+1; k++) begin
154: halted_flat3[k] = |halted_reshaped2[k];
155: end
156: haltsum3 = halted_flat3;
157: end
158:
159:
160: dm::dmstatus_t dmstatus;
161: dm::dmcontrol_t dmcontrol_d, dmcontrol_q;
162: dm::abstractcs_t abstractcs;
163: dm::cmderr_e cmderr_d, cmderr_q;
164: dm::command_t command_d, command_q;
165: logic cmd_valid_d, cmd_valid_q;
166: dm::abstractauto_t abstractauto_d, abstractauto_q;
167: dm::sbcs_t sbcs_d, sbcs_q;
168: logic [63:0] sbaddr_d, sbaddr_q;
169: logic [63:0] sbdata_d, sbdata_q;
170:
171: logic [NrHarts-1:0] havereset_d, havereset_q;
172: // program buffer
173: logic [dm::ProgBufSize-1:0][31:0] progbuf_d, progbuf_q;
174: logic [dm::DataCount-1:0][31:0] data_d, data_q;
175:
176: logic [HartSelLen-1:0] selected_hart;
177:
178: // a successful response returns zero
179: assign dmi_resp_o.resp = dm::DTM_SUCCESS;
180: // SBA
181: assign sbautoincrement_o = sbcs_q.sbautoincrement;
182: assign sbreadonaddr_o = sbcs_q.sbreadonaddr;
183: assign sbreadondata_o = sbcs_q.sbreadondata;
184: assign sbaccess_o = sbcs_q.sbaccess;
185: assign sbdata_o = sbdata_q[BusWidth-1:0];
186: assign sbaddress_o = sbaddr_q[BusWidth-1:0];
187:
188: assign hartsel_o = {dmcontrol_q.hartselhi, dmcontrol_q.hartsello};
189:
190: // needed to avoid lint warnings
191: logic [NrHartsAligned-1:0] havereset_d_aligned, havereset_q_aligned,
192: resumeack_aligned, unavailable_aligned,
193: halted_aligned;
194: assign resumeack_aligned = NrHartsAligned'(resumeack_i);
195: assign unavailable_aligned = NrHartsAligned'(unavailable_i);
196: assign halted_aligned = NrHartsAligned'(halted_i);
197:
198: assign havereset_d = NrHarts'(havereset_d_aligned);
199: assign havereset_q_aligned = NrHartsAligned'(havereset_q);
200:
201: dm::hartinfo_t [NrHartsAligned-1:0] hartinfo_aligned;
202: always_comb begin : p_hartinfo_align
203: hartinfo_aligned = '0;
204: hartinfo_aligned[NrHarts-1:0] = hartinfo_i;
205: end
206:
207: // helper variables
208: dm::sbcs_t sbcs;
209: dm::dmcontrol_t dmcontrol;
210: dm::abstractcs_t a_abstractcs;
211: logic [4:0] autoexecdata_idx;
212: always_comb begin : csr_read_write
213: // --------------------
214: // Static Values (R/O)
215: // --------------------
216: // dmstatus
217: dmstatus = '0;
218: dmstatus.version = dm::DbgVersion013;
219: // no authentication implemented
220: dmstatus.authenticated = 1'b1;
221: // we do not support halt-on-reset sequence
222: dmstatus.hasresethaltreq = 1'b0;
223: // TODO(zarubaf) things need to change here if we implement the array mask
224: dmstatus.allhavereset = havereset_q_aligned[selected_hart];
225: dmstatus.anyhavereset = havereset_q_aligned[selected_hart];
226:
227: dmstatus.allresumeack = resumeack_aligned[selected_hart];
228: dmstatus.anyresumeack = resumeack_aligned[selected_hart];
229:
230: dmstatus.allunavail = unavailable_aligned[selected_hart];
231: dmstatus.anyunavail = unavailable_aligned[selected_hart];
232:
233: // as soon as we are out of the legal Hart region tell the debugger
234: // that there are only non-existent harts
235: dmstatus.allnonexistent = logic'(32'(hartsel_o) > (NrHarts - 1));
236: dmstatus.anynonexistent = logic'(32'(hartsel_o) > (NrHarts - 1));
237:
238: // We are not allowed to be in multiple states at once. This is a to
239: // make the running/halted and unavailable states exclusive.
240: dmstatus.allhalted = halted_aligned[selected_hart] & ~unavailable_aligned[selected_hart];
241: dmstatus.anyhalted = halted_aligned[selected_hart] & ~unavailable_aligned[selected_hart];
242:
243: dmstatus.allrunning = ~halted_aligned[selected_hart] & ~unavailable_aligned[selected_hart];
244: dmstatus.anyrunning = ~halted_aligned[selected_hart] & ~unavailable_aligned[selected_hart];
245:
246: // abstractcs
247: abstractcs = '0;
248: abstractcs.datacount = dm::DataCount;
249: abstractcs.progbufsize = dm::ProgBufSize;
250: abstractcs.busy = cmdbusy_i;
251: abstractcs.cmderr = cmderr_q;
252:
253: // abstractautoexec
254: abstractauto_d = abstractauto_q;
255: abstractauto_d.zero0 = '0;
256:
257: // default assignments
258: havereset_d_aligned = NrHartsAligned'(havereset_q);
259: dmcontrol_d = dmcontrol_q;
260: cmderr_d = cmderr_q;
261: command_d = command_q;
262: progbuf_d = progbuf_q;
263: data_d = data_q;
264: sbcs_d = sbcs_q;
265: sbaddr_d = 64'(sbaddress_i);
266: sbdata_d = sbdata_q;
267:
268: resp_queue_data = 32'b0;
269: cmd_valid_d = 1'b0;
270: sbaddress_write_valid_o = 1'b0;
271: sbdata_read_valid_o = 1'b0;
272: sbdata_write_valid_o = 1'b0;
273: clear_resumeack_o = 1'b0;
274:
275: // helper variables
276: sbcs = '0;
277: dmcontrol = '0;
278: a_abstractcs = '0;
279:
280: autoexecdata_idx = dmi_req_i.addr[4:0] - 5'(dm::Data0);
281:
282: // localparam int unsigned DataCountAlign = $clog2(dm::DataCount);
283: // reads
284: if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) begin
285: unique case ({1'b0, dmi_req_i.addr}) inside
286: [(dm::Data0):DataEnd]: begin
287: // logic [$clog2(dm::DataCount)-1:0] resp_queue_idx;
288: // resp_queue_idx = dmi_req_i.addr[4:0] - int'(dm::Data0);
289: resp_queue_data = data_q[$clog2(dm::DataCount)'(autoexecdata_idx)];
290: if (!cmdbusy_i) begin
291: // check whether we need to re-execute the command (just give a cmd_valid)
292: if (autoexecdata_idx < $bits(abstractauto_q.autoexecdata)) begin
293: cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx];
294: end
295: end
296: end
297: dm::DMControl: resp_queue_data = dmcontrol_q;
298: dm::DMStatus: resp_queue_data = dmstatus;
299: dm::Hartinfo: resp_queue_data = hartinfo_aligned[selected_hart];
300: dm::AbstractCS: resp_queue_data = abstractcs;
301: dm::AbstractAuto: resp_queue_data = abstractauto_q;
302: // command is read-only
303: dm::Command: resp_queue_data = '0;
304: [(dm::ProgBuf0):ProgBufEnd]: begin
305: resp_queue_data = progbuf_q[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]];
306: if (!cmdbusy_i) begin
307: // check whether we need to re-execute the command (just give a cmd_valid)
308: // range of autoexecprogbuf is 31:16
309: cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}];
310: end
311: end
312: dm::HaltSum0: resp_queue_data = haltsum0;
313: dm::HaltSum1: resp_queue_data = haltsum1;
314: dm::HaltSum2: resp_queue_data = haltsum2;
315: dm::HaltSum3: resp_queue_data = haltsum3;
316: dm::SBCS: begin
317: resp_queue_data = sbcs_q;
318: end
319: dm::SBAddress0: begin
320: // access while the SBA was busy
321: if (sbbusy_i) begin
322: sbcs_d.sbbusyerror = 1'b1;
323: end else begin
324: resp_queue_data = sbaddr_q[31:0];
325: end
326: end
327: dm::SBAddress1: begin
328: // access while the SBA was busy
329: if (sbbusy_i) begin
330: sbcs_d.sbbusyerror = 1'b1;
331: end else begin
332: resp_queue_data = sbaddr_q[63:32];
333: end
334: end
335: dm::SBData0: begin
336: // access while the SBA was busy
337: if (sbbusy_i) begin
338: sbcs_d.sbbusyerror = 1'b1;
339: end else begin
340: sbdata_read_valid_o = (sbcs_q.sberror == '0);
341: resp_queue_data = sbdata_q[31:0];
342: end
343: end
344: dm::SBData1: begin
345: // access while the SBA was busy
346: if (sbbusy_i) begin
347: sbcs_d.sbbusyerror = 1'b1;
348: end else begin
349: resp_queue_data = sbdata_q[63:32];
350: end
351: end
352: default:;
353: endcase
354: end
355:
356: // write
357: if (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_WRITE) begin
358: unique case (dm::dm_csr_e'({1'b0, dmi_req_i.addr})) inside
359: [(dm::Data0):DataEnd]: begin
360: // attempts to write them while busy is set does not change their value
361: if (!cmdbusy_i && dm::DataCount > 0) begin
362: data_d[dmi_req_i.addr[$clog2(dm::DataCount)-1:0]] = dmi_req_i.data;
363: // check whether we need to re-execute the command (just give a cmd_valid)
364: if (autoexecdata_idx < $bits(abstractauto_q.autoexecdata)) begin
365: cmd_valid_d = abstractauto_q.autoexecdata[autoexecdata_idx];
366: end
367: end
368: end
369: dm::DMControl: begin
370: dmcontrol = dm::dmcontrol_t'(dmi_req_i.data);
371: // clear the havreset of the selected hart
372: if (dmcontrol.ackhavereset) begin
373: havereset_d_aligned[selected_hart] = 1'b0;
374: end
375: dmcontrol_d = dmi_req_i.data;
376: end
377: dm::DMStatus:; // write are ignored to R/O register
378: dm::Hartinfo:; // hartinfo is R/O
379: // only command error is write-able
380: dm::AbstractCS: begin // W1C
381: // Gets set if an abstract command fails. The bits in this
382: // field remain set until they are cleared by writing 1 to
383: // them. No abstract command is started until the value is
384: // reset to 0.
385: a_abstractcs = dm::abstractcs_t'(dmi_req_i.data);
386: // reads during abstract command execution are not allowed
387: if (!cmdbusy_i) begin
388: cmderr_d = dm::cmderr_e'(~a_abstractcs.cmderr & cmderr_q);
389: end else if (cmderr_q == dm::CmdErrNone) begin
390: cmderr_d = dm::CmdErrBusy;
391: end
392: end
393: dm::Command: begin
394: // writes are ignored if a command is already busy
395: if (!cmdbusy_i) begin
396: cmd_valid_d = 1'b1;
397: command_d = dm::command_t'(dmi_req_i.data);
398: // if there was an attempted to write during a busy execution
399: // and the cmderror field is zero set the busy error
400: end else if (cmderr_q == dm::CmdErrNone) begin
401: cmderr_d = dm::CmdErrBusy;
402: end
403: end
404: dm::AbstractAuto: begin
405: // this field can only be written legally when there is no command executing
406: if (!cmdbusy_i) begin
407: abstractauto_d = 32'b0;
408: abstractauto_d.autoexecdata = 12'(dmi_req_i.data[dm::DataCount-1:0]);
409: abstractauto_d.autoexecprogbuf = 16'(dmi_req_i.data[dm::ProgBufSize-1+16:16]);
410: end else if (cmderr_q == dm::CmdErrNone) begin
411: cmderr_d = dm::CmdErrBusy;
412: end
413: end
414: [(dm::ProgBuf0):ProgBufEnd]: begin
415: // attempts to write them while busy is set does not change their value
416: if (!cmdbusy_i) begin
417: progbuf_d[dmi_req_i.addr[$clog2(dm::ProgBufSize)-1:0]] = dmi_req_i.data;
418: // check whether we need to re-execute the command (just give a cmd_valid)
419: // this should probably throw an error if executed during another command
420: // was busy
421: // range of autoexecprogbuf is 31:16
422: cmd_valid_d = abstractauto_q.autoexecprogbuf[{1'b1, dmi_req_i.addr[3:0]}];
423: end
424: end
425: dm::SBCS: begin
426: // access while the SBA was busy
427: if (sbbusy_i) begin
428: sbcs_d.sbbusyerror = 1'b1;
429: end else begin
430: sbcs = dm::sbcs_t'(dmi_req_i.data);
431: sbcs_d = sbcs;
432: // R/W1C
433: sbcs_d.sbbusyerror = sbcs_q.sbbusyerror & (~sbcs.sbbusyerror);
434: sbcs_d.sberror = sbcs_q.sberror & (~sbcs.sberror);
435: end
436: end
437: dm::SBAddress0: begin
438: // access while the SBA was busy
439: if (sbbusy_i) begin
440: sbcs_d.sbbusyerror = 1'b1;
441: end else begin
442: sbaddr_d[31:0] = dmi_req_i.data;
443: sbaddress_write_valid_o = (sbcs_q.sberror == '0);
444: end
445: end
446: dm::SBAddress1: begin
447: // access while the SBA was busy
448: if (sbbusy_i) begin
449: sbcs_d.sbbusyerror = 1'b1;
450: end else begin
451: sbaddr_d[63:32] = dmi_req_i.data;
452: end
453: end
454: dm::SBData0: begin
455: // access while the SBA was busy
456: if (sbbusy_i) begin
457: sbcs_d.sbbusyerror = 1'b1;
458: end else begin
459: sbdata_d[31:0] = dmi_req_i.data;
460: sbdata_write_valid_o = (sbcs_q.sberror == '0);
461: end
462: end
463: dm::SBData1: begin
464: // access while the SBA was busy
465: if (sbbusy_i) begin
466: sbcs_d.sbbusyerror = 1'b1;
467: end else begin
468: sbdata_d[63:32] = dmi_req_i.data;
469: end
470: end
471: default:;
472: endcase
473: end
474: // hart threw a command error and has precedence over bus writes
475: if (cmderror_valid_i) begin
476: cmderr_d = cmderror_i;
477: end
478:
479: // update data registers
480: if (data_valid_i) begin
481: data_d = data_i;
482: end
483:
484: // set the havereset flag when we did a ndmreset
485: if (ndmreset_o) begin
486: havereset_d_aligned[NrHarts-1:0] = '1;
487: end
488: // -------------
489: // System Bus
490: // -------------
491: // set bus error
492: if (sberror_valid_i) begin
493: sbcs_d.sberror = sberror_i;
494: end
495: // update read data
496: if (sbdata_valid_i) begin
497: sbdata_d = 64'(sbdata_i);
498: end
499:
500: // dmcontrol
501: // TODO(zarubaf) we currently do not implement the hartarry mask
502: dmcontrol_d.hasel = 1'b0;
503: // we do not support resetting an individual hart
504: dmcontrol_d.hartreset = 1'b0;
505: dmcontrol_d.setresethaltreq = 1'b0;
506: dmcontrol_d.clrresethaltreq = 1'b0;
507: dmcontrol_d.zero1 = '0;
508: dmcontrol_d.zero0 = '0;
509: // Non-writeable, clear only
510: dmcontrol_d.ackhavereset = 1'b0;
511: if (!dmcontrol_q.resumereq && dmcontrol_d.resumereq) begin
512: clear_resumeack_o = 1'b1;
513: end
514: if (dmcontrol_q.resumereq && resumeack_i) begin
515: dmcontrol_d.resumereq = 1'b0;
516: end
517: // static values for dcsr
518: sbcs_d.sbversion = 3'b1;
519: sbcs_d.sbbusy = sbbusy_i;
520: sbcs_d.sbasize = $bits(sbcs_d.sbasize)'(BusWidth);
521: sbcs_d.sbaccess128 = 1'b0;
522: sbcs_d.sbaccess64 = logic'(BusWidth == 32'd64);
523: sbcs_d.sbaccess32 = logic'(BusWidth == 32'd32);
524: sbcs_d.sbaccess16 = 1'b0;
525: sbcs_d.sbaccess8 = 1'b0;
526: sbcs_d.sbaccess = (BusWidth == 32'd64) ? 3'd3 : 3'd2;
527: end
528:
529: // output multiplexer
530: always_comb begin : p_outmux
531: selected_hart = hartsel_o[HartSelLen-1:0];
532: // default assignment
533: haltreq_o = '0;
534: resumereq_o = '0;
535: if (selected_hart < (HartSelLen+1)'(NrHarts)) begin
536: haltreq_o[selected_hart] = dmcontrol_q.haltreq;
537: resumereq_o[selected_hart] = dmcontrol_q.resumereq;
538: end
539: end
540:
541: assign dmactive_o = dmcontrol_q.dmactive;
542: assign cmd_o = command_q;
543: assign cmd_valid_o = cmd_valid_q;
544: assign progbuf_o = progbuf_q;
545: assign data_o = data_q;
546:
547: assign ndmreset_o = dmcontrol_q.ndmreset;
548:
549: logic unused_testmode;
550: assign unused_testmode = testmode_i;
551:
552: // response FIFO
553: prim_fifo_sync #(
554: .Width (32),
555: .Pass (1'b0),
556: .Depth (2)
557: ) i_fifo (
558: .clk_i ( clk_i ),
559: .rst_ni ( dmi_rst_ni ), // reset only when system is re-set
560: .clr_i ( 1'b0 ),
561: .wdata ( resp_queue_data ),
562: .wvalid ( dmi_req_valid_i ),
563: .wready ( dmi_req_ready_o ),
564: .rdata ( dmi_resp_o.data ),
565: .rvalid ( dmi_resp_valid_o ),
566: .rready ( dmi_resp_ready_i ),
567: .depth ( ) // Doesn't use
568: );
569:
570: always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
571: // PoR
572: if (!rst_ni) begin
573: dmcontrol_q <= '0;
574: // this is the only write-able bit during reset
575: cmderr_q <= dm::CmdErrNone;
576: command_q <= '0;
577: abstractauto_q <= '0;
578: progbuf_q <= '0;
579: data_q <= '0;
580: sbcs_q <= '0;
581: sbaddr_q <= '0;
582: sbdata_q <= '0;
583: havereset_q <= '1;
584: end else begin
585: havereset_q <= SelectableHarts & havereset_d;
586: // synchronous re-set of debug module, active-low, except for dmactive
587: if (!dmcontrol_q.dmactive) begin
588: dmcontrol_q.haltreq <= '0;
589: dmcontrol_q.resumereq <= '0;
590: dmcontrol_q.hartreset <= '0;
591: dmcontrol_q.ackhavereset <= '0;
592: dmcontrol_q.zero1 <= '0;
593: dmcontrol_q.hasel <= '0;
594: dmcontrol_q.hartsello <= '0;
595: dmcontrol_q.hartselhi <= '0;
596: dmcontrol_q.zero0 <= '0;
597: dmcontrol_q.setresethaltreq <= '0;
598: dmcontrol_q.clrresethaltreq <= '0;
599: dmcontrol_q.ndmreset <= '0;
600: // this is the only write-able bit during reset
601: dmcontrol_q.dmactive <= dmcontrol_d.dmactive;
602: cmderr_q <= dm::CmdErrNone;
603: command_q <= '0;
604: cmd_valid_q <= '0;
605: abstractauto_q <= '0;
606: progbuf_q <= '0;
607: data_q <= '0;
608: sbcs_q <= '0;
609: sbaddr_q <= '0;
610: sbdata_q <= '0;
611: end else begin
612: dmcontrol_q <= dmcontrol_d;
613: cmderr_q <= cmderr_d;
614: command_q <= command_d;
615: cmd_valid_q <= cmd_valid_d;
616: abstractauto_q <= abstractauto_d;
617: progbuf_q <= progbuf_d;
618: data_q <= data_d;
619: sbcs_q <= sbcs_d;
620: sbaddr_q <= sbaddr_d;
621: sbdata_q <= sbdata_d;
622: end
623: end
624: end
625:
626: ///////////////////////////////////////////////////////
627: // assertions
628: ///////////////////////////////////////////////////////
629:
630: //pragma translate_off
631: `ifndef VERILATOR
632: haltsum: assert property (
633: @(posedge clk_i) disable iff (!rst_ni)
634: (dmi_req_ready_o && dmi_req_valid_i && dtm_op == dm::DTM_READ) |->
635: !({1'b0, dmi_req_i.addr} inside
636: {dm::HaltSum0, dm::HaltSum1, dm::HaltSum2, dm::HaltSum3}))
637: else $warning("Haltsums have not been properly tested yet.");
638: `endif
639: //pragma translate_on
640:
641: endmodule : dm_csrs
642: