jtag_debug_port.sv (3943B)
1 // Copyright 2014 Brian Swetland <swetland@frotz.net> 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 `timescale 1ns / 1ps 16 17 /* Exposes a 36bit register on JTAG USER4: 18 * 19 * 35 0 20 * CAAADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD 21 * | | | 22 * | addr data 23 * commit 24 * 25 * - on JTAG UPDATE 26 * - if commit bit is set: 27 * bits 34:32 are presented on o_addr, 28 * 31:0 are presented on o_wdata, 29 * and o_wr is strobed 30 * - otherwise bits 34:32 are presented on o_addr, 31 * o_rd is strobed, and i_rdata is captured on the next clock 32 * 33 * - to write a register via JTAG: 34 * - shift in {1, addr, data}, UPDATE 35 * 36 * - to read a register via JTAG: 37 * - shift in {0, addr, dontcare}, UPDATE 38 * - data will be returned on next read or write 39 * 40 * - data read back via JTAG will be {1, addr, data} 41 * - addr is the last address read or written 42 * - data is the data that was read or written 43 * - high bit is one 44 */ 45 46 module jtag_debug_port( 47 output reg o_rd, 48 output reg o_wr, 49 output [RBITS-1:0]o_addr, 50 output [31:0]o_wdata, 51 input [31:0]i_rdata, 52 input clk 53 ); 54 55 parameter RBITS = 3; 56 57 wire capture, sel, shift; 58 wire tck, tdi, update; 59 60 reg [RBITS+32:0]data_sr; // JTAG shift register 61 reg [RBITS+32:0]data_to_jtag; // captured on CAPTURE by sr 62 reg [RBITS+32:0]data_to_port; // captured on UPDATE from sr 63 reg [RBITS+32:0]data_to_jtag_next; 64 reg [RBITS+32:0]data_to_port_next; 65 reg o_rd_next; 66 reg o_wr_next; 67 68 assign o_wdata = data_to_port[31:0]; 69 assign o_addr = data_to_port[RBITS+31:32]; 70 71 wire do_txn; 72 73 `ifndef verilator 74 BSCANE2 #( 75 .JTAG_CHAIN(4) 76 ) bscan ( 77 .CAPTURE(capture), 78 .DRCK(), 79 .RESET(), 80 .RUNTEST(), 81 .SEL(sel), 82 .SHIFT(shift), 83 .TCK(tck), 84 .TDI(tdi), 85 .TMS(), 86 .UPDATE(update), 87 .TDO(data_sr[0]) 88 ); 89 `endif 90 91 localparam STATE_IDLE = 0; 92 localparam STATE_READ = 1; 93 localparam STATE_READ2 = 2; 94 localparam STATE_WRITE = 3; 95 96 reg [1:0]state = STATE_IDLE; 97 reg [1:0]state_next; 98 99 always @(*) begin 100 state_next = state; 101 data_to_port_next = data_to_port; 102 data_to_jtag_next = data_to_jtag; 103 o_rd_next = 0; 104 o_wr_next = 0; 105 106 case (state) 107 STATE_IDLE: begin 108 if (do_txn) begin 109 data_to_port_next = data_sr; 110 if (data_sr[RBITS+32]) begin 111 state_next = STATE_WRITE; 112 o_wr_next = 1; 113 end else begin 114 state_next = STATE_READ; 115 o_rd_next = 1; 116 end 117 end 118 end 119 STATE_READ: begin 120 state_next = STATE_READ2; 121 end 122 STATE_READ2: begin 123 state_next = STATE_IDLE; 124 data_to_jtag_next = { 1'b1, data_to_port[RBITS+31:32], i_rdata }; 125 end 126 STATE_WRITE: begin 127 state_next = STATE_IDLE; 128 data_to_jtag_next = { 1'b1, data_to_port[RBITS+31:0] }; 129 end 130 endcase 131 end 132 133 always @(posedge clk) begin 134 state <= state_next; 135 data_to_port <= data_to_port_next; 136 data_to_jtag <= data_to_jtag_next; 137 o_rd <= o_rd_next; 138 o_wr <= o_wr_next; 139 end 140 141 wire do_capture = sel & capture; 142 wire do_update = sel & update; 143 wire do_shift = sel & shift; 144 145 always @(posedge tck) 146 if (do_capture) 147 data_sr <= data_to_jtag; 148 else if (do_shift) 149 data_sr <= { tdi, data_sr[RBITS+32:1] }; 150 151 sync s0( 152 .clk_in(tck), 153 .in(do_update), 154 .clk_out(clk), 155 .out(do_txn) 156 ); 157 158 endmodule 159 160 module sync( 161 input clk_in, 162 input clk_out, 163 input in, 164 output out 165 ); 166 reg toggle = 1'b0; 167 reg [2:0] sync = 3'b0; 168 always @(posedge clk_in) 169 if (in) toggle <= ~toggle; 170 always @(posedge clk_out) 171 sync <= { sync[1:0], toggle }; 172 assign out = (sync[2] ^ sync[1]); 173 endmodule