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}