../src/pulp-platform_riscv-dbg_0.1_0/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: