5deb89a1362f05293fecfac467ca24d2baa5b63a
2 from cocotb
.triggers
import Timer
3 from cocotb
.utils
import get_sim_steps
4 from cocotb
.binary
import BinaryValue
6 class JTAG_Clock(object):
8 Class for the JTAG clock, run cycle by cycle
10 def __init__(self
, signal
, period
):
12 self
.t
= Timer(period
/4)
15 def Cycle(self
, cycles
=1):
18 Cycle start in middle of 0 pulse of the clock
20 for i
in range(cycles
):
29 class JTAG_Master(object):
31 Class that will run JTAG commands, shift in and out data
33 #TODO: Handle a JTAG chain with more than one device
35 def __init__(self
, tck
, tms
, tdi
, tdo
, trst_n
=None, clk_period
=1000):
37 self
.clkgen
= JTAG_Clock(tck
, clk_period
)
46 self
.period
= Timer(clk_period
)
49 # TODO: make IR length configurable; now 2 is assumed
52 self
.SAMPLEPRELOAD
= [1, 0]
55 # After command we always leave the controller in reset or runidle state
56 # If value is None we will always reset the interface
59 # The methods of this class are coroutines. The results will be stored
64 def cycle_clock(self
, cycles
=1):
65 if self
.state
== "Run" and self
.tms
:
67 yield self
.clkgen
.Cycle(cycles
)
71 if not self
.trst_n
is None:
72 # Enable reset signal for one clock period
77 # 5 cycles with tms on 1 should reset the JTAG TAP controller
79 yield self
.cycle_clock(5)
86 def change_state(self
, tms_list
):
87 tms_copy
= list(tms_list
)
89 self
.tms
<= tms_copy
.pop()
90 yield self
.cycle_clock()
94 def change_to_run(self
):
96 Put TAP in RunTestIdle state
97 self.result is bool and true if TAP went through reset state
100 if self
.state
is None:
102 if self
.state
is "Reset":
105 yield self
.cycle_clock()
107 assert(self
.state
== "Run")
108 self
.result
= isreset
111 def load_ir(self
, cmd
):
113 result
= BinaryValue(bits
=len(cmd_copy
))
116 yield self
.change_to_run()
118 yield self
.change_state([0, 1, 1])
123 # In first iteration we enter SHIFT state and tdo is made active
124 yield self
.cycle_clock()
125 # For the last iteration tdi will be shifted when entering next state
126 self
.tdi
<= cmd_copy
.pop()
127 l_result
.insert(0, str(self
.tdo
))
130 yield self
.change_state([0, 1, 1])
136 Get the IDCODE from the device
137 result will contain the 32 bit IDCODE of the device
140 result
= BinaryValue(bits
=32)
143 # Keep tdi 0 for the whole run
146 yield self
.change_to_run()
148 # If TAP was not reset we have to load IDCODE command
149 yield self
.load_ir(self
.IDCODE
)
151 # Should be again in RUN state
152 assert(self
.state
== "Run")
155 yield self
.change_state([0, 0, 1])
157 # Enter Shift; run for 32 cycles
160 l_result
.insert(0, str(self
.tdo
))
161 yield self
.cycle_clock()
162 result
.binstr
= "".join(l_result
)
165 yield self
.change_state([0, 1, 1])
171 def shift_data(self
, data_in
):
173 Shift data in through the JTAG and capture the output
174 Input can be of type BinaryValue or an iterable value of 0 and 1s.
175 Last bit will be shifted in first.
176 result will contain the sample TDO with the same number of bits as the input
178 if isinstance(data_in
, BinaryValue
):
179 data_copy
= [int(c
) for c
in data_in
.binstr
]
181 data_copy
= list(data_in
)
182 result
= BinaryValue()
185 yield self
.change_to_run()
187 yield self
.change_state([0, 1])
192 yield self
.cycle_clock()
193 self
.tdi
<= data_copy
.pop()
194 l_result
.insert(0, str(self
.tdo
))
195 result
.binstr
= "".join(l_result
)
198 yield self
.change_state([0, 1, 1])