code wiki / _hdl_build / nx_jtag_load.nx
nx_jtag_load.nx source
↩ module page · 59 lines · 2866 B
1// nx_jtag_load.nx -- LIB: JTAG bitstream LOADER (omniforge SI M5 = the OpenOCD replacement, sim). Models the REAL
2// IEEE 1149.1 TAP state machine (16 states, TMS-driven) and loads a bitstream into a config Data Register via
3// Shift-DR -> Update-DR -- exactly how OpenOCD drives an FPGA. The twin property: the bits shifted in arrive in
4// config faithfully, and the configured fabric runs the design. never-brick #26: VOLATILE config (an SRAM model, no
5// persistent/flash write -> a power cycle clears it, can't brick BY CONSTRUCTION), bounded, deterministic. license_tier: ORIGINAL
6import "nx_syscalls.nx"
7
8// TAP states: 0 TLR 1 RTI 2 SelDR 3 CapDR 4 ShiftDR 5 Exit1DR 6 PauseDR 7 Exit2DR 8 UpdateDR
9// 9 SelIR 10 CapIR 11 ShiftIR 12 Exit1IR 13 PauseIR 14 Exit2IR 15 UpdateIR
10func tap_next(state: i64, tms: i64) -> i64 {
11 if state==0 { if tms==0 { return 1 } return 0 }
12 if state==1 { if tms==0 { return 1 } return 2 }
13 if state==2 { if tms==0 { return 3 } return 9 }
14 if state==3 { if tms==0 { return 4 } return 5 }
15 if state==4 { if tms==0 { return 4 } return 5 }
16 if state==5 { if tms==0 { return 6 } return 8 }
17 if state==6 { if tms==0 { return 6 } return 7 }
18 if state==7 { if tms==0 { return 4 } return 8 }
19 if state==8 { if tms==0 { return 1 } return 2 }
20 if state==9 { if tms==0 { return 10 } return 0 }
21 if state==10 { if tms==0 { return 11 } return 12 }
22 if state==11 { if tms==0 { return 11 } return 12 }
23 if state==12 { if tms==0 { return 13 } return 15 }
24 if state==13 { if tms==0 { return 13 } return 14 }
25 if state==14 { if tms==0 { return 11 } return 15 }
26 if state==15 { if tms==0 { return 1 } return 2 }
27 return 0
28}
29
30// drive nclk TCKs from Test-Logic-Reset; capture TDI into dr_out while in Shift-DR. Returns final state; shifted_out[0] = # bits captured.
31func jtag_run(tms: *i64, tdi: *i64, nclk: i64, dr_out: *i64, shifted_out: *i64) -> i64 {
32 var state: i64 = 0
33 var sh: i64 = 0
34 var c: i64 = 0
35 while c < nclk {
36 if state == 4 { dr_out[sh] = tdi[c]; sh = sh + 1 }
37 state = tap_next(state, tms[c])
38 c = c + 1
39 }
40 shifted_out[0] = sh
41 return state
42}
43
44// build the TMS/TDI clock sequence to load nbits from TLR: TLR->RTI->SelDR->CapDR->ShiftDR, shift nbits, Exit1->UpdateDR. Returns nclk.
45func jtag_build_load(nbits: i64, bits: *i64, tms: *i64, tdi: *i64) -> i64 {
46 var c: i64 = 0
47 tms[c]=0; tdi[c]=0; c=c+1 // TLR -> RTI
48 tms[c]=1; tdi[c]=0; c=c+1 // RTI -> SelDR
49 tms[c]=0; tdi[c]=0; c=c+1 // SelDR -> CapDR
50 tms[c]=0; tdi[c]=0; c=c+1 // CapDR -> ShiftDR
51 var i: i64 = 0
52 while i < nbits {
53 if i == nbits-1 { tms[c]=1 } else { tms[c]=0 } // last bit exits Shift-DR
54 tdi[c]=bits[i]; c=c+1
55 i=i+1
56 }
57 tms[c]=1; tdi[c]=0; c=c+1 // Exit1DR -> UpdateDR
58 return c
59}