hw/vendor/pulp_riscv_dbg/src/dm_csrs.sv Cov: 98.5%

   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: