mirror of
https://gitlab.com/brendanhaines/cpu.git
synced 2024-12-25 18:46:53 -07:00
add start of JTAG TAP
This commit is contained in:
parent
625001152d
commit
7ab99bb5ff
179
other_projects/jtag.v
Normal file
179
other_projects/jtag.v
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
|
||||||
|
// 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
|
Loading…
Reference in New Issue
Block a user