├── .gitignore ├── LICENSE.txt ├── README.md ├── ocd_altera.sh ├── quartus_deca ├── .gitignore ├── direct_jtag.qpf └── direct_jtag.qsf └── rtl └── top.v /.gitignore: -------------------------------------------------------------------------------- 1 | .*swp 2 | *.bak 3 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021 Tom Verbeure 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # Intel JTAG Primitive 3 | 4 | This is the example code that goes with 5 | [The Intel JTAG Primitive - Using JTAG without Virtual JTAG](https://tomverbeure.github.io/2021/10/30/Intel-JTAG-Primitive.html) 6 | blog post. 7 | 8 | -------------------------------------------------------------------------------- /ocd_altera.sh: -------------------------------------------------------------------------------- 1 | 2 | /opt/openocd/bin/openocd -f interface/altera-usb-blaster2.cfg -c "jtag newtap max10 fpga_tap -expected-id 0x031050dd -irlen 10" 3 | 4 | -------------------------------------------------------------------------------- /quartus_deca/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /quartus_deca/direct_jtag.qpf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2020 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and any partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel FPGA IP License Agreement, or other applicable license 12 | # agreement, including, without limitation, that your use is for 13 | # the sole purpose of programming logic devices manufactured by 14 | # Intel and sold by Intel or its authorized distributors. Please 15 | # refer to the applicable agreement for further details, at 16 | # https://fpgasoftware.intel.com/eula. 17 | # 18 | # -------------------------------------------------------------------------- # 19 | # 20 | # Quartus Prime 21 | # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition 22 | # Date created = 17:14:27 October 28, 2021 23 | # 24 | # -------------------------------------------------------------------------- # 25 | 26 | QUARTUS_VERSION = "20.1" 27 | DATE = "17:14:27 October 28, 2021" 28 | 29 | # Revisions 30 | 31 | PROJECT_REVISION = "direct_jtag" 32 | -------------------------------------------------------------------------------- /quartus_deca/direct_jtag.qsf: -------------------------------------------------------------------------------- 1 | # -------------------------------------------------------------------------- # 2 | # 3 | # Copyright (C) 2020 Intel Corporation. All rights reserved. 4 | # Your use of Intel Corporation's design tools, logic functions 5 | # and other software and tools, and any partner logic 6 | # functions, and any output files from any of the foregoing 7 | # (including device programming or simulation files), and any 8 | # associated documentation or information are expressly subject 9 | # to the terms and conditions of the Intel Program License 10 | # Subscription Agreement, the Intel Quartus Prime License Agreement, 11 | # the Intel FPGA IP License Agreement, or other applicable license 12 | # agreement, including, without limitation, that your use is for 13 | # the sole purpose of programming logic devices manufactured by 14 | # Intel and sold by Intel or its authorized distributors. Please 15 | # refer to the applicable agreement for further details, at 16 | # https://fpgasoftware.intel.com/eula. 17 | # 18 | # -------------------------------------------------------------------------- # 19 | # 20 | # Quartus Prime 21 | # Version 20.1.1 Build 720 11/11/2020 SJ Lite Edition 22 | # Date created = 17:14:27 October 28, 2021 23 | # 24 | # -------------------------------------------------------------------------- # 25 | # 26 | # Notes: 27 | # 28 | # 1) The default values for assignments are stored in the file: 29 | # direct_jtag_assignment_defaults.qdf 30 | # If this file doesn't exist, see file: 31 | # assignment_defaults.qdf 32 | # 33 | # 2) Altera recommends that you do not modify this file. This 34 | # file is updated automatically by the Quartus Prime software 35 | # and any changes you make may be lost or overwritten. 36 | # 37 | # -------------------------------------------------------------------------- # 38 | 39 | 40 | set_global_assignment -name FAMILY "MAX 10" 41 | set_global_assignment -name DEVICE 10M50DAF484C6GES 42 | set_global_assignment -name TOP_LEVEL_ENTITY top 43 | set_global_assignment -name ORIGINAL_QUARTUS_VERSION 20.1.1 44 | set_global_assignment -name PROJECT_CREATION_TIME_DATE "17:14:27 OCTOBER 28, 2021" 45 | set_global_assignment -name LAST_QUARTUS_VERSION "20.1.1 Lite Edition" 46 | set_global_assignment -name PROJECT_OUTPUT_DIRECTORY output_files 47 | set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0 48 | set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85 49 | set_global_assignment -name DEVICE_FILTER_PIN_COUNT 484 50 | set_global_assignment -name DEVICE_FILTER_SPEED_GRADE 6 51 | set_global_assignment -name ERROR_CHECK_FREQUENCY_DIVISOR 256 52 | set_global_assignment -name EDA_SIMULATION_TOOL "ModelSim-Altera (VHDL)" 53 | set_global_assignment -name EDA_OUTPUT_DATA_FORMAT VHDL -section_id eda_simulation 54 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_timing_analysis 55 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_formal_verification 56 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_timing 57 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_symbol 58 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_signal_integrity 59 | set_global_assignment -name EDA_GENERATE_FUNCTIONAL_NETLIST OFF -section_id eda_board_design_boundary_scan 60 | set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top 61 | set_global_assignment -name PARTITION_FITTER_PRESERVATION_LEVEL PLACEMENT_AND_ROUTING -section_id Top 62 | set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top 63 | set_global_assignment -name POWER_PRESET_COOLING_SOLUTION "23 MM HEAT SINK WITH 200 LFPM AIRFLOW" 64 | set_global_assignment -name POWER_BOARD_THERMAL_MODEL "NONE (CONSERVATIVE)" 65 | set_global_assignment -name VERILOG_FILE ../rtl/top.v 66 | set_global_assignment -name FORCE_CONFIGURATION_VCCIO ON 67 | set_global_assignment -name AUTO_RESTART_CONFIGURATION OFF 68 | set_global_assignment -name ENABLE_CONFIGURATION_PINS OFF 69 | set_global_assignment -name ENABLE_BOOT_SEL_PIN OFF 70 | 71 | set_location_assignment PIN_H21 -to button 72 | set_location_assignment PIN_M8 -to clk 73 | set_location_assignment PIN_C7 -to led0 74 | set_location_assignment PIN_C8 -to led1 75 | set_location_assignment PIN_A6 -to led2 76 | 77 | set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL" 78 | set_instance_assignment -name IO_STANDARD "2.5 V" -to clk 79 | set_global_assignment -name USE_CONFIGURATION_DEVICE OFF 80 | set_global_assignment -name INTERNAL_FLASH_UPDATE_MODE "SINGLE COMP IMAGE WITH ERAM" 81 | set_global_assignment -name CRC_ERROR_OPEN_DRAIN OFF 82 | set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -rise 83 | set_global_assignment -name OUTPUT_IO_TIMING_NEAR_END_VMEAS "HALF VCCIO" -fall 84 | set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -rise 85 | set_global_assignment -name OUTPUT_IO_TIMING_FAR_END_VMEAS "HALF SIGNAL SWING" -fall 86 | set_global_assignment -name IOBANK_VCCIO 1.2V -section_id 8 87 | set_global_assignment -name IOBANK_VCCIO 1.8V -section_id 7 88 | set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 1A 89 | set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 1B 90 | set_global_assignment -name IOBANK_VCCIO 2.5V -section_id 2 91 | set_global_assignment -name IOBANK_VCCIO 3.3V -section_id 3 92 | set_global_assignment -name IOBANK_VCCIO 3.3V -section_id 4 93 | set_global_assignment -name IOBANK_VCCIO 1.5V -section_id 6 94 | set_global_assignment -name IOBANK_VCCIO 1.5V -section_id 5 95 | set_instance_assignment -name IO_STANDARD "1.5 V" -to button 96 | set_instance_assignment -name IO_STANDARD "1.2 V" -to led0 97 | set_instance_assignment -name IO_STANDARD "1.2 V" -to led1 98 | set_instance_assignment -name IO_STANDARD "1.2 V" -to led2 99 | 100 | set_global_assignment -name ENABLE_SIGNALTAP OFF 101 | set_global_assignment -name USE_SIGNALTAP_FILE cpu_debug.stp 102 | set_location_assignment PIN_Y5 -to probe_tck 103 | set_location_assignment PIN_Y6 -to probe_tms 104 | set_location_assignment PIN_W6 -to probe_tdi 105 | set_location_assignment PIN_W7 -to probe_tdocore 106 | set_location_assignment PIN_W8 -to probe_tdouser 107 | set_location_assignment PIN_V8 -to probe_clkdruser 108 | set_location_assignment PIN_AB8 -to probe_runidleuser 109 | set_location_assignment PIN_V7 -to probe_shiftuser 110 | set_location_assignment PIN_R11 -to probe_updateuser 111 | set_location_assignment PIN_AB7 -to probe_usr1user 112 | set_global_assignment -name SDC_FILE output_files/direct_jtag.sdc 113 | set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top -------------------------------------------------------------------------------- /rtl/top.v: -------------------------------------------------------------------------------- 1 | 2 | `default_nettype none 3 | 4 | module top( 5 | input wire button, 6 | output wire led0, 7 | output wire led1, 8 | output wire led2, 9 | 10 | input wire altera_reserved_tck, 11 | input wire altera_reserved_tms, 12 | input wire altera_reserved_tdi, 13 | output wire altera_reserved_tdo 14 | ); 15 | 16 | //============================================================ 17 | // Intel JTAG Primitive 18 | //============================================================ 19 | 20 | wire tmsutap; 21 | wire tckutap; 22 | wire tdiutap; 23 | 24 | wire clkdruser; 25 | wire runidleuser; 26 | wire shiftuser; 27 | wire updateuser; 28 | wire usr1user; 29 | reg tdouser; 30 | 31 | fiftyfivenm_jtag u_jtag( 32 | .tms(altera_reserved_tms), 33 | .tck(altera_reserved_tck), 34 | .tdi(altera_reserved_tdi), 35 | .tdo(altera_reserved_tdo), 36 | 37 | .tckutap(tckutap), 38 | .tmsutap(tmsutap), 39 | .tdiutap(tdiutap), 40 | 41 | .corectl (1'b0), 42 | 43 | .clkdruser (clkdruser), 44 | .shiftuser (shiftuser), 45 | .usr1user (usr1user), 46 | .updateuser (updateuser), 47 | .runidleuser (runidleuser), 48 | .tdouser (tdouser) 49 | ); 50 | 51 | //============================================================ 52 | // Tracking TAP FSM and IR capture to create captureuser signal 53 | //============================================================ 54 | localparam jtag_exit2_dr = 0; 55 | localparam jtag_exit1_dr = 1; 56 | localparam jtag_shift_dr = 2; 57 | localparam jtag_pause_dr = 3; 58 | localparam jtag_select_ir_scan = 4; 59 | localparam jtag_update_dr = 5; 60 | localparam jtag_capture_dr = 6; 61 | localparam jtag_select_dr_scan = 7; 62 | localparam jtag_exit2_ir = 8; 63 | localparam jtag_exit1_ir = 9; 64 | localparam jtag_shift_ir = 10; 65 | localparam jtag_pause_ir = 11; 66 | localparam jtag_run_test_idle = 12; 67 | localparam jtag_update_ir = 13; 68 | localparam jtag_capture_ir = 14; 69 | localparam jtag_test_logic_reset = 15; 70 | 71 | reg [3:0] jtag_fsm_state = 15; 72 | 73 | always @(posedge tckutap) begin 74 | case(jtag_fsm_state) 75 | jtag_test_logic_reset: jtag_fsm_state <= tmsutap ? jtag_test_logic_reset : jtag_run_test_idle; 76 | jtag_run_test_idle : jtag_fsm_state <= tmsutap ? jtag_select_dr_scan : jtag_run_test_idle; 77 | jtag_select_dr_scan : jtag_fsm_state <= tmsutap ? jtag_select_ir_scan : jtag_capture_dr; 78 | jtag_capture_dr : jtag_fsm_state <= tmsutap ? jtag_exit1_dr : jtag_shift_dr; 79 | jtag_shift_dr : jtag_fsm_state <= tmsutap ? jtag_exit1_dr : jtag_shift_dr; 80 | jtag_exit1_dr : jtag_fsm_state <= tmsutap ? jtag_update_dr : jtag_pause_dr; 81 | jtag_pause_dr : jtag_fsm_state <= tmsutap ? jtag_exit2_dr : jtag_pause_dr; 82 | jtag_exit2_dr : jtag_fsm_state <= tmsutap ? jtag_update_dr : jtag_shift_dr; 83 | jtag_update_dr : jtag_fsm_state <= tmsutap ? jtag_select_dr_scan : jtag_run_test_idle; 84 | jtag_select_ir_scan : jtag_fsm_state <= tmsutap ? jtag_test_logic_reset : jtag_capture_ir; 85 | jtag_capture_ir : jtag_fsm_state <= tmsutap ? jtag_exit1_ir : jtag_shift_ir; 86 | jtag_shift_ir : jtag_fsm_state <= tmsutap ? jtag_exit1_ir : jtag_shift_ir; 87 | jtag_exit1_ir : jtag_fsm_state <= tmsutap ? jtag_update_ir : jtag_pause_ir; 88 | jtag_pause_ir : jtag_fsm_state <= tmsutap ? jtag_exit2_ir : jtag_pause_dr; 89 | jtag_exit2_ir : jtag_fsm_state <= tmsutap ? jtag_update_ir : jtag_shift_ir; 90 | jtag_update_ir : jtag_fsm_state <= tmsutap ? jtag_select_dr_scan : jtag_run_test_idle; 91 | endcase 92 | end 93 | 94 | wire capture_dr; 95 | assign capture_dr = (jtag_fsm_state == jtag_capture_dr); 96 | 97 | reg [9:0] ir_shiftreg = 0; 98 | reg [9:0] ir_reg = 0; 99 | 100 | always @(posedge tckutap) begin 101 | if (jtag_fsm_state == jtag_shift_ir) begin 102 | ir_shiftreg <= { tdiutap, ir_shiftreg[9:1] }; 103 | end 104 | 105 | if (jtag_fsm_state == jtag_update_ir) begin 106 | ir_reg <= ir_shiftreg; 107 | end 108 | end 109 | 110 | wire captureuser; 111 | assign captureuser = capture_dr && (ir_reg == 10'h00c || ir_reg == 10'h00e); 112 | 113 | //============================================================ 114 | // USER0 and USER1 Chains 115 | //============================================================ 116 | 117 | // USER0 counts the number of times Capture-DR has been triggered when USER0 was selected. 118 | reg [7:0] user0_shiftreg = 0; 119 | reg [7:0] user0_reg = 0; 120 | reg [7:0] user0_cntr = 0; 121 | 122 | // USER1 is used to capture the state of the Arrow DECA button and to drive 3 LEDs. 123 | reg [7:0] user1_shiftreg = 0; 124 | reg [7:0] user1_reg = 0; 125 | 126 | always @(posedge tckutap) begin 127 | if (!usr1user) begin 128 | if (captureuser) begin 129 | user0_shiftreg <= user0_cntr; 130 | user0_cntr <= user0_cntr + 1'b1; 131 | end 132 | 133 | if (shiftuser) 134 | user0_shiftreg <= { tdiutap, user0_shiftreg[7:1] }; 135 | 136 | if (updateuser) 137 | user0_reg <= user0_shiftreg; 138 | end 139 | else begin 140 | if (captureuser) 141 | user1_shiftreg <= { 7'h0, button }; 142 | 143 | if (shiftuser) 144 | user1_shiftreg <= { tdiutap, user1_shiftreg[7:1] }; 145 | 146 | if (updateuser) 147 | user1_reg <= user1_shiftreg; 148 | end 149 | end 150 | 151 | always @(negedge tckutap) begin 152 | tdouser <= !usr1user ? user0_shiftreg[0] : user1_shiftreg[0]; 153 | end 154 | 155 | assign led0 = user1_reg[0]; 156 | assign led1 = user1_reg[1]; 157 | assign led2 = user1_reg[2]; 158 | 159 | endmodule 160 | 161 | --------------------------------------------------------------------------------