├── .gitignore ├── src_files.yml ├── .gitlab-ci.yml ├── README.md ├── .dir-locals.el ├── Bender.yml ├── testbench ├── compile.tcl ├── Makefile ├── deprecated │ ├── top_tb_jtag.v │ └── inc_jtag.v └── tb_jtag.sv ├── src ├── jtag_sync.sv ├── jtag_enable_synch.sv ├── jtag_rst_synch.sv ├── bscell.sv ├── jtag_enable.sv ├── jtagreg.sv ├── jtag_axi_wrap.sv └── tap_top.v └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /TAGS 2 | /testbench/transcript 3 | /testbench/vsim.wlf 4 | *.do 5 | /Bender.lock 6 | work/ 7 | *.ini 8 | -------------------------------------------------------------------------------- /src_files.yml: -------------------------------------------------------------------------------- 1 | jtag_pulp: 2 | incdirs: [ 3 | ../../hw/includes, 4 | ] 5 | files: [ 6 | src/bscell.sv, 7 | src/jtag_axi_wrap.sv, 8 | src/jtag_enable.sv, 9 | src/jtag_enable_synch.sv, 10 | src/jtagreg.sv, 11 | src/jtag_rst_synch.sv, 12 | src/jtag_sync.sv, 13 | src/tap_top.v, 14 | ] 15 | 16 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | 2 | variables: 3 | VSIM: vsim-10.7e 4 | VLOG: vlog-10.7e 5 | 6 | before_script: 7 | - export PATH="~balasr/.local/bin":$PATH 8 | 9 | stages: 10 | - build 11 | - test 12 | 13 | build: 14 | stage: build 15 | script: 16 | - cd testbench 17 | - make build 18 | 19 | test_pulp_tap: 20 | stage: test 21 | script: 22 | - cd testbench 23 | - make build run 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PULP JTAG TAP 2 | This a JTAG TAP used in the PULP project. Supports 3 | [IPApproX](https://github.com/pulp-platform/IPApproX) and 4 | [bender](https://github.com/fabianschuiki/bender). 5 | 6 | ## Testbench 7 | There is already a pregenerate `compile.tcl` so you don't need to have bender in 8 | your path. 9 | 10 | Call `make build run` to run the testbench. You can pass custom flags to by 11 | modifying `VSIM_FLAGS` and `VLOG_FLAGS`. 12 | 13 | -------------------------------------------------------------------------------- /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ;;; Directory Local Variables 2 | ;;; For more information see (info "(emacs) Directory Variables") 3 | 4 | ((nil . ((fill-column . 80))) 5 | (verilog-mode 6 | ;; (verilog-indent-lists quote nil) 7 | ;; (verilog-auto-lineup quote all) 8 | (verilog-cexp-indent . 2) 9 | (verilog-case-indent . 2) 10 | (verilog-indent-level-behavioral . 2) 11 | (verilog-indent-level-declaration . 2) 12 | (verilog-indent-level-module . 2) 13 | (verilog-indent-level . 2))) 14 | -------------------------------------------------------------------------------- /Bender.yml: -------------------------------------------------------------------------------- 1 | package: 2 | name: jtag_pulp 3 | authors: 4 | - "Robert Balas " # current maintainer 5 | - "Antonio Pullini <>" 6 | - "Davide Schiavone " 7 | 8 | sources: 9 | - src/bscell.sv 10 | - src/jtag_axi_wrap.sv 11 | - src/jtag_enable.sv 12 | - src/jtag_enable_synch.sv 13 | - src/jtagreg.sv 14 | - src/jtag_rst_synch.sv 15 | - src/jtag_sync.sv 16 | - src/tap_top.v 17 | 18 | - target: test 19 | include_dirs: 20 | - testbench 21 | files: 22 | # - testbench/top_tb_jtag.v obsolete and broken 23 | - testbench/tb_jtag.sv 24 | -------------------------------------------------------------------------------- /testbench/compile.tcl: -------------------------------------------------------------------------------- 1 | # This script was generated automatically by bender. 2 | set ROOT "/home/balasr/projects/jtag_pulp" 3 | 4 | vlog -incr -sv \ 5 | +acc \ 6 | +define+TARGET_SIMULATION \ 7 | +define+TARGET_TEST \ 8 | +define+TARGET_VSIM \ 9 | "$ROOT/src/bscell.sv" \ 10 | "$ROOT/src/jtag_axi_wrap.sv" \ 11 | "$ROOT/src/jtag_enable.sv" \ 12 | "$ROOT/src/jtag_enable_synch.sv" \ 13 | "$ROOT/src/jtagreg.sv" \ 14 | "$ROOT/src/jtag_rst_synch.sv" \ 15 | "$ROOT/src/jtag_sync.sv" \ 16 | "$ROOT/src/tap_top.v" 17 | 18 | vlog -incr -sv \ 19 | +acc \ 20 | +define+TARGET_SIMULATION \ 21 | +define+TARGET_TEST \ 22 | +define+TARGET_VSIM \ 23 | "+incdir+$ROOT/testbench" \ 24 | "$ROOT/testbench/tb_jtag.sv" 25 | -------------------------------------------------------------------------------- /src/jtag_sync.sv: -------------------------------------------------------------------------------- 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 | module jtag_sync 12 | ( 13 | input logic clk_i, 14 | input logic rst_ni, 15 | input logic tosynch, 16 | output logic synched 17 | ); 18 | 19 | logic synch1,synch2,synch3; 20 | 21 | always_ff @(posedge clk_i, negedge rst_ni) 22 | begin 23 | if (~rst_ni) begin 24 | synch1 <= 1'b0; 25 | synch2 <= 1'b0; 26 | synch3 <= 1'b0; 27 | synched <= 1'b0; 28 | end 29 | else begin 30 | synch1 <= tosynch; 31 | synch2 <= synch1; 32 | synch3 <= synch2; 33 | synched<= synch3; 34 | end 35 | end 36 | 37 | 38 | endmodule // jtag_sync 39 | -------------------------------------------------------------------------------- /src/jtag_enable_synch.sv: -------------------------------------------------------------------------------- 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 | module jtag_enable_synch 12 | ( 13 | input logic clk_i, 14 | input logic rst_ni, 15 | input logic tck, 16 | output logic enable 17 | ); 18 | 19 | logic tck1,tck2,tck3; 20 | 21 | always_ff @(negedge rst_ni, posedge clk_i) 22 | begin 23 | if (~rst_ni) 24 | begin 25 | tck1 <= 1'b0; 26 | tck2 <= 1'b0; 27 | tck3 <= 1'b0; 28 | end 29 | else 30 | begin 31 | tck1 <= tck; 32 | tck2 <= tck1; 33 | tck3 <= tck2; 34 | end 35 | end 36 | 37 | assign enable = ~tck3 & tck2; 38 | 39 | endmodule // jtag_enable_synch 40 | 41 | -------------------------------------------------------------------------------- /testbench/Makefile: -------------------------------------------------------------------------------- 1 | # Permission to use, copy, modify, and/or distribute this software for any 2 | # purpose with or without fee is hereby granted, provided that the above 3 | # copyright notice and this permission notice appear in all copies. 4 | # 5 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 6 | # REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 7 | # AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 8 | # INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 9 | # LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 10 | # OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 11 | # PERFORMANCE OF THIS SOFTWARE. 12 | 13 | # Author: Robert Balas (balasr@iis.ee.ethz.ch) 14 | 15 | VSIM = vsim 16 | VSIM_FLAGS = -c +debug -do "run -a; quit -code [coverage attribute -name TESTSTATUS -concise]" 17 | VLOG_FLAGS = +acc 18 | 19 | BENDER = bender 20 | 21 | 22 | .PHONY: build clean run 23 | 24 | compile.tcl: ../Bender.yml 25 | $(BENDER) script vsim -t test --vlog-arg="$(VLOG_FLAGS)" > $@ 26 | 27 | build: compile.tcl 28 | $(VSIM) -c -do 'source compile.tcl; quit' 29 | 30 | run: 31 | $(VSIM) work.tb_jtag $(VSIM_FLAGS) 32 | 33 | clean: 34 | rm -rf work transcript compile.tcl 35 | -------------------------------------------------------------------------------- /src/jtag_rst_synch.sv: -------------------------------------------------------------------------------- 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 | module jtag_rst_synch 12 | ( 13 | input logic clk_i, 14 | input logic trst_ni, 15 | output logic rst_sync, 16 | input logic test_mode_i, 17 | input logic rst_ni 18 | ); 19 | 20 | logic trst1,trst2,trst3,trst4,trst5; 21 | 22 | always_ff @(posedge clk_i, negedge trst_ni) 23 | begin 24 | if (~trst_ni) begin 25 | trst1 <= 1'b0; 26 | trst2 <= 1'b0; 27 | trst3 <= 1'b0; 28 | trst4 <= 1'b0; 29 | trst5 <= 1'b0; 30 | end 31 | else begin 32 | trst1 <= trst_ni; 33 | trst2 <= trst1; 34 | trst3 <= trst2; 35 | trst4 <= trst3; 36 | trst5 <= trst4; 37 | end 38 | end 39 | 40 | assign rst_sync = (test_mode_i) ? rst_ni : trst5 & trst_ni; 41 | 42 | 43 | endmodule // jtag_rst_synch 44 | 45 | -------------------------------------------------------------------------------- /src/bscell.sv: -------------------------------------------------------------------------------- 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 | module bscell 12 | ( 13 | input logic clk_i, 14 | input logic rst_ni, 15 | input logic mode_i, 16 | input logic enable_i, 17 | input logic shift_dr_i, 18 | input logic capture_dr_i, 19 | input logic update_dr_i, 20 | input logic scan_in_i, 21 | input logic jtagreg_in_i, 22 | output logic scan_out_o, 23 | output logic jtagreg_out_o 24 | ); 25 | 26 | logic r_dataout; 27 | logic r_datasample; 28 | logic s_datasample_next; 29 | 30 | always_ff @(negedge rst_ni, posedge clk_i) 31 | begin 32 | if (~rst_ni) 33 | begin 34 | r_datasample <= 1'b0; 35 | r_dataout <= 1'b0; 36 | end 37 | else 38 | begin 39 | if ((shift_dr_i | capture_dr_i) & enable_i) 40 | r_datasample <= s_datasample_next; 41 | if (update_dr_i & enable_i) 42 | r_dataout <= r_datasample; 43 | end 44 | end 45 | 46 | assign s_datasample_next = (shift_dr_i) ? scan_in_i : jtagreg_in_i; 47 | assign jtagreg_out_o = (mode_i) ? r_dataout : jtagreg_in_i; 48 | assign scan_out_o = r_datasample; 49 | 50 | endmodule 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/jtag_enable.sv: -------------------------------------------------------------------------------- 1 | module jtag_enable 2 | ( 3 | input logic capture_syn_i, 4 | input logic shift_syn_i, 5 | input logic update_syn_i, 6 | 7 | input logic enable_i, 8 | 9 | input logic axireg_sel_syn_i, 10 | input logic bbmuxreg_sel_syn_i, 11 | input logic clkgatereg_sel_syn_i, 12 | input logic confreg_sel_syn_i, 13 | 14 | output logic axireg_capture_syn_o, 15 | output logic axireg_shift_syn_o, 16 | output logic axireg_update_syn_o, 17 | output logic bbmuxreg_capture_syn_o, 18 | output logic bbmuxreg_shift_syn_o, 19 | output logic bbmuxreg_update_syn_o, 20 | output logic clkgatereg_capture_syn_o, 21 | output logic clkgatereg_shift_syn_o, 22 | output logic clkgatereg_update_syn_o, 23 | output logic confreg_capture_syn_o, 24 | output logic confreg_shift_syn_o, 25 | output logic confreg_update_syn_o, 26 | 27 | output logic update_enable_o 28 | 29 | ); 30 | 31 | assign axireg_capture_syn_o = axireg_sel_syn_i & capture_syn_i; 32 | assign axireg_shift_syn_o = axireg_sel_syn_i & shift_syn_i; 33 | assign axireg_update_syn_o = axireg_sel_syn_i & update_syn_i; 34 | 35 | assign bbmuxreg_capture_syn_o = bbmuxreg_sel_syn_i & capture_syn_i; 36 | assign bbmuxreg_shift_syn_o = bbmuxreg_sel_syn_i & shift_syn_i; 37 | assign bbmuxreg_update_syn_o = bbmuxreg_sel_syn_i & update_syn_i; 38 | 39 | assign clkgatereg_capture_syn_o = clkgatereg_sel_syn_i & capture_syn_i; 40 | assign clkgatereg_shift_syn_o = clkgatereg_sel_syn_i & shift_syn_i; 41 | assign clkgatereg_update_syn_o = clkgatereg_sel_syn_i & update_syn_i; 42 | 43 | assign confreg_capture_syn_o = confreg_sel_syn_i & capture_syn_i; 44 | assign confreg_shift_syn_o = confreg_sel_syn_i & shift_syn_i; 45 | assign confreg_update_syn_o = confreg_sel_syn_i & update_syn_i; 46 | 47 | assign update_enable_o = enable_i & update_syn_i; 48 | 49 | endmodule -------------------------------------------------------------------------------- /src/jtagreg.sv: -------------------------------------------------------------------------------- 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 | module jtagreg 12 | #( 13 | parameter JTAGREGSIZE = 96, 14 | parameter SYNC = 1 15 | ) 16 | ( 17 | input logic clk_i, 18 | input logic rst_ni, // already synched 19 | input logic enable_i, // rising edge of tck 20 | input logic capture_dr_i,// capture&sel 21 | input logic shift_dr_i, // shift&sel 22 | input logic update_dr_i, // update&sel 23 | input logic [JTAGREGSIZE-1:0] jtagreg_in_i, 24 | input logic mode_i, 25 | input logic scan_in_i, 26 | output logic scan_out_o, 27 | output logic [JTAGREGSIZE-1:0] jtagreg_out_o 28 | ); 29 | 30 | logic [JTAGREGSIZE-2:0] s_scanbit; 31 | 32 | logic scan_in_syn; 33 | 34 | 35 | bscell reg_bit_last 36 | ( 37 | .clk_i(clk_i), 38 | .rst_ni(rst_ni), 39 | .mode_i(mode_i), 40 | .enable_i(enable_i), 41 | .shift_dr_i(shift_dr_i), 42 | .capture_dr_i(capture_dr_i), 43 | .update_dr_i(update_dr_i), 44 | .scan_in_i(scan_in_syn), 45 | .jtagreg_in_i(jtagreg_in_i[JTAGREGSIZE-1]), 46 | .scan_out_o(s_scanbit[0]), 47 | .jtagreg_out_o(jtagreg_out_o[JTAGREGSIZE-1]) 48 | ); 49 | 50 | generate 51 | for (genvar i=1;i 0) 153 | data_out[i-1] = jtag_tdo; 154 | jtag_tck = #halfperiod 1'b0; 155 | if (i == (number - 1) ) 156 | jtag_tms = 1'b1; //exit1DR 157 | else 158 | jtag_tms = 1'b0; //shiftDR 159 | jtag_tdi = data[i]; 160 | end 161 | jtag_tck = #halfperiod 1'b1; 162 | data_out[number-1] = jtag_tdo; 163 | jtag_tck = #halfperiod 1'b0; 164 | jtag_tms = 1'b0; //pauseDR 165 | jtag_tdi = 1'b0; 166 | jtag_tck = #halfperiod 1'b1; 167 | jtag_tck = #halfperiod 1'b0; 168 | jtag_tms = 1'b1; //exit2DR 169 | jtag_tck = #halfperiod 1'b1; 170 | jtag_tck = #halfperiod 1'b0; 171 | jtag_tms = 1'b1; //updateDR 172 | jtag_tck = #halfperiod 1'b1; 173 | jtag_tck = #halfperiod 1'b0; 174 | jtag_tms = 1'b0; //run-test-idle 175 | jtag_tck = #halfperiod 1'b1; 176 | jtag_tck = #halfperiod 1'b0; 177 | jtag_tms = 1'b0; //run-test-idle 178 | jtag_tck = #halfperiod 1'b1; 179 | jtag_tck = #halfperiod 1'b0; 180 | jtag_tms = 1'b0; //run-test-idle 181 | 182 | jtag_tck = #halfperiod 1'b0; 183 | if (display == 1) 184 | $display("Data Captured from register: %0h",data_out); 185 | end 186 | 187 | endtask 188 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | SOLDERPAD HARDWARE LICENSE version 0.51 2 | 3 | This license is based closely on the Apache License Version 2.0, but is not 4 | approved or endorsed by the Apache Foundation. A copy of the non-modified 5 | Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0. 6 | 7 | As this license is not currently OSI or FSF approved, the Licensor permits any 8 | Work licensed under this License, at the option of the Licensee, to be treated 9 | as licensed under the Apache License Version 2.0 (which is so approved). 10 | 11 | This License is licensed under the terms of this License and in particular 12 | clause 7 below (Disclaimer of Warranties) applies in relation to its use. 13 | 14 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 15 | 16 | 1. Definitions. 17 | 18 | "License" shall mean the terms and conditions for use, reproduction, and 19 | distribution as defined by Sections 1 through 9 of this document. 20 | 21 | "Licensor" shall mean the Rights owner or entity authorized by the Rights owner 22 | that is granting the License. 23 | 24 | "Legal Entity" shall mean the union of the acting entity and all other entities 25 | that control, are controlled by, or are under common control with that entity. 26 | For the purposes of this definition, "control" means (i) the power, direct or 27 | indirect, to cause the direction or management of such entity, whether by 28 | contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the 29 | outstanding shares, or (iii) beneficial ownership of such entity. 30 | 31 | "You" (or "Your") shall mean an individual or Legal Entity exercising 32 | permissions granted by this License. 33 | 34 | "Rights" means copyright and any similar right including design right (whether 35 | registered or unregistered), semiconductor topography (mask) rights and 36 | database rights (but excluding Patents and Trademarks). 37 | 38 | "Source" form shall mean the preferred form for making modifications, including 39 | but not limited to source code, net lists, board layouts, CAD files, 40 | documentation source, and configuration files. 41 | 42 | "Object" form shall mean any form resulting from mechanical transformation or 43 | translation of a Source form, including but not limited to compiled object 44 | code, generated documentation, the instantiation of a hardware design and 45 | conversions to other media types, including intermediate forms such as 46 | bytecodes, FPGA bitstreams, artwork and semiconductor topographies (mask 47 | works). 48 | 49 | "Work" shall mean the work of authorship, whether in Source form or other 50 | Object form, made available under the License, as indicated by a Rights notice 51 | that is included in or attached to the work (an example is provided in the 52 | Appendix below). 53 | 54 | "Derivative Works" shall mean any work, whether in Source or Object form, that 55 | is based on (or derived from) the Work and for which the editorial revisions, 56 | annotations, elaborations, or other modifications represent, as a whole, an 57 | original work of authorship. For the purposes of this License, Derivative Works 58 | shall not include works that remain separable from, or merely link (or bind by 59 | name) or physically connect to or interoperate with the interfaces of, the Work 60 | and Derivative Works thereof. 61 | 62 | "Contribution" shall mean any design or work of authorship, including the 63 | original version of the Work and any modifications or additions to that Work or 64 | Derivative Works thereof, that is intentionally submitted to Licensor for 65 | inclusion in the Work by the Rights owner or by an individual or Legal Entity 66 | authorized to submit on behalf of the Rights owner. For the purposes of this 67 | definition, "submitted" means any form of electronic, verbal, or written 68 | communication sent to the Licensor or its representatives, including but not 69 | limited to communication on electronic mailing lists, source code control 70 | systems, and issue tracking systems that are managed by, or on behalf of, the 71 | Licensor for the purpose of discussing and improving the Work, but excluding 72 | communication that is conspicuously marked or otherwise designated in writing 73 | by the Rights owner as "Not a Contribution." 74 | 75 | "Contributor" shall mean Licensor and any individual or Legal Entity on behalf 76 | of whom a Contribution has been received by Licensor and subsequently 77 | incorporated within the Work. 78 | 79 | 2. Grant of License. Subject to the terms and conditions of this License, each 80 | Contributor hereby grants to You a perpetual, worldwide, non-exclusive, 81 | no-charge, royalty-free, irrevocable license under the Rights to reproduce, 82 | prepare Derivative Works of, publicly display, publicly perform, sublicense, 83 | and distribute the Work and such Derivative Works in Source or Object form and 84 | do anything in relation to the Work as if the Rights did not exist. 85 | 86 | 3. Grant of Patent License. Subject to the terms and conditions of this 87 | License, each Contributor hereby grants to You a perpetual, worldwide, 88 | non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this 89 | section) patent license to make, have made, use, offer to sell, sell, import, 90 | and otherwise transfer the Work, where such license applies only to those 91 | patent claims licensable by such Contributor that are necessarily infringed by 92 | their Contribution(s) alone or by combination of their Contribution(s) with the 93 | Work to which such Contribution(s) was submitted. If You institute patent 94 | litigation against any entity (including a cross-claim or counterclaim in a 95 | lawsuit) alleging that the Work or a Contribution incorporated within the Work 96 | constitutes direct or contributory patent infringement, then any patent 97 | licenses granted to You under this License for that Work shall terminate as of 98 | the date such litigation is filed. 99 | 100 | 4. Redistribution. You may reproduce and distribute copies of the Work or 101 | Derivative Works thereof in any medium, with or without modifications, and in 102 | Source or Object form, provided that You meet the following conditions: 103 | 104 | You must give any other recipients of the Work or Derivative Works a copy 105 | of this License; and 106 | 107 | You must cause any modified files to carry prominent notices stating that 108 | You changed the files; and 109 | 110 | You must retain, in the Source form of any Derivative Works that You 111 | distribute, all copyright, patent, trademark, and attribution notices from 112 | the Source form of the Work, excluding those notices that do not pertain to 113 | any part of the Derivative Works; and 114 | 115 | If the Work includes a "NOTICE" text file as part of its distribution, then 116 | any Derivative Works that You distribute must include a readable copy of 117 | the attribution notices contained within such NOTICE file, excluding those 118 | notices that do not pertain to any part of the Derivative Works, in at 119 | least one of the following places: within a NOTICE text file distributed as 120 | part of the Derivative Works; within the Source form or documentation, if 121 | provided along with the Derivative Works; or, within a display generated by 122 | the Derivative Works, if and wherever such third-party notices normally 123 | appear. The contents of the NOTICE file are for informational purposes only 124 | and do not modify the License. You may add Your own attribution notices 125 | within Derivative Works that You distribute, alongside or as an addendum to 126 | the NOTICE text from the Work, provided that such additional attribution 127 | notices cannot be construed as modifying the License. You may add Your own 128 | copyright statement to Your modifications and may provide additional or 129 | different license terms and conditions for use, reproduction, or 130 | distribution of Your modifications, or for any such Derivative Works as a 131 | whole, provided Your use, reproduction, and distribution of the Work 132 | otherwise complies with the conditions stated in this License. 133 | 134 | 5. Submission of Contributions. Unless You explicitly state otherwise, any 135 | Contribution intentionally submitted for inclusion in the Work by You to the 136 | Licensor shall be under the terms and conditions of this License, without any 137 | additional terms or conditions. Notwithstanding the above, nothing herein shall 138 | supersede or modify the terms of any separate license agreement you may have 139 | executed with Licensor regarding such Contributions. 140 | 141 | 6. Trademarks. This License does not grant permission to use the trade names, 142 | trademarks, service marks, or product names of the Licensor, except as required 143 | for reasonable and customary use in describing the origin of the Work and 144 | reproducing the content of the NOTICE file. 145 | 146 | 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in 147 | writing, Licensor provides the Work (and each Contributor provides its 148 | Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 149 | KIND, either express or implied, including, without limitation, any warranties 150 | or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 151 | PARTICULAR PURPOSE. You are solely responsible for determining the 152 | appropriateness of using or redistributing the Work and assume any risks 153 | associated with Your exercise of permissions under this License. 154 | 155 | 8. Limitation of Liability. In no event and under no legal theory, whether in 156 | tort (including negligence), contract, or otherwise, unless required by 157 | applicable law (such as deliberate and grossly negligent acts) or agreed to in 158 | writing, shall any Contributor be liable to You for damages, including any 159 | direct, indirect, special, incidental, or consequential damages of any 160 | character arising as a result of this License or out of the use or inability to 161 | use the Work (including but not limited to damages for loss of goodwill, work 162 | stoppage, computer failure or malfunction, or any and all other commercial 163 | damages or losses), even if such Contributor has been advised of the 164 | possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing the Work or 167 | Derivative Works thereof, You may choose to offer, and charge a fee for, 168 | acceptance of support, warranty, indemnity, or other liability obligations 169 | and/or rights consistent with this License. However, in accepting such 170 | obligations, You may act only on Your own behalf and on Your sole 171 | responsibility, not on behalf of any other Contributor, and only if You agree 172 | to indemnify, defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason of your 174 | accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | -------------------------------------------------------------------------------- /testbench/tb_jtag.sv: -------------------------------------------------------------------------------- 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 | 12 | module tb_jtag(); 13 | 14 | timeunit 100ns; 15 | timeprecision 1ns; 16 | 17 | localparam int unsigned JTAG_PERIOD = 1000; 18 | localparam int unsigned JTAG_IRLEN = 5; 19 | 20 | localparam int unsigned REG1_SIZE = 10; 21 | localparam int unsigned REG2_SIZE = 11; 22 | localparam int unsigned REG3_SIZE = 12; 23 | 24 | localparam IDCODE = 5'b00010; 25 | localparam REG1 = 5'b00100; 26 | localparam REG2 = 5'b00101; 27 | localparam REG3 = 5'b00110; 28 | localparam REG4 = 5'b00111; 29 | localparam REG5 = 5'b01000; 30 | localparam REG6 = 5'b01001; 31 | localparam BYPASS = 5'b11111; 32 | 33 | logic clk; 34 | logic rst_n; 35 | 36 | logic jtag_trst; 37 | logic jtag_tck; 38 | logic jtag_tms; 39 | logic jtag_tdi; 40 | 41 | logic jtag_tdo; 42 | 43 | logic s_tap_shiftdr; 44 | logic s_tap_updatedr; 45 | logic s_tap_capturedr; 46 | logic s_tap_reg1_sel; 47 | logic s_tap_reg2_sel; 48 | logic s_tap_reg3_sel; 49 | logic s_tap_tdo; 50 | logic s_tap_reg1_tdi; 51 | logic s_tap_reg2_tdi; 52 | logic s_tap_reg3_tdi; 53 | 54 | logic s_mode; 55 | 56 | logic [REG1_SIZE-1:0] s_reg1_in; 57 | logic [REG2_SIZE-1:0] s_reg2_in; 58 | logic [REG3_SIZE-1:0] s_reg3_in; 59 | 60 | logic [REG1_SIZE-1:0] s_reg1_out; 61 | logic [REG2_SIZE-1:0] s_reg2_out; 62 | logic [REG3_SIZE-1:0] s_reg3_out; 63 | 64 | assign s_reg1_in = 'hAB; 65 | assign s_reg2_in = 'hCD; 66 | assign s_reg3_in = 'hEF; 67 | 68 | tap_top u_tap ( 69 | // jtag 70 | .tms_i(jtag_tms), 71 | .tck_i(jtag_tck), 72 | .rst_ni(~jtag_trst), 73 | .td_i(jtag_tdi), 74 | .td_o(jtag_tdo), 75 | // tap states 76 | .shift_dr_o(s_tap_shiftdr), 77 | .update_dr_o(s_tap_updatedr), 78 | .capture_dr_o(s_tap_capturedr), 79 | // select signals for boundary scan or mbist 80 | .memory_sel_o(s_tap_reg1_sel), 81 | .fifo_sel_o(s_tap_reg2_sel), 82 | .confreg_sel_o(s_tap_reg3_sel), 83 | // tdo signal connected to tdi of sub modules 84 | .scan_in_o(s_tap_tdo), 85 | // tdi signals from sub modules 86 | .memory_out_i(s_tap_reg1_tdi), 87 | .fifo_out_i(s_tap_reg2_tdi), 88 | .confreg_out_i(s_tap_reg3_tdi) 89 | ); 90 | 91 | jtagreg #( 92 | .JTAGREGSIZE(REG1_SIZE), 93 | .SYNC(0) 94 | ) i_jtagreg1 ( 95 | .clk_i(jtag_tck), 96 | .rst_ni(~jtag_trst), 97 | .enable_i(s_tap_reg1_sel), 98 | .capture_dr_i(s_tap_capturedr), 99 | .shift_dr_i(s_tap_shiftdr), 100 | .update_dr_i(s_tap_updatedr), 101 | .jtagreg_in_i(s_reg1_in), 102 | .mode_i(s_mode), 103 | .scan_in_i(s_tap_tdo), 104 | .scan_out_o(s_tap_reg1_tdi), 105 | .jtagreg_out_o(s_reg1_out) 106 | ); 107 | 108 | jtagreg #( 109 | .JTAGREGSIZE(REG2_SIZE), 110 | .SYNC(0) 111 | ) i_jtagreg2 ( 112 | .clk_i(jtag_tck), 113 | .rst_ni(~jtag_trst), 114 | .enable_i(s_tap_reg2_sel), 115 | 116 | .capture_dr_i(s_tap_capturedr), 117 | .shift_dr_i(s_tap_shiftdr), 118 | .update_dr_i(s_tap_updatedr), 119 | .jtagreg_in_i(s_reg2_in), 120 | .mode_i(s_mode), 121 | .scan_in_i(s_tap_tdo), 122 | .scan_out_o(s_tap_reg2_tdi), 123 | .jtagreg_out_o(s_reg2_out) 124 | ); 125 | 126 | jtagreg #( 127 | .JTAGREGSIZE(REG3_SIZE), 128 | .SYNC(0) 129 | ) i_jtagreg3 ( 130 | .clk_i(jtag_tck), 131 | .rst_ni(~jtag_trst), 132 | .enable_i(s_tap_reg3_sel), 133 | .capture_dr_i(s_tap_capturedr), 134 | .shift_dr_i(s_tap_shiftdr), 135 | .update_dr_i(s_tap_updatedr), 136 | .jtagreg_in_i(s_reg3_in), 137 | .mode_i(s_mode), 138 | .scan_in_i(s_tap_tdo), 139 | .scan_out_o(s_tap_reg3_tdi), 140 | .jtagreg_out_o(s_reg3_out) 141 | ); 142 | 143 | // improve time format 144 | initial begin: timing_format 145 | $timeformat(-9, 0, "ns", 9); 146 | end: timing_format 147 | 148 | // actual test sequence 149 | initial begin 150 | logic [127:0] dr_out; 151 | rst_n = 1; 152 | clk = 0; 153 | s_mode = 0; 154 | 155 | jtag_trst = 1'b0; 156 | jtag_tdi = 1'b0; 157 | jtag_tms = 1'b0; 158 | jtag_tck = 1'b0; 159 | 160 | #1 rst_n = 0; 161 | #100 rst_n = 1; 162 | 163 | jtag_hard_rst(); 164 | jtag_rst(); 165 | 166 | #10000 s_mode = 1'b1; 167 | #10000 s_mode = 1'b0; 168 | 169 | jtag_selectir(REG1); 170 | jtag_senddr(REG1_SIZE, 'h11, dr_out); 171 | assert (dr_out === s_reg1_in) 172 | else 173 | $error("dr register of tap1 contains: %0h expected: %0h", 174 | dr_out, s_reg1_in); 175 | 176 | jtag_selectir(REG2); 177 | jtag_senddr(REG2_SIZE, 'h22, dr_out); 178 | assert (dr_out === s_reg2_in) 179 | else 180 | $error("dr register of tap2 contains: %0h expected: %0h", 181 | dr_out, s_reg2_in); 182 | 183 | 184 | jtag_selectir(REG3); 185 | jtag_senddr(REG3_SIZE, 'h33, dr_out); 186 | assert (dr_out === s_reg3_in) 187 | else 188 | $error("dr register of tap3 contains: %0h expected: %0h", 189 | dr_out, s_reg3_in); 190 | 191 | 192 | #10000 s_mode = 1'b1; 193 | #10000 s_mode = 1'b0; 194 | 195 | $stop(); 196 | end 197 | 198 | // generate a clock 199 | always 200 | #1 clk = ~clk; 201 | 202 | 203 | // jtag commands 204 | task jtag_rst; 205 | integer halfperiod; 206 | begin 207 | if ($test$plusargs("debug")) 208 | $display("%t: rst start", $time); 209 | halfperiod = JTAG_PERIOD / 2; 210 | jtag_tck = 1'b0; 211 | jtag_tms = 1'b0; 212 | jtag_tck = #halfperiod 1'b1; 213 | jtag_tck = #halfperiod 1'b0; 214 | jtag_tms = 1'b1; 215 | jtag_tck = #halfperiod 1'b1; 216 | jtag_tck = #halfperiod 1'b0; 217 | jtag_tms = 1'b1; 218 | jtag_tck = #halfperiod 1'b1; 219 | jtag_tck = #halfperiod 1'b0; 220 | jtag_tms = 1'b1; 221 | jtag_tck = #halfperiod 1'b1; 222 | jtag_tck = #halfperiod 1'b0; 223 | jtag_tms = 1'b1; 224 | jtag_tck = #halfperiod 1'b1; 225 | jtag_tck = #halfperiod 1'b0; 226 | jtag_tms = 1'b0; 227 | jtag_tck = #halfperiod 1'b1; 228 | jtag_tck = #halfperiod 1'b0; 229 | jtag_tms = 1'b0; 230 | jtag_tck = #halfperiod 1'b1; 231 | jtag_tck = #halfperiod 1'b0; 232 | jtag_tms = 1'b0; 233 | jtag_tck = #halfperiod 1'b0; 234 | if ($test$plusargs("debug")) 235 | $display("%t: rst done", $time); 236 | end 237 | endtask 238 | 239 | task jtag_hard_rst; 240 | integer halfperiod; 241 | begin 242 | if ($test$plusargs("debug")) 243 | $display("%t: hard rst start", $time); 244 | 245 | halfperiod = JTAG_PERIOD / 2; 246 | jtag_tck = 1'b0; 247 | jtag_trst = 1'b0; 248 | jtag_tck = #halfperiod 1'b1; 249 | jtag_tck = #halfperiod 1'b0; 250 | jtag_trst = 1'b1; 251 | jtag_tck = #halfperiod 1'b1; 252 | jtag_tck = #halfperiod 1'b0; 253 | jtag_trst = 1'b1; 254 | jtag_tck = #halfperiod 1'b1; 255 | jtag_tck = #halfperiod 1'b0; 256 | jtag_trst = 1'b1; 257 | jtag_tck = #halfperiod 1'b1; 258 | jtag_tck = #halfperiod 1'b0; 259 | jtag_trst = 1'b1; 260 | jtag_tck = #halfperiod 1'b1; 261 | jtag_tck = #halfperiod 1'b0; 262 | jtag_trst = 1'b0; 263 | jtag_tck = #halfperiod 1'b1; 264 | jtag_tck = #halfperiod 1'b0; 265 | jtag_trst = 1'b0; 266 | jtag_tck = #halfperiod 1'b1; 267 | jtag_tck = #halfperiod 1'b0; 268 | jtag_trst = 1'b0; 269 | jtag_tck = #halfperiod 1'b0; 270 | if ($test$plusargs("debug")) 271 | $display("%t: hard rst end", $time); 272 | 273 | end 274 | endtask 275 | 276 | task jtag_selectir ( 277 | input [JTAG_IRLEN-1:0] instruction 278 | ); 279 | integer halfperiod; 280 | integer i; 281 | begin 282 | if ($test$plusargs("debug")) 283 | $display("%t: select ir start, ir=0x%0h", $time, instruction); 284 | 285 | halfperiod = JTAG_PERIOD / 2; 286 | jtag_tck = 1'b0; // TODO: buggy? 287 | jtag_tck = #halfperiod 1'b1; 288 | jtag_tck = #halfperiod 1'b0; 289 | jtag_tms = 1'b1; //selectDR 290 | jtag_tck = #halfperiod 1'b1; 291 | jtag_tck = #halfperiod 1'b0; 292 | jtag_tms = 1'b1; //selectIR 293 | jtag_tck = #halfperiod 1'b1; 294 | jtag_tck = #halfperiod 1'b0; 295 | jtag_tms = 1'b0; //captureIR 296 | jtag_tck = #halfperiod 1'b1; 297 | jtag_tck = #halfperiod 1'b0; 298 | jtag_tms = 1'b0; //shiftIR 299 | if ($test$plusargs("debug")) 300 | $display("%t: select ir capture start", $time); 301 | for (i=0 ; i < JTAG_IRLEN ; i=i+1) 302 | begin 303 | jtag_tck = #halfperiod 1'b1; 304 | jtag_tck = #halfperiod 1'b0; 305 | if (i == (JTAG_IRLEN - 1) ) 306 | jtag_tms = 1'b1; //exit1IR 307 | else 308 | jtag_tms = 1'b0; //shiftIR 309 | jtag_tdi = instruction[i]; 310 | end 311 | if ($test$plusargs("debug")) 312 | $display("%t: select ir capture end", $time); 313 | jtag_tck = #halfperiod 1'b1; 314 | jtag_tck = #halfperiod 1'b0; 315 | jtag_tms = 1'b0; //pauseIR 316 | jtag_tdi = 1'b0; 317 | jtag_tck = #halfperiod 1'b1; 318 | jtag_tck = #halfperiod 1'b0; 319 | jtag_tms = 1'b1; //exit2IR 320 | jtag_tck = #halfperiod 1'b1; 321 | jtag_tck = #halfperiod 1'b0; 322 | jtag_tms = 1'b1; //updateIR 323 | jtag_tck = #halfperiod 1'b1; 324 | jtag_tck = #halfperiod 1'b0; 325 | jtag_tms = 1'b0; //run-test-idle 326 | jtag_tck = #halfperiod 1'b1; 327 | jtag_tck = #halfperiod 1'b0; 328 | jtag_tms = 1'b0; //run-test-idle 329 | jtag_tck = #halfperiod 1'b1; 330 | jtag_tck = #halfperiod 1'b0; 331 | jtag_tms = 1'b0; //run-test-idle 332 | 333 | jtag_tck = #halfperiod 1'b0; 334 | if ($test$plusargs("debug")) 335 | $display("%t: select ir end", $time); 336 | 337 | end 338 | endtask 339 | 340 | task jtag_senddr ( 341 | input integer number, 342 | input [127:0] data, 343 | output [127:0] dr_out 344 | ); 345 | integer halfperiod; 346 | integer i; 347 | logic [127:0] data_out; 348 | begin 349 | if ($test$plusargs("debug")) 350 | $display("%t: select dr start, dr=0x%0h", $time, data); 351 | 352 | data_out = 0; 353 | halfperiod = JTAG_PERIOD / 2; 354 | jtag_tck = 1'b0; 355 | jtag_tck = #halfperiod 1'b1; 356 | jtag_tck = #halfperiod 1'b0; 357 | jtag_tms = 1'b1; //selectDR 358 | jtag_tck = #halfperiod 1'b1; 359 | jtag_tck = #halfperiod 1'b0; 360 | jtag_tms = 1'b0; //captureDR 361 | jtag_tck = #halfperiod 1'b1; 362 | jtag_tck = #halfperiod 1'b0; 363 | jtag_tms = 1'b0; //shiftNR 364 | for (i=0 ; i < number ; i=i+1) 365 | begin 366 | jtag_tck = #halfperiod 1'b1; 367 | if (i > 0) 368 | data_out[i-1] = jtag_tdo; 369 | jtag_tck = #halfperiod 1'b0; 370 | if (i == (number - 1) ) 371 | jtag_tms = 1'b1; //exit1DR 372 | else 373 | jtag_tms = 1'b0; //shiftDR 374 | jtag_tdi = data[i]; 375 | end 376 | jtag_tck = #halfperiod 1'b1; 377 | data_out[number-1] = jtag_tdo; 378 | jtag_tck = #halfperiod 1'b0; 379 | jtag_tms = 1'b0; //pauseDR 380 | jtag_tdi = 1'b0; 381 | jtag_tck = #halfperiod 1'b1; 382 | jtag_tck = #halfperiod 1'b0; 383 | jtag_tms = 1'b1; //exit2DR 384 | jtag_tck = #halfperiod 1'b1; 385 | jtag_tck = #halfperiod 1'b0; 386 | jtag_tms = 1'b1; //updateDR 387 | jtag_tck = #halfperiod 1'b1; 388 | jtag_tck = #halfperiod 1'b0; 389 | jtag_tms = 1'b0; //run-test-idle 390 | jtag_tck = #halfperiod 1'b1; 391 | jtag_tck = #halfperiod 1'b0; 392 | jtag_tms = 1'b0; //run-test-idle 393 | jtag_tck = #halfperiod 1'b1; 394 | jtag_tck = #halfperiod 1'b0; 395 | jtag_tms = 1'b0; //run-test-idle 396 | 397 | jtag_tck = #halfperiod 1'b0; 398 | dr_out = data_out; 399 | if ($test$plusargs("debug")) 400 | $display("%t: data captured from register: 0x%0h", $time, data_out); 401 | end 402 | 403 | endtask 404 | 405 | endmodule 406 | -------------------------------------------------------------------------------- /src/tap_top.v: -------------------------------------------------------------------------------- 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 | // synopsys translate_off 12 | //`include "timescale.v" 13 | // synopsys translate_on 14 | 15 | // Length of the Instruction register 16 | `define IR_LENGTH 5 17 | 18 | // Supported Instructions 19 | `define IDCODE 5'b00010 20 | `define REG1 5'b00100 21 | `define REG2 5'b00101 22 | `define REG3 5'b00110 23 | `define REG_CLK_BYP 5'b00111 24 | `define REG_OBSERV 5'b01000 25 | `define REG6 5'b01001 26 | `define BYPASS 5'b11111 27 | 28 | // Top module 29 | module tap_top #( 30 | // manufacturer = PULP Platform, part number = 0, version = 1 31 | parameter IDCODE_VALUE = 32'h10000db3 32 | )( 33 | // JTAG pads 34 | tms_i, 35 | tck_i, 36 | rst_ni, 37 | td_i, 38 | td_o, 39 | 40 | // TAP states 41 | shift_dr_o, 42 | update_dr_o, 43 | capture_dr_o, 44 | 45 | // Select signals for boundary scan or mbist 46 | memory_sel_o, 47 | fifo_sel_o, 48 | confreg_sel_o, 49 | clk_byp_sel_o, 50 | observ_sel_o, 51 | 52 | // TDO signal that is connected to TDI of sub-modules. 53 | scan_in_o, 54 | 55 | // TDI signals from sub-modules 56 | memory_out_i, // from reg1 module 57 | fifo_out_i, // from reg2 module 58 | confreg_out_i, // from reg3 module 59 | clk_byp_out_i, 60 | observ_out_i 61 | ); 62 | 63 | 64 | // JTAG pins 65 | input tms_i; // JTAG test mode select pad 66 | input tck_i; // JTAG test clock pad 67 | input rst_ni; // JTAG test reset pad 68 | input td_i; // JTAG test data input pad 69 | output td_o; // JTAG test data output pad 70 | //output tdo_padoe_o; // Output enable for JTAG test data output pad 71 | 72 | // TAP states 73 | output shift_dr_o; 74 | output update_dr_o; 75 | output capture_dr_o; 76 | 77 | // Select signals for boundary scan or mbist 78 | output memory_sel_o; 79 | output fifo_sel_o; 80 | output confreg_sel_o; 81 | output clk_byp_sel_o; 82 | output observ_sel_o; 83 | 84 | // TDO signal that is connected to TDI of sub-modules. 85 | output scan_in_o; 86 | 87 | // TDI signals from sub-modules 88 | input memory_out_i; // from reg1 module 89 | input fifo_out_i; // from reg2 module 90 | input confreg_out_i; // from reg4 module 91 | input clk_byp_out_i; 92 | input observ_out_i; 93 | 94 | 95 | // Registers 96 | reg test_logic_reset; 97 | reg run_test_idle; 98 | reg sel_dr_scan; 99 | reg capture_dr; 100 | reg shift_dr; 101 | reg exit1_dr; 102 | reg pause_dr; 103 | reg exit2_dr; 104 | reg update_dr; 105 | reg sel_ir_scan; 106 | reg capture_ir; 107 | reg shift_ir, shift_ir_neg; 108 | reg exit1_ir; 109 | reg pause_ir; 110 | reg exit2_ir; 111 | reg update_ir; 112 | reg idcode_sel; 113 | reg memory_sel; 114 | reg fifo_sel; 115 | reg confreg_sel; 116 | reg bypass_sel; 117 | 118 | reg clk_byp_sel; 119 | reg observ_sel; 120 | 121 | reg tdo_comb; 122 | reg td_o; 123 | //reg tdo_padoe_o; 124 | reg tms_q1, tms_q2, tms_q3, tms_q4; 125 | wire tms_reset; 126 | 127 | assign scan_in_o = td_i; 128 | assign shift_dr_o = shift_dr; 129 | assign update_dr_o = update_dr; 130 | assign capture_dr_o = capture_dr; 131 | 132 | assign memory_sel_o = memory_sel; 133 | assign fifo_sel_o = fifo_sel; 134 | assign confreg_sel_o = confreg_sel; 135 | 136 | assign clk_byp_sel_o = clk_byp_sel; 137 | assign observ_sel_o = observ_sel; 138 | 139 | 140 | always @ (posedge tck_i) 141 | begin 142 | tms_q1 <= tms_i; 143 | tms_q2 <= tms_q1; 144 | tms_q3 <= tms_q2; 145 | tms_q4 <= tms_q3; 146 | end 147 | 148 | 149 | assign tms_reset = tms_q1 & tms_q2 & tms_q3 & tms_q4 & tms_i; // 5 consecutive TMS=1 causes reset 150 | 151 | 152 | /********************************************************************************** 153 | * * 154 | * TAP State Machine: Fully JTAG compliant * 155 | * * 156 | **********************************************************************************/ 157 | 158 | // test_logic_reset state 159 | always @ (posedge tck_i or negedge rst_ni) 160 | begin 161 | if(~rst_ni) 162 | test_logic_reset<= 1'b1; 163 | else if (tms_reset) 164 | test_logic_reset<= 1'b1; 165 | else 166 | begin 167 | if(tms_i & (test_logic_reset | sel_ir_scan)) 168 | test_logic_reset<= 1'b1; 169 | else 170 | test_logic_reset<= 1'b0; 171 | end 172 | end 173 | 174 | // run_test_idle state 175 | always @ (posedge tck_i or negedge rst_ni) 176 | begin 177 | if(~rst_ni) 178 | run_test_idle<= 1'b0; 179 | else if (tms_reset) 180 | run_test_idle<= 1'b0; 181 | else 182 | if(~tms_i & (test_logic_reset | run_test_idle | update_dr | update_ir)) 183 | run_test_idle<= 1'b1; 184 | else 185 | run_test_idle<= 1'b0; 186 | end 187 | 188 | // sel_dr_scan state 189 | always @ (posedge tck_i or negedge rst_ni) 190 | begin 191 | if(~rst_ni) 192 | sel_dr_scan<= 1'b0; 193 | else if (tms_reset) 194 | sel_dr_scan<= 1'b0; 195 | else 196 | if(tms_i & (run_test_idle | update_dr | update_ir)) 197 | sel_dr_scan<= 1'b1; 198 | else 199 | sel_dr_scan<= 1'b0; 200 | end 201 | 202 | // capture_dr state 203 | always @ (posedge tck_i or negedge rst_ni) 204 | begin 205 | if(~rst_ni) 206 | capture_dr<= 1'b0; 207 | else if (tms_reset) 208 | capture_dr<= 1'b0; 209 | else 210 | if(~tms_i & sel_dr_scan) 211 | capture_dr<= 1'b1; 212 | else 213 | capture_dr<= 1'b0; 214 | end 215 | 216 | // shift_dr state 217 | always @ (posedge tck_i or negedge rst_ni) 218 | begin 219 | if(~rst_ni) 220 | shift_dr<= 1'b0; 221 | else if (tms_reset) 222 | shift_dr<= 1'b0; 223 | else 224 | if(~tms_i & (capture_dr | shift_dr | exit2_dr)) 225 | shift_dr<= 1'b1; 226 | else 227 | shift_dr<= 1'b0; 228 | end 229 | 230 | // exit1_dr state 231 | always @ (posedge tck_i or negedge rst_ni) 232 | begin 233 | if(~rst_ni) 234 | exit1_dr<= 1'b0; 235 | else if (tms_reset) 236 | exit1_dr<= 1'b0; 237 | else 238 | if(tms_i & (capture_dr | shift_dr)) 239 | exit1_dr<= 1'b1; 240 | else 241 | exit1_dr<= 1'b0; 242 | end 243 | 244 | // pause_dr state 245 | always @ (posedge tck_i or negedge rst_ni) 246 | begin 247 | if(~rst_ni) 248 | pause_dr<= 1'b0; 249 | else if (tms_reset) 250 | pause_dr<= 1'b0; 251 | else 252 | if(~tms_i & (exit1_dr | pause_dr)) 253 | pause_dr<= 1'b1; 254 | else 255 | pause_dr<= 1'b0; 256 | end 257 | 258 | // exit2_dr state 259 | always @ (posedge tck_i or negedge rst_ni) 260 | begin 261 | if(~rst_ni) 262 | exit2_dr<= 1'b0; 263 | else if (tms_reset) 264 | exit2_dr<= 1'b0; 265 | else 266 | if(tms_i & pause_dr) 267 | exit2_dr<= 1'b1; 268 | else 269 | exit2_dr<= 1'b0; 270 | end 271 | 272 | // update_dr state 273 | always @ (posedge tck_i or negedge rst_ni) 274 | begin 275 | if(~rst_ni) 276 | update_dr<= 1'b0; 277 | else if (tms_reset) 278 | update_dr<= 1'b0; 279 | else 280 | if(tms_i & (exit1_dr | exit2_dr)) 281 | update_dr<= 1'b1; 282 | else 283 | update_dr<= 1'b0; 284 | end 285 | 286 | // sel_ir_scan state 287 | always @ (posedge tck_i or negedge rst_ni) 288 | begin 289 | if(~rst_ni) 290 | sel_ir_scan<= 1'b0; 291 | else if (tms_reset) 292 | sel_ir_scan<= 1'b0; 293 | else 294 | if(tms_i & sel_dr_scan) 295 | sel_ir_scan<= 1'b1; 296 | else 297 | sel_ir_scan<= 1'b0; 298 | end 299 | 300 | // capture_ir state 301 | always @ (posedge tck_i or negedge rst_ni) 302 | begin 303 | if(~rst_ni) 304 | capture_ir<= 1'b0; 305 | else if (tms_reset) 306 | capture_ir<= 1'b0; 307 | else 308 | if(~tms_i & sel_ir_scan) 309 | capture_ir<= 1'b1; 310 | else 311 | capture_ir<= 1'b0; 312 | end 313 | 314 | // shift_ir state 315 | always @ (posedge tck_i or negedge rst_ni) 316 | begin 317 | if(~rst_ni) 318 | shift_ir<= 1'b0; 319 | else if (tms_reset) 320 | shift_ir<= 1'b0; 321 | else 322 | if(~tms_i & (capture_ir | shift_ir | exit2_ir)) 323 | shift_ir<= 1'b1; 324 | else 325 | shift_ir<= 1'b0; 326 | end 327 | 328 | // exit1_ir state 329 | always @ (posedge tck_i or negedge rst_ni) 330 | begin 331 | if(~rst_ni) 332 | exit1_ir<= 1'b0; 333 | else if (tms_reset) 334 | exit1_ir<= 1'b0; 335 | else 336 | if(tms_i & (capture_ir | shift_ir)) 337 | exit1_ir<= 1'b1; 338 | else 339 | exit1_ir<= 1'b0; 340 | end 341 | 342 | // pause_ir state 343 | always @ (posedge tck_i or negedge rst_ni) 344 | begin 345 | if(~rst_ni) 346 | pause_ir<= 1'b0; 347 | else if (tms_reset) 348 | pause_ir<= 1'b0; 349 | else 350 | if(~tms_i & (exit1_ir | pause_ir)) 351 | pause_ir<= 1'b1; 352 | else 353 | pause_ir<= 1'b0; 354 | end 355 | 356 | // exit2_ir state 357 | always @ (posedge tck_i or negedge rst_ni) 358 | begin 359 | if(~rst_ni) 360 | exit2_ir<= 1'b0; 361 | else if (tms_reset) 362 | exit2_ir<= 1'b0; 363 | else 364 | if(tms_i & pause_ir) 365 | exit2_ir<= 1'b1; 366 | else 367 | exit2_ir<= 1'b0; 368 | end 369 | 370 | // update_ir state 371 | always @ (posedge tck_i or negedge rst_ni) 372 | begin 373 | if(~rst_ni) 374 | update_ir<= 1'b0; 375 | else if (tms_reset) 376 | update_ir<= 1'b0; 377 | else 378 | if(tms_i & (exit1_ir | exit2_ir)) 379 | update_ir<= 1'b1; 380 | else 381 | update_ir<= 1'b0; 382 | end 383 | 384 | /********************************************************************************** 385 | * * 386 | * End: TAP State Machine * 387 | * * 388 | **********************************************************************************/ 389 | 390 | 391 | 392 | /********************************************************************************** 393 | * * 394 | * jtag_ir: JTAG Instruction Register * 395 | * * 396 | **********************************************************************************/ 397 | reg [`IR_LENGTH-1:0] jtag_ir; // Instruction register 398 | reg [`IR_LENGTH-1:0] latched_jtag_ir, latched_jtag_ir_neg; 399 | wire instruction_tdo; 400 | 401 | always @ (posedge tck_i or negedge rst_ni) 402 | begin 403 | if(~rst_ni) 404 | jtag_ir[`IR_LENGTH-1:0] <= `IR_LENGTH'b0; 405 | else if(capture_ir) 406 | jtag_ir <= 5'b00101; // This value is fixed for easier fault detection 407 | else if(shift_ir) 408 | jtag_ir[`IR_LENGTH-1:0] <= {td_i, jtag_ir[`IR_LENGTH-1:1]}; 409 | end 410 | 411 | assign instruction_tdo = jtag_ir[0]; 412 | /********************************************************************************** 413 | * * 414 | * End: jtag_ir * 415 | * * 416 | **********************************************************************************/ 417 | 418 | 419 | 420 | /********************************************************************************** 421 | * * 422 | * idcode logic * 423 | * * 424 | **********************************************************************************/ 425 | reg [31:0] idcode_reg; 426 | wire idcode_tdo; 427 | 428 | always @ (posedge tck_i or negedge rst_ni) 429 | begin 430 | if (~rst_ni) 431 | idcode_reg <= IDCODE_VALUE; 432 | else if(idcode_sel & shift_dr) 433 | idcode_reg <= {td_i, idcode_reg[31:1]}; 434 | else if(idcode_sel & (capture_dr | exit1_dr)) 435 | idcode_reg <= IDCODE_VALUE; 436 | end 437 | 438 | assign idcode_tdo = idcode_reg[0]; 439 | 440 | /********************************************************************************** 441 | * * 442 | * End: idcode logic * 443 | * * 444 | **********************************************************************************/ 445 | 446 | 447 | /********************************************************************************** 448 | * * 449 | * Bypass logic * 450 | * * 451 | **********************************************************************************/ 452 | wire bypassed_tdo; 453 | reg bypass_reg; 454 | 455 | always @ (posedge tck_i or negedge rst_ni) 456 | begin 457 | if (~rst_ni) 458 | bypass_reg<= 1'b0; 459 | else if(shift_dr) 460 | bypass_reg<= td_i; 461 | end 462 | 463 | assign bypassed_tdo = bypass_reg; 464 | /********************************************************************************** 465 | * * 466 | * End: Bypass logic * 467 | * * 468 | **********************************************************************************/ 469 | 470 | 471 | /********************************************************************************** 472 | * * 473 | * Activating Instructions * 474 | * * 475 | **********************************************************************************/ 476 | // Updating jtag_ir (Instruction Register) 477 | always @ (posedge tck_i or negedge rst_ni) 478 | begin 479 | if(~rst_ni) 480 | latched_jtag_ir <= `IDCODE; // IDCODE seled after reset 481 | else if (tms_reset) 482 | latched_jtag_ir <= `IDCODE; // IDCODE seled after reset 483 | else if(update_ir) 484 | latched_jtag_ir <= jtag_ir; 485 | end 486 | 487 | /********************************************************************************** 488 | * * 489 | * End: Activating Instructions * 490 | * * 491 | **********************************************************************************/ 492 | 493 | 494 | // Updating jtag_ir (Instruction Register) 495 | always @ (latched_jtag_ir) 496 | begin 497 | idcode_sel = 1'b0; 498 | memory_sel = 1'b0; 499 | fifo_sel = 1'b0; 500 | confreg_sel = 1'b0; 501 | bypass_sel = 1'b0; 502 | clk_byp_sel = 1'b0; 503 | observ_sel = 1'b0; 504 | 505 | case(latched_jtag_ir) /* synthesis parallel_case */ 506 | `IDCODE: idcode_sel = 1'b1; // ID Code 507 | `REG1: memory_sel = 1'b1; // REG1 508 | `REG2: fifo_sel = 1'b1; // REG2 509 | `REG3: confreg_sel = 1'b1; // REG3 510 | `REG_CLK_BYP: clk_byp_sel = 1'b1; // REG4 511 | `REG_OBSERV: observ_sel = 1'b1; // REG5 512 | `BYPASS: bypass_sel = 1'b1; // BYPASS 513 | default: bypass_sel = 1'b1; // BYPASS 514 | endcase 515 | end 516 | 517 | 518 | 519 | /********************************************************************************** 520 | * * 521 | * Multiplexing TDO data * 522 | * * 523 | **********************************************************************************/ 524 | always @ (*) 525 | begin 526 | if(shift_ir_neg) 527 | tdo_comb = instruction_tdo; 528 | else 529 | begin 530 | case(latched_jtag_ir_neg) // synthesis parallel_case 531 | `IDCODE: tdo_comb = idcode_tdo; // Reading ID code 532 | `REG1: tdo_comb = memory_out_i; // REG1 533 | `REG2: tdo_comb = fifo_out_i; // REG2 534 | `REG3: tdo_comb = confreg_out_i; // REG3 535 | `REG_CLK_BYP: tdo_comb = confreg_out_i; // REG4 536 | `REG_OBSERV: tdo_comb = clk_byp_out_i; // REG5 537 | `BYPASS: tdo_comb = bypassed_tdo; // BYPASS 538 | default: tdo_comb = bypassed_tdo; // BYPASS instruction 539 | endcase 540 | end 541 | end 542 | 543 | 544 | // Tristate control for td_o pin 545 | always @ (negedge tck_i or negedge rst_ni) 546 | begin 547 | if(~rst_ni) begin 548 | td_o <= 1'b0; 549 | end else begin 550 | td_o <= tdo_comb; 551 | // tdo_padoe_o <= shift_ir | shift_dr ; 552 | end 553 | end 554 | /********************************************************************************** 555 | * * 556 | * End: Multiplexing TDO data * 557 | * * 558 | **********************************************************************************/ 559 | 560 | 561 | always @ (negedge tck_i) 562 | begin 563 | shift_ir_neg <= shift_ir; 564 | latched_jtag_ir_neg <= latched_jtag_ir; 565 | end 566 | 567 | endmodule 568 | --------------------------------------------------------------------------------