add peripherals
[shakti-peripherals.git] / src / peripherals / jtagdtm / jtagdtm_new.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
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.
10
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 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package jtagdtm_new;
15 /*====== Package imports ======= */
16 import ConcatReg::*;
17 import FIFO::*;
18 import FIFOF::*;
19 import SpecialFIFOs::*;
20 /*======= Project imports ===== */
21 `include "jtagdefines.bsv"
22 import defined_types::*;
23 /*============================== */
24
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*)
40 method Bit#(1) tdo;
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;
55
56 endinterface
57
58 function Reg#(t) readOnlyReg(t r);
59 return (interface Reg;
60 method t _read = r;
61 method Action _write(t x) = noAction;
62 endinterface);
63 endfunction
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);
68 r._write(x);
69 if(x==1)
70 a;
71 endmethod
72 endinterface);
73 endfunction
74
75
76
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);
83
84 (*synthesize*)
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 /*================================================ */
93
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 /*======================================== */
101
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);
107
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});
122
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);
126
127
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;
133
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];
139
140 Reg#(Bit#(1)) rg_tdo<-mkRegA(0);
141
142 /*== This rule implements the TAPs STATE MACHINE====== */
143 `ifdef verbose
144 rule just_display;
145 $display($time,"\tTAPSTATE: ",fshow(tapstate),"\tINSTRUCTION: %h",instruction_shiftreg, " DMIACCESS: %h",dmiaccess_shiftreg[1]);
146 endrule
147 `endif
148
149 rule reset_tap(wr_trst);
150 tapstate<=TestLogicReset;
151 instruction<=`IDCODE;
152 instruction_shiftreg<=0;
153 dtmcontrol<=0;
154 rg_dmibusy<=False;
155 dmiaccess_shiftreg[1]<=0;
156 dtmcontrol_shiftreg<=({17'd0,3'd2,2'd0,6'd6,4'd1});
157 idcode_sr<=`IDCODEVALUE;
158 bypass_sr<=0;
159 endrule
160 rule tap_state_machine(posedge_clk && !wr_trst);
161 case(tapstate)
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;
189 endcase
190 endrule
191
192 rule dmireset_generated(wr_dmireset_generated && !wr_trst);
193 dmiaccess_shiftreg[1][1:0]<='d0;
194 response_status<=0;
195 endrule
196 rule dmihardreset_generated(wr_dmihardreset_generated && !wr_trst);
197 request_to_DM.deq;
198 response_from_DM.deq;
199 rg_dmibusy<=False;
200 endrule
201
202 /*======= perform dtmcontrol shifts ======== */
203 rule shift_dtm(posedge_clk && !wr_trst);
204 case(tapstate)
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;
209 endcase
210 endrule
211 /*========================================== */
212 /*======= perform dmiaccess shifts ======== */
213 rule shift_dmiaccess(posedge_clk && !wr_dmihardreset_generated && !wr_trst && !wr_dmireset_generated);
214 case(tapstate)
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);
225 rg_dmibusy<=False;
226 end
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]);
231 rg_dmibusy<=True;
232 $display($time,"\tDTM: Sending request to Debug: %h",dmiaccess_shiftreg[0]);
233 end
234 else if(rg_dmibusy) begin
235 response_from_DM.enq('d3);
236 end
237 endcase
238 endrule
239 /*========================================== */
240
241 /*== perform instruction register shifts === */
242 rule shift_reg(posedge_clk && !wr_trst);
243 case(tapstate)
244 CaptureIR: instruction_shiftreg<='b10101;
245 ShiftIR : instruction_shiftreg<= {wr_tdi,instruction_shiftreg[4:1]};
246 endcase
247 endrule
248 rule transfer_instruction_on_nedge(negedge_clk && !wr_trst); // TODO negedge here
249 case(tapstate)
250 TestLogicReset :instruction<=`IDCODE;
251 UpdateIR :instruction<=instruction_shiftreg;
252 endcase
253 endrule
254
255 /*==== Bypass Section === */
256 rule bypass_logic(posedge_clk && !wr_trst);
257 case(tapstate)
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;
261 endcase
262 endrule
263
264 /*======= IDCODE section === */
265 rule idcode_logic(posedge_clk && !wr_trst);
266 case(tapstate)
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]};
270 endcase
271 endrule
272
273 rule generate_tdo_outputpin(negedge_clk && !wr_trst);
274 if(tapstate==ShiftIR)
275 rg_tdo<=instruction_tdo;
276 else
277 case(instruction)
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;
286 endcase
287 endrule
288
289 /*======== JTAG input pins ===== */
290 method Action tms_i(Bit#(1) tms);
291 wr_tms<=tms;
292 endmethod
293 method Action tdi_i(Bit#(1) tdi);
294 wr_tdi<=tdi;
295 endmethod
296 method Action tck_i(Bit#(1) tck);
297 prv_clk<=tck;
298 if(prv_clk==0 && tck==1)
299 posedge_clk.send;
300 else if(prv_clk==1 && tck==0)
301 negedge_clk.send;
302 endmethod
303 method Action trst_i(Bit#(1) trst);
304 wr_trst<=unpack(trst);
305 endmethod
306 /*============================= */
307 method Action debug_tdi_i(Bit#(1) debug_tdi);
308 wr_debug_tdi<=debug_tdi;
309 endmethod
310 method Action bs_chain_i(Bit#(1) bs_chain);
311 wr_bs_chain_tdi<=bs_chain;
312 endmethod
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 ====== */
325 method tdo = rg_tdo;
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);
330 endmethod
331 method ActionValue#(Bit#(40)) request_to_dm if(request_to_DM.notEmpty);
332 request_to_DM.deq;
333 return request_to_DM.first;
334 endmethod
335 endmodule
336
337 endpackage