origen_jtag 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/config/application.rb +64 -0
- data/config/commands.rb +90 -0
- data/config/development.rb +15 -0
- data/config/environment.rb +1 -0
- data/config/users.rb +19 -0
- data/config/version.rb +8 -0
- data/lib/origen_jtag/driver.rb +449 -0
- data/lib/origen_jtag/dut.rb +64 -0
- data/lib/origen_jtag/tap_controller.rb +299 -0
- data/lib/origen_jtag.rb +13 -0
- data/pattern/jtag_workout.rb +184 -0
- data/templates/web/index.md.erb +139 -0
- data/templates/web/layouts/_basic.html.erb +13 -0
- data/templates/web/partials/_navbar.html.erb +22 -0
- data/templates/web/release_notes.md.erb +5 -0
- metadata +73 -0
@@ -0,0 +1,64 @@
|
|
1
|
+
module OrigenJTAG
|
2
|
+
# This is a dummy DUT model which is used
|
3
|
+
# to instantiate and test the JTAG locally
|
4
|
+
# during development.
|
5
|
+
#
|
6
|
+
# It is not included when this library is imported.
|
7
|
+
class DUT
|
8
|
+
include OrigenJTAG
|
9
|
+
include Origen::Callbacks
|
10
|
+
include Origen::Registers
|
11
|
+
include Origen::Pins
|
12
|
+
|
13
|
+
JTAG_CONFIG = {
|
14
|
+
verbose: true,
|
15
|
+
tclk_format: :rh,
|
16
|
+
tclk_multiple: 1,
|
17
|
+
tdo_strobe: :tclk_high,
|
18
|
+
tdo_store_cycle: 0,
|
19
|
+
init_state: :unknown
|
20
|
+
}
|
21
|
+
|
22
|
+
def initialize(options = {})
|
23
|
+
JTAG_CONFIG[:tclk_format] = options[:tclk_format] if options[:tclk_format]
|
24
|
+
JTAG_CONFIG[:tclk_multiple] = options[:tclk_multiple] if options[:tclk_multiple]
|
25
|
+
JTAG_CONFIG[:tdo_strobe] = options[:tdo_strobe] if options[:tdo_strobe]
|
26
|
+
JTAG_CONFIG[:tdo_store_cycle] = options[:tdo_store_cycle] if options[:tdo_store_cycle]
|
27
|
+
JTAG_CONFIG[:init_state] = options[:init_state] if options[:init_state]
|
28
|
+
end
|
29
|
+
|
30
|
+
def tclk_format
|
31
|
+
JTAG_CONFIG[:tclk_format]
|
32
|
+
end
|
33
|
+
|
34
|
+
def tclk_multiple
|
35
|
+
JTAG_CONFIG[:tclk_multiple]
|
36
|
+
end
|
37
|
+
|
38
|
+
def tdo_strobe
|
39
|
+
JTAG_CONFIG[:tdo_strobe]
|
40
|
+
end
|
41
|
+
|
42
|
+
def tdo_store_cycle
|
43
|
+
JTAG_CONFIG[:tdo_store_cycle]
|
44
|
+
end
|
45
|
+
|
46
|
+
def init_state
|
47
|
+
JTAG_CONFIG[:init_state]
|
48
|
+
end
|
49
|
+
|
50
|
+
def on_create
|
51
|
+
add_reg :test16, 0x0012, 16, bus: { pos: 8, bits: 8 },
|
52
|
+
bit: { pos: 0 }
|
53
|
+
|
54
|
+
add_reg :test32, 0x0014, 32, bus: { pos: 16, bits: 16 },
|
55
|
+
bit: { pos: 0 }
|
56
|
+
|
57
|
+
$tester.set_timeset('nvmbist', 40)
|
58
|
+
add_pin :tclk
|
59
|
+
add_pin :tdi
|
60
|
+
add_pin :tdo
|
61
|
+
add_pin :tms
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,299 @@
|
|
1
|
+
module OrigenJTAG
|
2
|
+
# Provides methods specifically for controlling the state of the
|
3
|
+
# TAP Controller
|
4
|
+
module TAPController
|
5
|
+
# Map of internal state symbols to human readable names
|
6
|
+
STATES = {
|
7
|
+
reset: 'Test-Logic-Reset',
|
8
|
+
idle: 'Run-Test/Idle',
|
9
|
+
select_dr: 'Select-DR',
|
10
|
+
capture_dr: 'Capture-DR',
|
11
|
+
shift_dr: 'Shift-DR',
|
12
|
+
exit1_dr: 'Exit1-DR',
|
13
|
+
pause_dr: 'Pause-DR',
|
14
|
+
exit2_dr: 'Exit2-DR',
|
15
|
+
update_dr: 'Update-DR',
|
16
|
+
select_ir: 'Select-IR',
|
17
|
+
capture_ir: 'Capture-IR',
|
18
|
+
shift_ir: 'Shift-IR',
|
19
|
+
exit1_ir: 'Exit1-IR',
|
20
|
+
pause_ir: 'Pause-IR',
|
21
|
+
exit2_ir: 'Exit2-IR',
|
22
|
+
update_ir: 'Update-IR'
|
23
|
+
}
|
24
|
+
|
25
|
+
# Returns the current state of the JTAG TAP Controller
|
26
|
+
attr_reader :state
|
27
|
+
alias_method :current_state, :state
|
28
|
+
|
29
|
+
# Goto Shift-DR state then exit back to Run-Test/Idle
|
30
|
+
#
|
31
|
+
# @example Trandition into Shift-DR
|
32
|
+
# # State is Run-Test/Idle
|
33
|
+
# jtag.shift_dr do
|
34
|
+
# # State is Shift-DR
|
35
|
+
# end
|
36
|
+
# # State is Run-Test/Idle
|
37
|
+
#
|
38
|
+
# This method can be nested inside of a pause_dr block
|
39
|
+
# to transition into the Shift-DR state and then back
|
40
|
+
# to Pause-DR
|
41
|
+
#
|
42
|
+
# @example Switching between Pause-DR and Shift-DR
|
43
|
+
# # State is Run-Test/Idle
|
44
|
+
# jtag.pause_dr do
|
45
|
+
# # State is Pause-DR
|
46
|
+
# jtag.shift_dr do
|
47
|
+
# # State is Shift-DR
|
48
|
+
# end
|
49
|
+
# # State is Pause-DR
|
50
|
+
# end
|
51
|
+
# # State is Run-Test/Idle
|
52
|
+
def shift_dr
|
53
|
+
validate_state(:idle, :pause_dr)
|
54
|
+
log 'Transition to Shift-DR...'
|
55
|
+
if state == :idle
|
56
|
+
tms!(1) # => Select-DR-Scan
|
57
|
+
tms!(0) # => Capture-DR
|
58
|
+
tms!(0) # => Shift-DR
|
59
|
+
update_state :shift_dr
|
60
|
+
log '**** Data start ****', always: true
|
61
|
+
yield
|
62
|
+
log 'Transition to Run-Test/Idle...'
|
63
|
+
if @last_data_vector_shifted
|
64
|
+
@last_data_vector_shifted = false
|
65
|
+
else
|
66
|
+
tms!(1) # => Exit1-DR
|
67
|
+
end
|
68
|
+
log '**** Data stop ****', always: true
|
69
|
+
tms!(1) # => Update-DR
|
70
|
+
tms!(0) # => Run-Test/Idle
|
71
|
+
update_state :idle
|
72
|
+
else # :pause_dr
|
73
|
+
tms!(1) # => Exit2-DR
|
74
|
+
tms!(0) # => Shift-DR
|
75
|
+
update_state :shift_dr
|
76
|
+
yield
|
77
|
+
log 'Transition to Pause-DR...'
|
78
|
+
tms!(1) # => Exit1-DR
|
79
|
+
tms!(0) # => Pause-DR
|
80
|
+
update_state :pause_dr
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# Goto Pause-DR state then exit back to Run-Test/Idle
|
85
|
+
#
|
86
|
+
# @example Trandition into Pause-DR
|
87
|
+
# # State is Run-Test/Idle
|
88
|
+
# jtag.pause_dr do
|
89
|
+
# # State is Pause-DR
|
90
|
+
# end
|
91
|
+
# # State is Run-Test/Idle
|
92
|
+
#
|
93
|
+
# This method can be nested inside of a shift_dr block
|
94
|
+
# to transition into the Pause-DR state and then back
|
95
|
+
# to Shift-DR
|
96
|
+
#
|
97
|
+
# @example Switching between Shift-DR and Pause-DR
|
98
|
+
# # State is Run-Test/Idle
|
99
|
+
# jtag.shift_dr do
|
100
|
+
# # State is Shift-DR
|
101
|
+
# jtag.pause_dr do
|
102
|
+
# # State is Pause-DR
|
103
|
+
# end
|
104
|
+
# # State is Shift-DR
|
105
|
+
# end
|
106
|
+
# # State is Run-Test/Idle
|
107
|
+
def pause_dr
|
108
|
+
validate_state(:idle, :shift_dr)
|
109
|
+
log 'Transition to Pause-DR...'
|
110
|
+
if state == :idle
|
111
|
+
tms!(1) # => Select-DR-Scan
|
112
|
+
tms!(0) # => Capture-DR
|
113
|
+
tms!(1) # => Exit1-DR
|
114
|
+
tms!(0) # => Pause-DR
|
115
|
+
update_state :pause_dr
|
116
|
+
yield
|
117
|
+
log 'Transition to Run-Test/Idle...'
|
118
|
+
tms!(1) # => Exit2-DR
|
119
|
+
tms!(1) # => Update-DR
|
120
|
+
tms!(0) # => Run-Test/Idle
|
121
|
+
update_state :idle
|
122
|
+
else # shift_dr
|
123
|
+
tms!(1) # => Exit1-DR
|
124
|
+
tms!(0) # => Pause-DR
|
125
|
+
update_state :pause_dr
|
126
|
+
yield
|
127
|
+
log 'Transition to Shift-DR...'
|
128
|
+
tms!(1) # => Exit2-DR
|
129
|
+
tms!(0) # => Shift-DR
|
130
|
+
update_state :shift_dr
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
# Goto Shift-IR state then exit back to Run-Test/Idle
|
135
|
+
#
|
136
|
+
# @example Trandition into Shift-IR
|
137
|
+
# # State is Run-Test/Idle
|
138
|
+
# jtag.shift_ir do
|
139
|
+
# # State is Shift-IR
|
140
|
+
# end
|
141
|
+
# # State is Run-Test/Idle
|
142
|
+
#
|
143
|
+
# This method can be nested inside of a pause_ir block
|
144
|
+
# to transition into the Shift-IR state and then back
|
145
|
+
# to Pause-IR
|
146
|
+
#
|
147
|
+
# @example Switching between Pause-IR and Shift-IR
|
148
|
+
# # State is Run-Test/Idle
|
149
|
+
# jtag.pause_ir do
|
150
|
+
# # State is Pause-IR
|
151
|
+
# jtag.shift_ir do
|
152
|
+
# # State is Shift-IR
|
153
|
+
# end
|
154
|
+
# # State is Pause-IR
|
155
|
+
# end
|
156
|
+
# # State is Run-Test/Idle
|
157
|
+
def shift_ir
|
158
|
+
validate_state(:idle, :pause_ir)
|
159
|
+
log 'Transition to Shift-IR...'
|
160
|
+
if state == :idle
|
161
|
+
tms!(1) # => Select-DR-Scan
|
162
|
+
tms!(1) # => Select-IR-Scan
|
163
|
+
tms!(0) # => Capture-IR
|
164
|
+
tms!(0) # => Shift-IR
|
165
|
+
update_state :shift_ir
|
166
|
+
log '**** Data start ****', always: true
|
167
|
+
yield
|
168
|
+
log 'Transition to Run-Test/Idle...'
|
169
|
+
if @last_data_vector_shifted
|
170
|
+
@last_data_vector_shifted = false
|
171
|
+
else
|
172
|
+
tms!(1) # => Exit1-DR
|
173
|
+
end
|
174
|
+
log '**** Data stop ****', always: true
|
175
|
+
tms!(1) # => Update-IR
|
176
|
+
tms!(0) # => Run-Test/Idle
|
177
|
+
update_state :idle
|
178
|
+
else # :pause_ir
|
179
|
+
tms!(1) # => Exit2-IR
|
180
|
+
tms!(0) # => Shift-IR
|
181
|
+
update_state :shift_ir
|
182
|
+
yield
|
183
|
+
log 'Transition to Pause-IR...'
|
184
|
+
tms!(1) # => Exit1-IR
|
185
|
+
tms!(0) # => Pause-IR
|
186
|
+
update_state :pause_ir
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# Goto Pause-IR state then exit back to Run-Test/Idle
|
191
|
+
#
|
192
|
+
# @example Trandition into Pause-iR
|
193
|
+
# # State is Run-Test/Idle
|
194
|
+
# jtag.pause_ir do
|
195
|
+
# # State is Pause-IR
|
196
|
+
# end
|
197
|
+
# # State is Run-Test/Idle
|
198
|
+
#
|
199
|
+
# This method can be nested inside of a shift_ir block
|
200
|
+
# to transition into the Pause-IR state and then back
|
201
|
+
# to Shift-IR
|
202
|
+
#
|
203
|
+
# @example Switching between Shift-IR and Pause-IR
|
204
|
+
# # State is Run-Test/Idle
|
205
|
+
# jtag.shift_ir do
|
206
|
+
# # State is Shift-IR
|
207
|
+
# jtag.pause_ir do
|
208
|
+
# # State is Pause-IR
|
209
|
+
# end
|
210
|
+
# # State is Shift-IR
|
211
|
+
# end
|
212
|
+
# # State is Run-Test/Idle
|
213
|
+
def pause_ir
|
214
|
+
validate_state(:idle, :shift_ir)
|
215
|
+
log 'Transition to Pause-IR...'
|
216
|
+
if state == :idle
|
217
|
+
tms!(1) # => Select-DR-Scan
|
218
|
+
tms!(1) # => Select-IR-Scan
|
219
|
+
tms!(0) # => Capture-IR
|
220
|
+
tms!(1) # => Exit1-IR
|
221
|
+
tms!(0) # => Pause-IR
|
222
|
+
update_state :pause_ir
|
223
|
+
yield
|
224
|
+
log 'Transition to Run-Test/Idle...'
|
225
|
+
tms!(1) # => Exit2-IR
|
226
|
+
tms!(1) # => Update-IR
|
227
|
+
tms!(0) # => Run-Test/Idle
|
228
|
+
update_state :idle
|
229
|
+
else # :shift_ir
|
230
|
+
tms!(1) # => Exit1-IR
|
231
|
+
tms!(0) # => Pause-IR
|
232
|
+
update_state :pause_ir
|
233
|
+
yield
|
234
|
+
log 'Transition to Shift-IR...'
|
235
|
+
tms!(1) # => Exit2-IR
|
236
|
+
tms!(0) # => Shift-IR
|
237
|
+
update_state :shift_ir
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# Returns the current state as a human readable string
|
242
|
+
def state_str
|
243
|
+
STATES[state]
|
244
|
+
end
|
245
|
+
alias_method :current_state_str, :state_str
|
246
|
+
|
247
|
+
# Forces the state to Run-Test/Idle regardless of the current
|
248
|
+
# state.
|
249
|
+
def idle
|
250
|
+
log 'Force transition to Run-Test/Idle...'
|
251
|
+
# From the JTAG2IPS block guide holding TMS high for 5 cycles
|
252
|
+
# will force it to reset regardless of the state, let's give
|
253
|
+
# it 6 for luck:
|
254
|
+
6.times { tms!(1) }
|
255
|
+
# Now a couple of cycles low to get it into idle
|
256
|
+
2.times { tms!(0) }
|
257
|
+
update_state :idle
|
258
|
+
end
|
259
|
+
|
260
|
+
# Force state to Test-Logic-Reset regardless of the current
|
261
|
+
# state
|
262
|
+
def reset
|
263
|
+
log 'Force transition to Test-Logic-Reset...'
|
264
|
+
# JTAG reset
|
265
|
+
6.times { tms!(1) }
|
266
|
+
end
|
267
|
+
|
268
|
+
private
|
269
|
+
|
270
|
+
def init_tap_controller(options = {})
|
271
|
+
options = {
|
272
|
+
}.merge(options)
|
273
|
+
end
|
274
|
+
|
275
|
+
def update_state(state)
|
276
|
+
@state = state
|
277
|
+
log "Current state: #{state_str}"
|
278
|
+
end
|
279
|
+
|
280
|
+
# Ensures that the current state matches one of the given acceptable
|
281
|
+
# states.
|
282
|
+
#
|
283
|
+
# Additionally if the current state is unknown and idle is acceptable
|
284
|
+
# then the state will be transitioned to idle.
|
285
|
+
def validate_state(*acceptable_states)
|
286
|
+
if current_state == :unknown && acceptable_states.include?(:idle)
|
287
|
+
idle
|
288
|
+
elsif acceptable_states.include?(current_state)
|
289
|
+
return
|
290
|
+
else
|
291
|
+
fail 'JTAG TAP Controller - An invalid state sequence has occurred!'
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
def log(msg, options = {})
|
296
|
+
cc "JTAG::TAPController - #{msg}" if verbose? || options[:always]
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
data/lib/origen_jtag.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'origen'
|
2
|
+
require_relative '../config/application.rb'
|
3
|
+
|
4
|
+
# Include this module to add a JTAG driver to your class
|
5
|
+
module OrigenJTAG
|
6
|
+
autoload :TAPController, 'origen_jtag/tap_controller'
|
7
|
+
autoload :Driver, 'origen_jtag/driver'
|
8
|
+
|
9
|
+
# Returns an instance of the OrigenJTAG::Driver
|
10
|
+
def jtag
|
11
|
+
@jtag ||= Driver.new(self)
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,184 @@
|
|
1
|
+
Pattern.create(options={:name => "jtag_workout_#{$dut.tclk_format.upcase}#{$dut.tclk_multiple}"}) do
|
2
|
+
def test(msg)
|
3
|
+
ss "Test - #{msg}"
|
4
|
+
end
|
5
|
+
|
6
|
+
jtag = $dut.jtag
|
7
|
+
reg = $dut.reg(:test16)
|
8
|
+
|
9
|
+
# First tests of the TAP Controller
|
10
|
+
|
11
|
+
test "Transition TAP controller in and out of Shift-DR"
|
12
|
+
jtag.shift_dr { }
|
13
|
+
|
14
|
+
test "Transition TAP controller in and out of Pause-DR"
|
15
|
+
jtag.pause_dr { }
|
16
|
+
|
17
|
+
test "Transition TAP controller in and out of Shift-IR"
|
18
|
+
jtag.shift_ir { }
|
19
|
+
|
20
|
+
test "Transition TAP controller in and out of Pause-IR"
|
21
|
+
jtag.pause_ir { }
|
22
|
+
|
23
|
+
test "Transition into Shift-DR, then back and forth into Pause-DR"
|
24
|
+
jtag.shift_dr do
|
25
|
+
jtag.pause_dr { }
|
26
|
+
jtag.pause_dr { }
|
27
|
+
end
|
28
|
+
|
29
|
+
test "Transition into Pause-DR, then back and forth into Shift-DR"
|
30
|
+
jtag.pause_dr do
|
31
|
+
jtag.shift_dr { }
|
32
|
+
jtag.shift_dr { }
|
33
|
+
end
|
34
|
+
|
35
|
+
test "Transition into Shift-IR, then back and forth into Pause-IR"
|
36
|
+
jtag.shift_ir do
|
37
|
+
jtag.pause_ir { }
|
38
|
+
jtag.pause_ir { }
|
39
|
+
end
|
40
|
+
|
41
|
+
test "Transition into Pause-IR, then back and forth into Shift-IR"
|
42
|
+
jtag.pause_ir do
|
43
|
+
jtag.shift_ir { }
|
44
|
+
jtag.shift_ir { }
|
45
|
+
end
|
46
|
+
|
47
|
+
# Tests of the shift method, make sure it handles registers with
|
48
|
+
# bit-level flags set in additional to dumb values
|
49
|
+
|
50
|
+
test "Shifting an explicit value into TDI"
|
51
|
+
jtag.shift 0x1234, :size => 16, :cycle_last => true
|
52
|
+
|
53
|
+
test "Shifting an explicit value out of TDO"
|
54
|
+
jtag.shift 0x1234, :size => 16, :cycle_last => true, :read => true
|
55
|
+
|
56
|
+
test "Shift register into TDI"
|
57
|
+
reg.write(0xFF01)
|
58
|
+
cc "Full register (16 bits)"
|
59
|
+
jtag.shift reg, :cycle_last => true
|
60
|
+
cc "Full register with additional size (32 bits)"
|
61
|
+
jtag.shift reg, :cycle_last => true, :size => 32
|
62
|
+
cc "Full register with reduced size (8 bits)"
|
63
|
+
jtag.shift reg, :cycle_last => true, :size => 8, :includes_last_bit => false
|
64
|
+
|
65
|
+
test "Shift register into TDI with overlay"
|
66
|
+
reg.overlay("write_overlay")
|
67
|
+
cc "Full register (16 bits)"
|
68
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
69
|
+
jtag.shift reg, :cycle_last => true
|
70
|
+
cc "Full register with additional size (32 bits)"
|
71
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
72
|
+
jtag.shift reg, :cycle_last => true, :size => 32
|
73
|
+
cc "Full register with reduced size (8 bits)"
|
74
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
75
|
+
jtag.shift reg, :cycle_last => true, :size => 8, :includes_last_bit => false
|
76
|
+
cc "It should in-line overlays when running in simulation mode"
|
77
|
+
Origen.mode = :simulation
|
78
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
79
|
+
jtag.shift reg, :cycle_last => true
|
80
|
+
Origen.mode = :debug
|
81
|
+
|
82
|
+
test "Shift register into TDI with single bit overlay"
|
83
|
+
reg.overlay(nil)
|
84
|
+
reg.bit(:bit).overlay("write_overlay")
|
85
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
86
|
+
jtag.shift reg, :cycle_last => true
|
87
|
+
reg.overlay(nil)
|
88
|
+
|
89
|
+
test "Read register out of TDO"
|
90
|
+
cc "Full register (16 bits)"
|
91
|
+
reg.read
|
92
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
93
|
+
cc "Full register with additional size (32 bits)"
|
94
|
+
reg.read
|
95
|
+
jtag.shift reg, :cycle_last => true, :size => 32, :read => true
|
96
|
+
cc "Full register with reduced size (8 bits)"
|
97
|
+
reg.read
|
98
|
+
jtag.shift reg, :cycle_last => true, :size => 8, :read => true, :includes_last_bit => false
|
99
|
+
|
100
|
+
test "Read single bit out of TDO"
|
101
|
+
reg.bit(:bit).read
|
102
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
103
|
+
|
104
|
+
test "Store register out of TDO"
|
105
|
+
cc "Full register (16 bits)"
|
106
|
+
reg.store
|
107
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
108
|
+
cc "Full register with additional size (32 bits)"
|
109
|
+
reg.store
|
110
|
+
jtag.shift reg, :cycle_last => true, :size => 32, :read => true
|
111
|
+
cc "Full register with reduced size (8 bits)"
|
112
|
+
reg.store
|
113
|
+
jtag.shift reg, :cycle_last => true, :size => 8, :read => true, :includes_last_bit => false
|
114
|
+
|
115
|
+
test "Store single bit out of TDO"
|
116
|
+
reg.bit(:bit).store
|
117
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
118
|
+
|
119
|
+
test "Test flag clear, bit 0 should be read, but not stored"
|
120
|
+
reg.bit(:bit).read
|
121
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
122
|
+
|
123
|
+
test "Shift register out of TDO with overlay"
|
124
|
+
reg.overlay("read_overlay")
|
125
|
+
cc "Full register (16 bits)"
|
126
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
127
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
128
|
+
cc "Full register with additional size (32 bits)"
|
129
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
130
|
+
jtag.shift reg, :cycle_last => true, :size => 32, :read => true
|
131
|
+
cc "Full register with reduced size (8 bits)"
|
132
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
133
|
+
jtag.shift reg, :cycle_last => true, :size => 8, :read => true, :includes_last_bit => false
|
134
|
+
cc "It should in-line overlays when running in simulation mode"
|
135
|
+
Origen.mode = :simulation
|
136
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
137
|
+
jtag.shift reg, :cycle_last => true, :read => true
|
138
|
+
Origen.mode = :debug
|
139
|
+
|
140
|
+
test "Shift register out of TDO with single bit overlay"
|
141
|
+
reg.overlay(nil)
|
142
|
+
reg.bit(:bit).overlay("read_overlay")
|
143
|
+
Origen.tester.cycle # Give a padding cycle as a place for the subroutine call to go
|
144
|
+
jtag.shift reg, :cycle_last => true
|
145
|
+
reg.overlay(nil)
|
146
|
+
|
147
|
+
# Finally integration tests of the TAPController + shift
|
148
|
+
|
149
|
+
test "Write value into DR"
|
150
|
+
jtag.write_dr 0xFFFF, :size => 16, :msg => "Write value into DR"
|
151
|
+
|
152
|
+
test "Write register into DR with full-width overlay"
|
153
|
+
r = $dut.reg(:test32).overlay("write_overlay")
|
154
|
+
jtag.write_dr r
|
155
|
+
|
156
|
+
test "Read value out of DR"
|
157
|
+
jtag.read_dr 0xFFFF, :size => 16, :msg => "Read value out of DR"
|
158
|
+
|
159
|
+
test "Write value into IR"
|
160
|
+
jtag.write_ir 0xF, :size => 4, :msg => "Write value into IR"
|
161
|
+
|
162
|
+
test "Read value out of IR"
|
163
|
+
jtag.read_ir 0xF, :size => 4, :msg => "Read value out of IR"
|
164
|
+
|
165
|
+
test "The IR value is tracked and duplicate writes are inhibited"
|
166
|
+
jtag.write_ir 0xF, :size => 4
|
167
|
+
|
168
|
+
test "Unless forced"
|
169
|
+
jtag.write_ir 0xF, :size => 4, :force => true
|
170
|
+
|
171
|
+
test "Reset"
|
172
|
+
jtag.reset
|
173
|
+
|
174
|
+
test "Suspend of compare on TDO works"
|
175
|
+
cc "TDO should be H"
|
176
|
+
jtag.read_dr 0xFFFF, :size => 16, :msg => "Read value out of DR"
|
177
|
+
$tester.ignore_fails($dut.pin(:tdo)) do
|
178
|
+
cc "TDO should be X"
|
179
|
+
jtag.read_dr 0xFFFF, :size => 16, :msg => "Read value out of DR"
|
180
|
+
end
|
181
|
+
cc "TDO should be H"
|
182
|
+
jtag.read_dr 0xFFFF, :size => 16, :msg => "Read value out of DR"
|
183
|
+
|
184
|
+
end
|
@@ -0,0 +1,139 @@
|
|
1
|
+
% render "layouts/basic.html" do
|
2
|
+
|
3
|
+
%# HTML tags can be embedded in mark down files if you want to do specific custom
|
4
|
+
%# formatting like this, but in most cases that is not required.
|
5
|
+
<h1><%= Origen.app.namespace %> <span style="font-size: 14px">(<%= Origen.app.version %>)</span></h1>
|
6
|
+
|
7
|
+
### Purpose
|
8
|
+
|
9
|
+
This plugin provides an ATE driver for an IEEE 1149.1 compliant JTAG interface.
|
10
|
+
|
11
|
+
It makes no assumptions about the instruction or data register attributes or higher
|
12
|
+
level protocol concerns. For use at DUT model level this plugin would be normally be wrapped in
|
13
|
+
a higher level protocol such as [Nexus](http://origen-sdk.org/nexus/).
|
14
|
+
|
15
|
+
### How To Import
|
16
|
+
|
17
|
+
In your Gemfile add:
|
18
|
+
|
19
|
+
~~~ruby
|
20
|
+
gem "origen_jtag", ">= <%= Origen.app.version %>"
|
21
|
+
~~~
|
22
|
+
|
23
|
+
or if your application is a plugin add this to your <code>.gemspec</code>
|
24
|
+
|
25
|
+
~~~ruby
|
26
|
+
spec.add_development_dependency "origen_jtag", ">= <%= Origen.app.version %>"
|
27
|
+
~~~
|
28
|
+
|
29
|
+
__NOTE:__ You will also need to include <code>require 'origen_jtag'</code> somewhere in your environment. This can be done in <code>config/environment.rb</code> for example.
|
30
|
+
|
31
|
+
### How To Use
|
32
|
+
|
33
|
+
Include the <code>OrigenJTAG</code> module to add a JTAG driver to your class and
|
34
|
+
define the required pins.
|
35
|
+
Normally the pins would be an alias to existing DUT pins and therefore the
|
36
|
+
JTAG driver module cannot assume them.
|
37
|
+
|
38
|
+
Including the module adds a <code>jtag</code> method which will return an instance of
|
39
|
+
[<code>OrigenJTAG::Driver</code>](<%= path "api/OrigenJTAG/Driver.html" %>).
|
40
|
+
|
41
|
+
The following attributes can be customized by defining a <code>JTAG_CONFIG</code>
|
42
|
+
hash:
|
43
|
+
|
44
|
+
* **tclk_format** - TCLK timing format, Return High (:rh) or Return Low (:rl). Default is :rh.
|
45
|
+
* **tclk_multiple** - Number of cycles for a single TCLK pulse to cover, to support cases where TCLK needs to be a fraction of another clock period. Assumes 50% duty cycle, specify only even numbers if > 1. Default is :r1.
|
46
|
+
* **tdo_strobe** - When using multiple cycles for TCK, which state of TCK to strobe for TDO, :tclk_high or :tclk_low or :tclk_all. Default :tclk_high.
|
47
|
+
* **tdo_store_cycle** - When using multiple cycles for TCK, which cycle of TCK to store for TDO if store requested (0 to number of tclk_multiple-1). Default 0
|
48
|
+
|
49
|
+
Here is an example integration:
|
50
|
+
|
51
|
+
~~~ruby
|
52
|
+
class Pioneer
|
53
|
+
|
54
|
+
include OrigenJTAG
|
55
|
+
include Origen::Pins
|
56
|
+
|
57
|
+
# TCK covers 4 tester cycles, 2 high then 2 low for each effective TCK pulse
|
58
|
+
# Strobe TDO only when TCK high. Only store TDO on last cycle (3)
|
59
|
+
JTAG_CONFIG = {
|
60
|
+
:tclk_format => :rl,
|
61
|
+
:tclk_multiple => 4,
|
62
|
+
:tdo_strobe => :tclk_high,
|
63
|
+
:tdo_store_cycle => 3,
|
64
|
+
}
|
65
|
+
|
66
|
+
def initialize
|
67
|
+
add_pin :tclk
|
68
|
+
add_pin :tdi
|
69
|
+
add_pin :tdo
|
70
|
+
add_pin :tms
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
Pioneer.new.jtag # => An instance of OrigenJTAG::Driver
|
76
|
+
~~~
|
77
|
+
|
78
|
+
Two APIs are provided, the primary one provides canned methods to read and
|
79
|
+
write to the IR and DR registers.
|
80
|
+
|
81
|
+
These accept either an absolute data value or an Origen register/bit collection.
|
82
|
+
|
83
|
+
~~~ruby
|
84
|
+
jtag.write_dr 0x1234, :size => 16
|
85
|
+
# The size option is not required when a register is supplied
|
86
|
+
jtag.write_dr $dut.reg(:clkdiv)
|
87
|
+
# Although it can still be added if the register is not the full data width
|
88
|
+
jtag.write_dr $dut.reg(:clkdiv), :size => 32
|
89
|
+
# A rich read method is available which supports bit-level read, store and
|
90
|
+
# overlay operations
|
91
|
+
$dut.reg(:clkdiv).bits(:div).read(0x55)
|
92
|
+
jtag.read $dut.reg(:clkdiv)
|
93
|
+
# Similar methods exist for the instruction register
|
94
|
+
jtag.write_ir 0x1F, :size => 5
|
95
|
+
jtag.read_ir 0x1F, :size => 5
|
96
|
+
~~~
|
97
|
+
|
98
|
+
A secondary API provides low level control of the TAP Controller state machine.
|
99
|
+
|
100
|
+
~~~ruby
|
101
|
+
jtag.pause_dr do
|
102
|
+
jtag.shift_dr do
|
103
|
+
# The shift method accepts the same arguments as the canned read/write methods
|
104
|
+
jtag.shift 0x55, :size => 32
|
105
|
+
end
|
106
|
+
end
|
107
|
+
~~~
|
108
|
+
|
109
|
+
See the [<code>OrigenJTAG::Driver</code>](<%= path "api/OrigenJTAG/Driver.html" %>) and
|
110
|
+
[<code>OrigenJTAG::TAPController</code>](<%= path "api/OrigenJTAG/TAPController.html" %>)
|
111
|
+
APIs for more details about the available driver methods.
|
112
|
+
|
113
|
+
### How To Setup a Development Environment
|
114
|
+
|
115
|
+
[Clone the repository from Github](https://github.com/Origen-SDK/origen_jtag).
|
116
|
+
|
117
|
+
An instance of the OrigenJTAG driver is hooked up to a dummy DUT
|
118
|
+
object for use in the console:
|
119
|
+
|
120
|
+
~~~
|
121
|
+
origen i
|
122
|
+
|
123
|
+
> $dut.jtag
|
124
|
+
=> #<OrigenJTAG::Driver:0x0000001ee48e78>
|
125
|
+
~~~
|
126
|
+
|
127
|
+
Follow the instructions here if you want to make a 3rd party app
|
128
|
+
workspace use your development copy of the OrigenJTAG plugin:
|
129
|
+
[Setting up a Plugin Development Environment](http://origen-sdk.org/origen/latest/guides/plugins)
|
130
|
+
|
131
|
+
This plugin also contains a test suite, makes sure this passes before committing
|
132
|
+
any changes!
|
133
|
+
|
134
|
+
~~~
|
135
|
+
origen examples
|
136
|
+
~~~
|
137
|
+
|
138
|
+
|
139
|
+
% end
|