2 Copyright (c) 2013, IIT Madras
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 /*====== Package imports ======= */
19 import SpecialFIFOs::*;
20 /*======= Project imports ===== */
21 `include "jtagdefines.bsv"
22 import defined_types::*;
23 /*============================== */
25 interface Ifc_jtagdtm;
26 /*======== JTAG input pins ===== */
27 (*always_enabled,always_ready*)
28 method Action tms_i(Bit#(1) tms);
29 (*always_enabled,always_ready*)
30 method Action tdi_i(Bit#(1) tdi);
31 (*always_enabled,always_ready*)
32 method Action tck_i(Bit#(1) tck);
33 (*always_enabled,always_ready*)
34 method Action trst_i(Bit#(1) trst);
35 /*==== inputs from Sub-modules === */
36 method Action debug_tdi_i(Bit#(1) debug_tdi);
37 method Action bs_chain_i(Bit#(1) bs_chain);
38 /*======= JTAG Output Pins ====== */
39 (*always_enabled,always_ready*)
41 method Bit#(1) tdo_oe;
42 /*======== TAP States ============= */
43 method Bit#(1) shift_dr;
44 method Bit#(1) pause_dr;
45 method Bit#(1) update_dr;
46 method Bit#(1) capture_dr;
47 /*=========== Output for BS Chain ==== */
48 method Bit#(1) extest_select;
49 method Bit#(1) sample_preload_select;
50 method Bit#(1) debug_select;
51 method Bit#(1) debug_tdo;
52 /*================================ */
53 method Action response_from_dm(Bit#(34) responsedm);
54 method ActionValue#(Bit#(40)) request_to_dm;
58 function Reg#(t) readOnlyReg(t r);
59 return (interface Reg;
61 method Action _write(t x) = noAction;
64 function Reg#(Bit#(1)) condwriteSideEffect(Reg#(Bit#(1)) r, Action a);
65 return (interface Reg;
66 method Bit#(1) _read = r._read;
67 method Action _write(Bit#(1) x);
77 typedef enum {TestLogicReset = 4'h0, RunTestIdle = 4'h1, SelectDRScan = 4'h2,
78 CaptureDR = 4'h3, ShiftDR = 4'h4, Exit1DR = 4'h5,
79 PauseDR = 4'h6, Exit2DR = 4'h7, UpdateDR = 4'h8,
80 SelectIRScan = 4'h9, CaptureIR = 4'ha, ShiftIR = 4'hb,
81 Exit1IR = 4'hc, PauseIR = 4'hd, Exit2IR = 4'he,
82 UpdateIR = 4'hf } TapStates deriving(Bits,Eq,FShow);
85 module mkjtagdtm(Ifc_jtagdtm);
86 Reg#(Bit#(1)) prv_clk <-mkReg(0);
87 PulseWire posedge_clk <-mkPulseWire();
88 PulseWire negedge_clk <-mkPulseWire();
89 /*========= FIFOs to communicate with the DM==== */
90 FIFOF#(Bit#(40)) request_to_DM <-mkUGFIFOF1();
91 FIFOF#(Bit#(34)) response_from_DM <-mkUGFIFOF1();
92 /*================================================ */
94 /*=== Wires to capture the input pins === */
95 Wire#(Bit#(1)) wr_tms<-mkDWire(0);
96 Wire#(Bit#(1)) wr_tdi<-mkDWire(0);
97 Wire#(Bool) wr_trst<-mkDWire(False);
98 Wire#(Bit#(1)) wr_debug_tdi<-mkDWire(0);
99 Wire#(Bit#(1)) wr_bs_chain_tdi<-mkDWire(0);
100 /*======================================== */
102 Reg#(TapStates) tapstate<-mkRegA(TestLogicReset);
103 Reg#(Bit#(5)) instruction_shiftreg<-mkRegA(0);
104 Reg#(Bit#(5)) instruction<-mkRegA(`IDCODE); // clock this by the inverted clock
105 Reg#(Bit#(1)) bypass_sr<-mkRegA(0);
106 Reg#(Bit#(32)) idcode_sr<-mkRegA(`IDCODEVALUE);
108 Wire#(Bool) wr_dmihardreset_generated<-mkDWire(False);
109 Reg#(Bit#(1)) rg_dmihardreset<-mkRegA(0);
110 Reg#(Bit#(1)) dmihardreset=condwriteSideEffect(rg_dmihardreset,wr_dmihardreset_generated._write(True));
111 Wire#(Bool) wr_dmireset_generated<-mkDWire(False);
112 Reg#(Bit#(1)) rg_dmireset<-mkRegA(0);
113 Reg#(Bit#(1)) dmireset=condwriteSideEffect(rg_dmireset,wr_dmireset_generated._write(True));
114 Reg#(Bit#(3)) idle=readOnlyReg(3'd7);
115 Reg#(Bit#(2)) dmistat<-mkRegA(0);
116 Reg#(Bit#(6)) abits =readOnlyReg(6'd6);
117 Reg#(Bit#(4)) version = readOnlyReg('d1);
118 Reg#(Bit#(32)) dtmcontrol=concatReg8(readOnlyReg(14'd0),
119 dmihardreset,dmireset,readOnlyReg(1'd0),
120 idle,dmistat,abits,version);
121 Reg#(Bit#(32)) dtmcontrol_shiftreg<-mkRegA({17'd0,3'd2,2'd0,6'd6,4'd1});
123 Reg#(Bit#(40)) dmiaccess_shiftreg[2]<-mkCReg(2,'d0);
124 Reg#(Bit#(2)) response_status<-mkReg(0);
125 Reg#(Bool) rg_dmibusy<-mkRegA(False);
128 Bit#(1) bypass_sel = instruction == `BYPASS?1:0;
129 Bit#(1) idcode_sel = instruction == `IDCODE?1:0;
130 Bit#(1) dbg_sel = instruction == `DEBUG?1:0;
131 Bit#(1) dtmcontrol_sel = instruction == `DTMCONTROL?1:0;
132 Bit#(1) dmi_sel = instruction == `DMIACCESS?1:0;
134 Bit#(1) instruction_tdo=instruction_shiftreg[0];
135 Bit#(1) bypass_tdo=bypass_sr;
136 Bit#(1) idcode_tdo=idcode_sr[0];
137 Bit#(1) dtmcontrol_tdo=dtmcontrol_shiftreg[0];
138 Bit#(1) dmiaccess_tdo=dmiaccess_shiftreg[0][0];
140 Reg#(Bit#(1)) rg_tdo<-mkRegA(0);
142 /*== This rule implements the TAPs STATE MACHINE====== */
145 $display($time,"\tTAPSTATE: ",fshow(tapstate),"\tINSTRUCTION: %h",instruction_shiftreg, " DMIACCESS: %h",dmiaccess_shiftreg[1]);
149 rule reset_tap(wr_trst);
150 tapstate<=TestLogicReset;
151 instruction<=`IDCODE;
152 instruction_shiftreg<=0;
155 dmiaccess_shiftreg[1]<=0;
156 dtmcontrol_shiftreg<=({17'd0,3'd2,2'd0,6'd6,4'd1});
157 idcode_sr<=`IDCODEVALUE;
160 rule tap_state_machine(posedge_clk && !wr_trst);
162 TestLogicReset: if(wr_tms==0) tapstate<=RunTestIdle;
163 RunTestIdle : if(wr_tms==1) tapstate <= SelectDRScan;
164 SelectDRScan : if(wr_tms==1) tapstate <= SelectIRScan;
165 else tapstate <= CaptureDR;
166 CaptureDR : if(wr_tms==0) tapstate <= ShiftDR;
167 else tapstate <= Exit1DR;
168 ShiftDR : if(wr_tms==1) tapstate <= Exit1DR;
169 Exit1DR : if(wr_tms==0) tapstate <= PauseDR;
170 else tapstate <= UpdateDR;
171 PauseDR : if(wr_tms==1) tapstate <= Exit2DR;
172 Exit2DR : if(wr_tms==1) tapstate <= UpdateDR;
173 else tapstate <= ShiftDR;
174 UpdateDR : if(wr_tms==1) tapstate <= SelectDRScan;
175 else tapstate <= RunTestIdle;
176 SelectIRScan : if(wr_tms==1) tapstate <= TestLogicReset;
177 else tapstate <= CaptureIR;
178 CaptureIR : if(wr_tms==0) tapstate <= ShiftIR;
179 else tapstate <= Exit1IR;
180 ShiftIR : if(wr_tms==1) tapstate <= Exit1IR;
181 Exit1IR : if(wr_tms==0) tapstate <= PauseIR;
182 else tapstate <= UpdateIR;
183 PauseIR : if(wr_tms==1) tapstate <= Exit2IR;
184 Exit2IR : if(wr_tms==1) tapstate <= UpdateIR;
185 else tapstate <= ShiftIR;
186 UpdateIR : if(wr_tms==1) tapstate <= SelectDRScan;
187 else tapstate <= RunTestIdle;
188 default : tapstate <= TestLogicReset;
192 rule dmireset_generated(wr_dmireset_generated && !wr_trst);
193 dmiaccess_shiftreg[1][1:0]<='d0;
196 rule dmihardreset_generated(wr_dmihardreset_generated && !wr_trst);
198 response_from_DM.deq;
202 /*======= perform dtmcontrol shifts ======== */
203 rule shift_dtm(posedge_clk && !wr_trst);
205 TestLogicReset: dtmcontrol<={17'd0,idle,2'b0,abits,version};
206 CaptureDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<=dtmcontrol;
207 ShiftDR: if(dtmcontrol_sel==1) dtmcontrol_shiftreg<={wr_tdi,dtmcontrol_shiftreg[31:1]};
208 UpdateDR: if(dtmcontrol_sel==1) dtmcontrol<=dtmcontrol_shiftreg;
211 /*========================================== */
212 /*======= perform dmiaccess shifts ======== */
213 rule shift_dmiaccess(posedge_clk && !wr_dmihardreset_generated && !wr_trst && !wr_dmireset_generated);
215 TestLogicReset: dmiaccess_shiftreg[0]<='d0;
216 CaptureDR: if(dmi_sel==1)
217 if(response_from_DM.notEmpty)begin
218 let x=response_from_DM.first[33:0];
219 $display($time,"\tDTM: Getting response: data %h op: %h",x[33:2],x[1:0]);
220 x[1:0]=x[1:0]|response_status;// keeping the lower 2 bits sticky
221 dmiaccess_shiftreg[0][33:0]<=x;
222 response_status<=x[1:0];
223 response_from_DM.deq;
224 $display($time,"\tDTM: New DMIACCESS value: %h",x);
227 ShiftDR: if(dmi_sel==1) dmiaccess_shiftreg[0]<={wr_tdi,dmiaccess_shiftreg[0][39:1]};
228 UpdateDR: if(dmi_sel==1)
229 if(request_to_DM.notFull && dmiaccess_shiftreg[0][1:0]!=0 && rg_dmibusy==False)begin
230 request_to_DM.enq(dmiaccess_shiftreg[0]);
232 $display($time,"\tDTM: Sending request to Debug: %h",dmiaccess_shiftreg[0]);
234 else if(rg_dmibusy) begin
235 response_from_DM.enq('d3);
239 /*========================================== */
241 /*== perform instruction register shifts === */
242 rule shift_reg(posedge_clk && !wr_trst);
244 CaptureIR: instruction_shiftreg<='b10101;
245 ShiftIR : instruction_shiftreg<= {wr_tdi,instruction_shiftreg[4:1]};
248 rule transfer_instruction_on_nedge(negedge_clk && !wr_trst); // TODO negedge here
250 TestLogicReset :instruction<=`IDCODE;
251 UpdateIR :instruction<=instruction_shiftreg;
255 /*==== Bypass Section === */
256 rule bypass_logic(posedge_clk && !wr_trst);
258 TestLogicReset: bypass_sr<=1'b0;
259 CaptureDR : if(bypass_sel==1) bypass_sr<=1'b0;
260 ShiftDR : if(bypass_sel==1) bypass_sr<=wr_tdi;
264 /*======= IDCODE section === */
265 rule idcode_logic(posedge_clk && !wr_trst);
267 TestLogicReset:idcode_sr<=`IDCODEVALUE;
268 CaptureDR: if(idcode_sel==1) idcode_sr<=`IDCODEVALUE;
269 ShiftDR : if(idcode_sel==1) idcode_sr<={wr_tdi,idcode_sr[31:1]};
273 rule generate_tdo_outputpin(negedge_clk && !wr_trst);
274 if(tapstate==ShiftIR)
275 rg_tdo<=instruction_tdo;
278 `IDCODE: rg_tdo<=idcode_tdo;
279 `DEBUG : rg_tdo<=wr_debug_tdi;
280 `EXTEST: rg_tdo<=wr_bs_chain_tdi;
281 `SAMPLE_PRELOAD: rg_tdo<=wr_bs_chain_tdi;
282 `BYPASS: rg_tdo<=bypass_tdo;
283 `DTMCONTROL: rg_tdo<=dtmcontrol_tdo;
284 `DMIACCESS: rg_tdo<=dmiaccess_tdo;
285 default: rg_tdo<=bypass_tdo;
289 /*======== JTAG input pins ===== */
290 method Action tms_i(Bit#(1) tms);
293 method Action tdi_i(Bit#(1) tdi);
296 method Action tck_i(Bit#(1) tck);
298 if(prv_clk==0 && tck==1)
300 else if(prv_clk==1 && tck==0)
303 method Action trst_i(Bit#(1) trst);
304 wr_trst<=unpack(trst);
306 /*============================= */
307 method Action debug_tdi_i(Bit#(1) debug_tdi);
308 wr_debug_tdi<=debug_tdi;
310 method Action bs_chain_i(Bit#(1) bs_chain);
311 wr_bs_chain_tdi<=bs_chain;
313 /*======== TAP States ============= */
314 method shift_dr=tapstate==ShiftDR?1:0;
315 method pause_dr=tapstate==PauseDR?1:0;
316 method update_dr=tapstate==UpdateDR?1:0;
317 method capture_dr=tapstate==CaptureDR?1:0;
318 /*=================================== */
319 /*=========== Output for BS Chain ==== */
320 method extest_select =instruction==`EXTEST?1:0;
321 method sample_preload_select =instruction==`SAMPLE_PRELOAD?1:0;
322 method debug_select =instruction==`DEBUG?1:0;
323 /*================================ */
324 /*======= JTAG Output Pins ====== */
326 method debug_tdo = wr_tdi;
327 method Bit#(1) tdo_oe = ((tapstate == ShiftIR) || (tapstate == ShiftDR))?1:0;
328 method Action response_from_dm(Bit#(34) responsedm) if(response_from_DM.notFull);
329 response_from_DM.enq(responsedm);
331 method ActionValue#(Bit#(40)) request_to_dm if(request_to_DM.notEmpty);
333 return request_to_DM.first;