// IEEE 1149.1 - digital // IEEE 1149.4 - analog / mixed-signal // IEEE 1149.5 - system level // IEEE 1149.6 - ac-coupled, differential nets // IEEE 1532 - boundary scan (superset of IEEE 1149.1) // References: // http://www.interfacebus.com/Design_Connector_JTAG_Bus.html // Designing to IEEE 1149.1-2013 module jtag_tap( input wire jtag_tck, input wire jtag_tms, // tie high to disable module input wire jtag_tdi, output reg jtag_tdo, input wire jtag_trst, // [optional] async active low reset ); // NOTE: do not connect jtag_trst to any system logic (only tie to test logic) // For instance a reset input to the IC must not change the JTAG TAP state // TODO: TMP controller (IEEE 1149.1-2013 6.2.1) // State values according to IEEE 1149.1-2013 localparam STATE_EXIT_2_DR = 4'h0, STATE_EXIT_1_DR = 4'h1, STATE_SHIFT_DR = 4'h2, STATE_PAUSE_DR = 4'h3, STATE_SELECT_IR_SCAN = 4'h4, STATE_UPDATE_DR = 4'h5, STATE_CAPTURE_DR = 4'h6, STATE_SELECT_DR_SCAN = 4'h7, STATE_EXIT_2_IR = 4'h8, STATE_EXIT_1_IR = 4'h9, STATE_SHIFT_IR = 4'hA, STATE_PAUSE_IR = 4'hB, STATE_RUN_TEST_IDLE = 4'hC, STATE_UPDATE_IR = 4'hD, STATE_CAPTURE_IR = 4'hD, STATE_TEST_LOGIC_RESET = 4'hF; localparam INSTR_BYPASS = 8'hFF, // required always // may also be other codes: recommend 0 INSTR_SAMPLE = 8'h, // required always INSTR_PRELOAD = 8'h, // required always INSTR_EXTEST = 8'h, // required always INSTR_IDCODE = 8'h, // required if IDCODE register is included INSTR_USERCODE = 8'h, // required if IDCODE register is included in a user-programmable component that does not allow programming via this test logic // INSTR_CLAMP = 8'hxx, // INSTR_HIGHZ = 8'hxx, INSTR_IC_RESET = 8'h, // required if reset selection register is included // INSTR_CLAMP_HOLD = 8'hxx, // required if TMP controller & TMP status register are included // INSTR_CLAMP_RELEASE = 8'hxx, // required if TMP controller & TMP status register are included // INSTR_TMP_STATUS = 8'hxx, // required if TMP controller & TMP status register are included // recommended if there is programmable I/O // INSTR_INIT_SETUP = 8'h, // required if initialization data register is included // INSTR_INIT_SETUP_CLAMP = 8'h, // required if initialization data register is included // INSTR_INIT_RUN = 8'h, // required if initialization status register is included // required registers reg [3:0] state = STATE_TEST_LOGIC_RESET; reg [7:0] reg_instruction_shift, reg_instruction; reg [7:0] reg_data; always @(posedge jtag_tck or posedge jtag_trst) begin : state_transitions if (jtag_trst == 1'b0) begin state <= STATE_TEST_LOGIC_RESET; end else begin case (state) begin STATE_TEST_LOGIC_RESET: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_RUN_TEST_IDLE; STATE_RUN_TEST_IDLE: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; STATE_SELECT_DR_SCAN: state <= jtag_tms ? STATE_SELECT_IR_SCAN : STATE_CAPTURE_DR; STATE_CAPTURE_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; STATE_SHIFT_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; STATE_EXIT_1_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_PAUSE_DR; STATE_PAUSE_DR: state <= jtag_tms ? STATE_EXIT_2_DR : STATE_PAUSE_DR; STATE_EXIT_2_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_SHIFT_DR; STATE_UPDATE_DR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; STATE_SELECT_IR_SCAN: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_CAPTURE_IR; STATE_CAPTURE_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; STATE_SHIFT_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; STATE_EXIT_1_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_PAUSE_IR; STATE_PAUSE_IR: state <= jtag_tms ? STATE_EXIT_2_IR : STATE_PAUSE_IR; STATE_EXIT_2_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_SHIFT_IR; STATE_UPDATE_IR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; end end end always @(posedge jtag_tck or posedge jtag_trst) begin : actions_posedge if (jtag_trst == 1'b0 || state == STATE_TEST_LOGIC_RESET) begin reg_instruction_shift <= 8'hxx; reg_instruction <= INSTR_IDCODE; end else begin case (state) STATE_TEST_LOGIC_RESET: begin reg_instruction_shift <= 8'hxx; reg_instruction <= INSTR_IDCODE; end STATE_CAPTURE_IR: begin // TODO: check MSB/LSB first reg_instruction_shift[1:0] <= 2'b01; reg_instruction_shift[7:2] <= 6'h00; // these bits may be chosen to be any fixed value // reg_instruction <= reg_instruction; end STATE_SHIFT_IR: begin // TODO: check MSB/LSB first reg_instruction_shift[7] <= jtag_tdi; reg_instruction_shift[6:0] <= reg_instruction_shift[7:1]; // reg_instruction <= reg_instruction; end STATE_EXIT_1_IR, STATE_EXIT_2_IR, STATE_PAUSE_IR: begin // reg_instruction_shift <= reg_instruction_shift; // reg_instruction <= reg_instruction; end STATE_UPDATE_IR: begin // reg_instruction_shift <= reg_instruction_shift; reg_instruction <= reg_instruction_shift; // TODO: do this on negedge? see pg 70 end default: begin reg_instruction_shift <= 8'hxx; // reg_instruction <= reg_instruction; end endcase // case (state) begin // STATE_TEST_LOGIC_RESET: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_RUN_TEST_IDLE; // STATE_RUN_TEST_IDLE: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // STATE_SELECT_DR_SCAN: state <= jtag_tms ? STATE_SELECT_IR_SCAN : STATE_CAPTURE_DR; // STATE_CAPTURE_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; // STATE_SHIFT_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; // STATE_EXIT_1_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_PAUSE_DR; // STATE_PAUSE_DR: state <= jtag_tms ? STATE_EXIT_2_DR : STATE_PAUSE_DR; // STATE_EXIT_2_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_SHIFT_DR; // STATE_UPDATE_DR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // STATE_SELECT_IR_SCAN: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_CAPTURE_IR; // STATE_CAPTURE_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; // STATE_SHIFT_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; // STATE_EXIT_1_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_PAUSE_IR; // STATE_PAUSE_IR: state <= jtag_tms ? STATE_EXIT_2_IR : STATE_PAUSE_IR; // STATE_EXIT_2_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_SHIFT_IR; // STATE_UPDATE_IR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // end end end always @(negedge jtag_tck or posedge jtag_trst) begin : actions_negedge if (jtag_trst == 1'b0 || state == STATE_TEST_LOGIC_RESET) begin end else begin // case (state) begin // STATE_TEST_LOGIC_RESET: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_RUN_TEST_IDLE; // STATE_RUN_TEST_IDLE: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // STATE_SELECT_DR_SCAN: state <= jtag_tms ? STATE_SELECT_IR_SCAN : STATE_CAPTURE_DR; // STATE_CAPTURE_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; // STATE_SHIFT_DR: state <= jtag_tms ? STATE_EXIT_1_DR : STATE_SHIFT_DR; // STATE_EXIT_1_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_PAUSE_DR; // STATE_PAUSE_DR: state <= jtag_tms ? STATE_EXIT_2_DR : STATE_PAUSE_DR; // STATE_EXIT_2_DR: state <= jtag_tms ? STATE_UPDATE_DR : STATE_SHIFT_DR; // STATE_UPDATE_DR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // STATE_SELECT_IR_SCAN: state <= jtag_tms ? STATE_TEST_LOGIC_RESET : STATE_CAPTURE_IR; // STATE_CAPTURE_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; // STATE_SHIFT_IR: state <= jtag_tms ? STATE_EXIT_1_IR : STATE_SHIFT_IR; // STATE_EXIT_1_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_PAUSE_IR; // STATE_PAUSE_IR: state <= jtag_tms ? STATE_EXIT_2_IR : STATE_PAUSE_IR; // STATE_EXIT_2_IR: state <= jtag_tms ? STATE_UPDATE_IR : STATE_SHIFT_IR; // STATE_UPDATE_IR: state <= jtag_tms ? STATE_SELECT_DR_SCAN : STATE_RUN_TEST_IDLE; // end end end endmodule