├── .gitattributes ├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── s6prog.c /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | 46 | [Dd]ebug/ 47 | [Rr]elease/ 48 | x64/ 49 | build/ 50 | [Bb]in/ 51 | [Oo]bj/ 52 | 53 | # MSTest test Results 54 | [Tt]est[Rr]esult*/ 55 | [Bb]uild[Ll]og.* 56 | 57 | *_i.c 58 | *_p.c 59 | *.ilk 60 | *.meta 61 | *.obj 62 | *.pch 63 | *.pdb 64 | *.pgc 65 | *.pgd 66 | *.rsp 67 | *.sbr 68 | *.tlb 69 | *.tli 70 | *.tlh 71 | *.tmp 72 | *.tmp_proj 73 | *.log 74 | *.vspscc 75 | *.vssscc 76 | .builds 77 | *.pidb 78 | *.log 79 | *.scc 80 | 81 | # Visual C++ cache files 82 | ipch/ 83 | *.aps 84 | *.ncb 85 | *.opensdf 86 | *.sdf 87 | *.cachefile 88 | 89 | # Visual Studio profiler 90 | *.psess 91 | *.vsp 92 | *.vspx 93 | 94 | # Guidance Automation Toolkit 95 | *.gpState 96 | 97 | # ReSharper is a .NET coding add-in 98 | _ReSharper*/ 99 | *.[Rr]e[Ss]harper 100 | 101 | # TeamCity is a build add-in 102 | _TeamCity* 103 | 104 | # DotCover is a Code Coverage Tool 105 | *.dotCover 106 | 107 | # NCrunch 108 | *.ncrunch* 109 | .*crunch*.local.xml 110 | 111 | # Installshield output folder 112 | [Ee]xpress/ 113 | 114 | # DocProject is a documentation generator add-in 115 | DocProject/buildhelp/ 116 | DocProject/Help/*.HxT 117 | DocProject/Help/*.HxC 118 | DocProject/Help/*.hhc 119 | DocProject/Help/*.hhk 120 | DocProject/Help/*.hhp 121 | DocProject/Help/Html2 122 | DocProject/Help/html 123 | 124 | # Click-Once directory 125 | publish/ 126 | 127 | # Publish Web Output 128 | *.Publish.xml 129 | *.pubxml 130 | 131 | # NuGet Packages Directory 132 | ## TODO: If you have NuGet Package Restore enabled, uncomment the next line 133 | #packages/ 134 | 135 | # Windows Azure Build Output 136 | csx 137 | *.build.csdef 138 | 139 | # Windows Store app package directory 140 | AppPackages/ 141 | 142 | # Others 143 | sql/ 144 | *.Cache 145 | ClientBin/ 146 | [Ss]tyle[Cc]op.* 147 | ~$* 148 | *~ 149 | *.dbmdl 150 | *.[Pp]ublish.xml 151 | *.pfx 152 | *.publishsettings 153 | 154 | # RIA/Silverlight projects 155 | Generated_Code/ 156 | 157 | # Backup & report files from converting an old project file to a newer 158 | # Visual Studio version. Backup files are not needed, because we have git ;-) 159 | _UpgradeReport_Files/ 160 | Backup*/ 161 | UpgradeLog*.XML 162 | UpgradeLog*.htm 163 | 164 | # SQL Server files 165 | App_Data/*.mdf 166 | App_Data/*.ldf 167 | 168 | ############# 169 | ## Windows detritus 170 | ############# 171 | 172 | # Windows image file caches 173 | Thumbs.db 174 | ehthumbs.db 175 | 176 | # Folder config file 177 | Desktop.ini 178 | 179 | # Recycle Bin used on file shares 180 | $RECYCLE.BIN/ 181 | 182 | # Mac crap 183 | .DS_Store 184 | 185 | 186 | ############# 187 | ## Python 188 | ############# 189 | 190 | *.py[co] 191 | 192 | # Packages 193 | *.egg 194 | *.egg-info 195 | dist/ 196 | build/ 197 | eggs/ 198 | parts/ 199 | var/ 200 | sdist/ 201 | develop-eggs/ 202 | .installed.cfg 203 | 204 | # Installer logs 205 | pip-log.txt 206 | 207 | # Unit test / coverage reports 208 | .coverage 209 | .tox 210 | 211 | #Translations 212 | *.mo 213 | 214 | #Mr Developer 215 | .mr.developer.cfg 216 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Liam Davey 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | all: 2 | gcc -Wall -O2 -g -o s6prog s6prog.c -lusb -lftdi 3 | 4 | clean: 5 | rm -rf p 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Spartan 6 Programmer 2 | ==================== 3 | 4 | An application to program a Spartan 6 FPGA over JTAG using an FTDI FT232H chip. 5 | 6 | It takes a ".bin" file as input, which can be output from Xilinx ISE. 7 | -------------------------------------------------------------------------------- /s6prog.c: -------------------------------------------------------------------------------- 1 | /* 2 | Programs a Spartan 6 FPGA over JTAG using an FTDI FT232H chip. 3 | 4 | Takes a ".bin" file as input, which can be output from ISE. 5 | */ 6 | 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #define CLK_DIV_5_DISABLE (0x8a) 16 | #define CLK_DIV_5_ENABLE (0x8b) 17 | #define DATA_CLK_3_PHASE_ENABLE (0x8c) 18 | #define DATA_CLK_3_PHASE_DISABLE (0x8d) 19 | #define DATA_CLK_BITS (0x8e) 20 | #define DATA_CLK_BYTES (0x8f) 21 | #define ADAPTIVE_CLK_ENABLE (0x96) 22 | #define ADAPTIVE_CLK_DISABLE (0x97) 23 | 24 | #define JTAG_INSTR_ISC_DNA (0x30) // (110000b) 25 | #define JTAG_INSTR_ISC_DISABLE (0x16) // (010110b) 26 | #define JTAG_INSTR_ISC_NOOP (0x14) // (010100b) 27 | #define JTAG_INSTR_ISC_PROGRAM (0x11) // (010001b) 28 | #define JTAG_INSTR_ISC_ENABLE (0x10) // (010000b) 29 | #define JTAG_INSTR_BYPASS (0x3f) // (111111b) 30 | #define JTAG_INSTR_JSHUTDOWN (0x0d) // (001101b) 31 | #define JTAG_INSTR_JSTART (0x0c) // (001100b) 32 | #define JTAG_INSTR_JPROGRAM (0x0b) // (001011b) 33 | #define JTAG_INSTR_HIGHZ (0x0a) // (001010b) 34 | #define JTAG_INSTR_IDCODE (0x09) // (001001b) 35 | #define JTAG_INSTR_USERCODE (0x08) // (001000b) 36 | #define JTAG_INSTR_INTEST (0x07) // (000111b) 37 | #define JTAG_INSTR_PRELOAD (0x01) // (000001b) 38 | #define JTAG_INSTR_SAMPLE (0x01) // (000001b) 39 | #define JTAG_INSTR_EXTEST (0x0f) // (001111b) 40 | #define JTAG_INSTR_CFG_IN (0x05) // (000101b) 41 | 42 | #define FDATA_SIZE (16 * 1024 * 1024) 43 | #define JTAG_BUFFER_SIZE (1024 * 1024) 44 | #define JTAG_CHUNK_SIZE (0x8000) 45 | #define JTAG_RECV_ATTEMPTS (20) 46 | #define JTAG_STARTUP_DELAY (500) 47 | #define JTAG_SHUTDOWN_DELAY (500) 48 | #define JTAG_TCK_DIVISOR_LOW (0) 49 | 50 | /* 51 | FT2232H pin definitions 52 | 53 | pin | name | mpsse function 54 | -------+-----------+--------------- 55 | 13 | ADBUS0 | TCK 56 | 14 | ADBUS1 | TDI 57 | 15 | ADBUS2 | TDO 58 | 16 | ADBUS3 | TMS 59 | 17 | ADBUS4 | GPIOL0 60 | 18 | ADBUS5 | GPIOL1 61 | 19 | ADBUS6 | GPIOL2 62 | 20 | ADBUS7 | GPIOL3 63 | | | 64 | 21 | ACBUS0 | GPIOH0 65 | 25 | ACBUS1 | GPIOH1 66 | 26 | ACBUS2 | GPIOH2 67 | 27 | ACBUS3 | GPIOH3 68 | 28 | ACBUS4 | GPIOH4 69 | 29 | ACBUS5 | GPIOH5 70 | 30 | ACBUS6 | GPIOH6 71 | 31 | ACBUS7 | GPIOH7 72 | 73 | 0 is LSB, 7 is MSB 74 | 75 | 76 | *** MPSSE mode commands *** 77 | 78 | * SET_BITS_LOW, data, direction 79 | sets low port bits and direction 80 | * SET_BITS_HIGH, data, direction 81 | sets high port bits and direction 82 | * TCK_DIVISOR, div_low, div_high 83 | sets the TCK divisor to {div_high, div_low} 84 | rate = 60e6 / ((value + 1) * 2) 85 | * SEND_IMMEDIATE 86 | immediately send whatever data is in the ftdi device's buffer to 87 | the host. 88 | 89 | 90 | *** MPSSE shifting commands *** 91 | 92 | bit mode format: 93 | {shifting command, 94 | length in bits, 95 | data byte} 96 | 97 | byte mode format: 98 | {shifting command, 99 | length in bytes high, 100 | length in bytes low, 101 | data byte 0, 102 | ..., 103 | data byte n} 104 | 105 | shifting command byte: 106 | MPSSE_WRITE_NEG 0x01 Write TDI/DO on negative TCK/SK edge 107 | MPSSE_BITMODE 0x02 Write bits, not bytes 108 | MPSSE_READ_NEG 0x04 Sample TDO/DI on negative TCK/SK edge 109 | MPSSE_LSB 0x08 LSB first 110 | MPSSE_DO_WRITE 0x10 Write TDI/DO 111 | MPSSE_DO_READ 0x20 Read TDO/DI 112 | MPSSE_WRITE_TMS 0x40 Write TMS/CS 113 | 114 | * MPSSE_DO_WRITE and MPSSE_WRITE_TMS cannot both be set 115 | * cannot read and write on the same clock edge 116 | 117 | */ 118 | 119 | 120 | //////////////////////////////////////////////////////////////////////// 121 | // low level jtag and ftdi device functions 122 | //////////////////////////////////////////////////////////////////////// 123 | 124 | 125 | unsigned char * jtag_buf = NULL; 126 | int jtag_buf_i = 0; 127 | struct ftdi_context ftdi; 128 | 129 | int jtag_send() 130 | { 131 | //int i; 132 | 133 | if(jtag_buf_i < 1) 134 | return 1; 135 | 136 | //printf("jtag_send %d bytes:\n", jtag_buf_i); 137 | //for(i = 0; (i < jtag_buf_i); i++) 138 | // printf("%02x ", jtag_buf[i]); 139 | //printf("\n"); 140 | 141 | int l = ftdi_write_data(&ftdi, jtag_buf, jtag_buf_i); 142 | if(l != jtag_buf_i) 143 | { 144 | //printf("error: jtag_send: ftdi_write_data returned %d (expected %d)\n", l, jtag_buf_i); 145 | return 1; 146 | } 147 | jtag_buf_i = 0; 148 | return 0; 149 | } 150 | 151 | int jtag_recv(unsigned char * rbuf, int n) 152 | { 153 | int timeout = JTAG_RECV_ATTEMPTS, ret; 154 | //unsigned char * rbuf2 = rbuf; 155 | unsigned char buf[32]; 156 | while(n > 0) 157 | { 158 | if(rbuf != NULL) 159 | { 160 | ret = ftdi_read_data(&ftdi, rbuf, n); 161 | rbuf += ret; 162 | } 163 | else 164 | ret = ftdi_read_data(&ftdi, buf, 32); 165 | 166 | n -= ret; 167 | 168 | if(timeout-- <= 0) 169 | { 170 | //printf("error: jtag_recv: timed out with %d byte remaining\n", n); 171 | break; 172 | } 173 | } 174 | 175 | //printf("jtag_recv: "); 176 | //while(rbuf2 < rbuf) 177 | // printf("%02x ", *rbuf2++); 178 | //printf("\n"); 179 | 180 | return n; 181 | } 182 | 183 | // close and deinitialize ftdi device 184 | void jtag_close() 185 | { 186 | if(jtag_buf != NULL) 187 | free(jtag_buf); 188 | jtag_buf = NULL; 189 | ftdi_usb_purge_buffers(&ftdi); 190 | ftdi_usb_reset(&ftdi); 191 | ftdi_usb_close(&ftdi); 192 | ftdi_deinit(&ftdi); 193 | } 194 | 195 | // initialize ftdi device for jtag 196 | int jtag_init() 197 | { 198 | int ret; 199 | 200 | if((jtag_buf = malloc(JTAG_BUFFER_SIZE)) == NULL) 201 | { 202 | printf("error: jtag_init: could not malloc jtag_buf\n"); 203 | return 1; 204 | } 205 | 206 | // initialize ftdi data structure and open the ftdi device with 207 | // VID:PID = 0403:6014 208 | ftdi_init(&ftdi); 209 | if(ftdi_usb_open_desc(&ftdi, 0x0403, 0x6014, 0, 0) < 0) 210 | { 211 | printf("error: could not open ftdi device\n"); 212 | ftdi_deinit(&ftdi); 213 | return 1; 214 | } 215 | 216 | // reset ftdi device 217 | ret = ftdi_usb_reset(&ftdi); 218 | 219 | // use interface A 220 | //ret += ftdi_set_interface(&ftdi, INTERFACE_A); 221 | 222 | // 1ms latency timer 223 | ret += ftdi_set_latency_timer(&ftdi, 1); 224 | 225 | // purge buffers 226 | ret += ftdi_usb_purge_buffers(&ftdi); 227 | 228 | // set bit mode to MPSSE, 0xfb bitmask sets all bits except for 229 | // TDO to output 230 | ret += ftdi_set_bitmode(&ftdi, 0x00, 0x00); 231 | ret += ftdi_set_bitmode(&ftdi, 0x0b, BITMODE_MPSSE); 232 | 233 | if(ret < 0) 234 | { 235 | printf("error: jtag_init: ftdi device config failed\n"); 236 | return 1; 237 | } 238 | 239 | jtag_buf_i = 0; 240 | 241 | // set TMS high, TCK low, TDI low and TDO as input 242 | jtag_buf[jtag_buf_i++] = SET_BITS_LOW; 243 | jtag_buf[jtag_buf_i++] = 0x08; 244 | jtag_buf[jtag_buf_i++] = 0x0b; 245 | 246 | // set all pins of the high port to inputs 247 | jtag_buf[jtag_buf_i++] = SET_BITS_HIGH; 248 | jtag_buf[jtag_buf_i++] = 0x00; 249 | jtag_buf[jtag_buf_i++] = 0x00; 250 | 251 | // disable the divide by 5 clock prescaler 252 | jtag_buf[jtag_buf_i++] = CLK_DIV_5_DISABLE; 253 | 254 | // set the TCK rate to 30MHz 255 | jtag_buf[jtag_buf_i++] = TCK_DIVISOR; 256 | jtag_buf[jtag_buf_i++] = JTAG_TCK_DIVISOR_LOW; 257 | jtag_buf[jtag_buf_i++] = 0x00; 258 | 259 | // disable 3 phase data clocking 260 | jtag_buf[jtag_buf_i++] = DATA_CLK_3_PHASE_DISABLE; 261 | 262 | // disable adaptive clocking 263 | jtag_buf[jtag_buf_i++] = ADAPTIVE_CLK_DISABLE; 264 | 265 | // flush ftdi buffer 266 | jtag_buf[jtag_buf_i++] = SEND_IMMEDIATE; 267 | 268 | if(jtag_send()) 269 | { 270 | printf("error: jtag_init: could not send initialization commands\n"); 271 | jtag_close(); 272 | return 1; 273 | } 274 | 275 | return 0; 276 | } 277 | 278 | #define jtag_add_send_immediate() (jtag_buf[jtag_buf_i++] = SEND_IMMEDIATE) 279 | 280 | // go to test logic reset state 281 | void jtag_to_tlr() 282 | { 283 | // TMS: 11111 284 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 285 | jtag_buf[jtag_buf_i++] = 4; 286 | jtag_buf[jtag_buf_i++] = 0x9f; 287 | } 288 | 289 | // go to rti state from tlr state 290 | void jtag_tlr_to_rti() 291 | { 292 | // TMS: 0 293 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 294 | jtag_buf[jtag_buf_i++] = 0; 295 | jtag_buf[jtag_buf_i++] = 0x80; 296 | } 297 | 298 | // spin in run-test-idle state for 128 * 8 TCK cycles 299 | void jtag_rti_spin() 300 | { 301 | int n; 302 | 303 | // set TMS to 0 304 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 305 | jtag_buf[jtag_buf_i++] = 0; 306 | jtag_buf[jtag_buf_i++] = 0x80; 307 | 308 | // run TCK for 128 * 8 cycles 309 | for(n = 0; n < 128; n++) 310 | { 311 | jtag_buf[jtag_buf_i++] = DATA_CLK_BITS; 312 | jtag_buf[jtag_buf_i++] = 7; 313 | } 314 | 315 | jtag_send(); 316 | } 317 | 318 | // go to shift-ir state from rti state 319 | void jtag_rti_to_shift_ir() 320 | { 321 | // RTI -> SHIFT-IR 322 | // TMS: 0011 323 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 324 | jtag_buf[jtag_buf_i++] = 3; 325 | jtag_buf[jtag_buf_i++] = 0x83; 326 | } 327 | 328 | // go to shift-dr state from rti state 329 | void jtag_rti_to_shift_dr() 330 | { 331 | // RTI -> SHIFT-DR 332 | // TMS: 001 333 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 334 | jtag_buf[jtag_buf_i++] = 2; 335 | jtag_buf[jtag_buf_i++] = 0x81; 336 | } 337 | 338 | void jtag_exit1_ir_to_rti() 339 | { 340 | // EXIT1-IR -> RTI 341 | // TMS: 01 342 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 343 | jtag_buf[jtag_buf_i++] = 1; 344 | jtag_buf[jtag_buf_i++] = 0x81; 345 | } 346 | 347 | void jtag_exit1_dr_to_rti() 348 | { 349 | // EXIT1-DR -> RTI 350 | // TMS: 01 351 | jtag_buf[jtag_buf_i++] = MPSSE_WRITE_TMS | MPSSE_LSB | MPSSE_BITMODE | MPSSE_WRITE_NEG; 352 | jtag_buf[jtag_buf_i++] = 1; 353 | jtag_buf[jtag_buf_i++] = 0x81; 354 | } 355 | 356 | // add commands to jtag_buf to shift out 'n' bytes from 'tdi'. 357 | // if do_read is set then make the command read while shifting out. 358 | // assumes tap already in shift-dr or shift-ir state. 359 | void jtag_shift_bytes(unsigned char * tdi, int n, int do_read) 360 | { 361 | int i; 362 | 363 | // command byte 364 | jtag_buf[jtag_buf_i] = MPSSE_LSB; 365 | if(tdi != NULL) 366 | jtag_buf[jtag_buf_i] |= MPSSE_DO_WRITE | MPSSE_WRITE_NEG; 367 | if(do_read) 368 | jtag_buf[jtag_buf_i] |= MPSSE_DO_READ; 369 | jtag_buf_i++; 370 | 371 | // two byte length 372 | jtag_buf[jtag_buf_i++] = ((n - 1) & 0xff); 373 | jtag_buf[jtag_buf_i++] = ((n - 1) >> 8) & 0xff; 374 | 375 | // data bytes if writing 376 | if(tdi != NULL) 377 | for(i = 0; i < n; i++) 378 | jtag_buf[jtag_buf_i++] = tdi[i]; 379 | } 380 | 381 | // shift 'n' bits of data onto TDI 382 | // assumes tap already in shift-dr or shift-ir state. 383 | 384 | void jtag_shift_bits(unsigned char * tdi, int n, int do_read) 385 | { 386 | // if more than one bits need to be shifted 387 | if(n > 1) 388 | { 389 | // command byte 390 | jtag_buf[jtag_buf_i] = MPSSE_BITMODE | MPSSE_LSB; 391 | if(tdi != NULL) 392 | jtag_buf[jtag_buf_i] |= MPSSE_DO_WRITE | MPSSE_WRITE_NEG; 393 | if(do_read) 394 | jtag_buf[jtag_buf_i] |= MPSSE_DO_READ; 395 | jtag_buf_i++; 396 | 397 | // number of bits 398 | jtag_buf[jtag_buf_i++] = (n - 2); 399 | 400 | // data byte (last byte of buffer) 401 | if(tdi != NULL) 402 | jtag_buf[jtag_buf_i++] = *tdi & ((1 << (n - 1)) - 1); 403 | } 404 | 405 | // shift the final bit 406 | jtag_buf[jtag_buf_i] = MPSSE_WRITE_TMS | MPSSE_BITMODE | MPSSE_LSB | MPSSE_WRITE_NEG; 407 | if(do_read) 408 | jtag_buf[jtag_buf_i] |= MPSSE_DO_READ; 409 | jtag_buf_i++; 410 | 411 | // shift one bit 412 | jtag_buf[jtag_buf_i++] = 0; 413 | 414 | // MSB is value to set TDI to 415 | // LSB is TMS value (=1) 416 | if(tdi != NULL) 417 | jtag_buf[jtag_buf_i++] = (*tdi & (1 << (n - 1))) ? 0x81 : 0x01; 418 | else 419 | jtag_buf[jtag_buf_i++] = 0x01; 420 | } 421 | 422 | // receive bits from ftdi device 423 | // combines the bits if they were transferred in separate commands 424 | int jtag_recv_bits(unsigned char * tdo, int n) 425 | { 426 | unsigned char rbuf[2]; 427 | 428 | if((n < 1) || (n > 8)) 429 | return 1; 430 | 431 | if(jtag_recv(rbuf, (n > 1) ? 2 : 1)) 432 | { 433 | printf("error: jtag_read_bits: could not recv bytes\n"); 434 | return 1; 435 | } 436 | 437 | // if more than one bits were shifted then we need to add the 438 | // final bit received to the correct position in the prior bits. 439 | if(n > 1) 440 | { 441 | // bits are shifted in from the left (MSB) so if less than 8 442 | // bits were shifted then need to shift the bits in the 443 | // received byte right by 8 - n bits. 444 | *tdo = ((rbuf[1] & 0x80) | (rbuf[0] >> 1)) >> (8 - n); 445 | } else 446 | // if only 1 bit received 447 | *tdo = (rbuf[0] & 0x80) >> 7; 448 | 449 | return 0; 450 | } 451 | 452 | // read and/or write data register 453 | // n is length of data in bits. 454 | // this attempts to send and receive in one transfer if possible 455 | int jtag_dr_op(unsigned char * tdi, unsigned char * tdo, int n) 456 | { 457 | int bytes_remaining, bits_remaining, chunk_length; 458 | int tdi_i, tdo_i; 459 | 460 | if((tdi == NULL) && (tdo == NULL)) 461 | return 1; 462 | 463 | // go to shift dr state 464 | jtag_rti_to_shift_dr(); 465 | 466 | // number of whole bytes that need to be shifted out 467 | bytes_remaining = (n - 1) / 8; 468 | // number of bits that need to be shifted out 469 | // this should only ever be between 1 and 8 inclusive 470 | bits_remaining = n - (bytes_remaining * 8); 471 | 472 | tdi_i = 0; 473 | tdo_i = 0; 474 | chunk_length = 0; 475 | 476 | while(bytes_remaining > 0) 477 | { 478 | // shift out/in a maximum number bytes at a time 479 | chunk_length = (bytes_remaining > JTAG_CHUNK_SIZE) ? JTAG_CHUNK_SIZE : bytes_remaining; 480 | 481 | //printf("chunk_length %d\n", chunk_length); 482 | 483 | // shift the chunk through the data register 484 | if(tdi != NULL) 485 | { 486 | jtag_shift_bytes(&tdi[tdi_i], chunk_length, (tdo != NULL)); 487 | tdi_i += chunk_length; 488 | } else 489 | jtag_shift_bytes(NULL, chunk_length, (tdo != NULL)); 490 | 491 | bytes_remaining -= chunk_length; 492 | 493 | // if there is still another chunk to transfer then need to 494 | // send this chunk and read in any data before sending the next 495 | if(bytes_remaining > 0) 496 | { 497 | if(jtag_send()) 498 | { 499 | printf("error: jtag_shift_dr: could not send bytes for chunk\n"); 500 | return 1; 501 | } 502 | 503 | if(tdo != NULL) 504 | { 505 | if(jtag_recv(&tdo[tdo_i], chunk_length)) 506 | { 507 | printf("error: jtag_shift_dr: could not receive bytes for chunk\n"); 508 | return 1; 509 | } 510 | tdo_i += chunk_length; 511 | } 512 | } 513 | } 514 | 515 | // shift the remaining bits 516 | if(bits_remaining > 0) 517 | { 518 | if(tdi != NULL) 519 | jtag_shift_bits(&tdi[tdi_i], bits_remaining, (tdo != NULL)); 520 | else 521 | jtag_shift_bits(NULL, bits_remaining, (tdo != NULL)); 522 | } 523 | 524 | // back to rti state 525 | jtag_exit1_dr_to_rti(); 526 | 527 | // send the last chunk 528 | if(jtag_send()) 529 | { 530 | printf("error: jtag_shift_dr: could not send bytes for last chunk\n"); 531 | return 1; 532 | } 533 | 534 | // now receive the bytes from the last chunk sent and any bits 535 | if(tdo != NULL) 536 | { 537 | // if chunk_length is 0 it means that only bits were sent 538 | if(chunk_length > 0) 539 | { 540 | if(jtag_recv(&tdo[tdo_i], chunk_length)) 541 | { 542 | printf("error: jtag_shift_dr: could not receive bytes for the last chunk\n"); 543 | return 1; 544 | } 545 | tdo_i += chunk_length; 546 | } 547 | 548 | if(bits_remaining > 0) 549 | { 550 | if(jtag_recv_bits(&tdo[tdo_i], bits_remaining)) 551 | { 552 | printf("error: jtag_shift_dr: could not receive bits for the last chunk\n"); 553 | return 1; 554 | } 555 | tdo_i++; 556 | } 557 | } 558 | 559 | return 0; 560 | } 561 | 562 | //////////////////////////////////////////////////////////////////////// 563 | // high level functions 564 | //////////////////////////////////////////////////////////////////////// 565 | 566 | #define jtag_dr_write(tdi, n) (jtag_dr_op(tdi, NULL, n)) 567 | #define jtag_dr_read(tdo, n) (jtag_dr_op(NULL, tdo, n)) 568 | #define jtag_dr_rw(tdi, tdo, n) (jtag_dr_op(tdi, tdo, n)) 569 | 570 | // shift in 6 bit instruction 571 | void jtag_ir_write(unsigned char instruction) 572 | { 573 | jtag_rti_to_shift_ir(); 574 | jtag_shift_bits(&instruction, 6, 0); 575 | jtag_exit1_ir_to_rti(); 576 | } 577 | 578 | // sends an invalid command to the ftdi device and checks to see if it 579 | // replies with the correct sequence. 580 | int jtag_mpsse_sync() 581 | { 582 | int ret; 583 | unsigned char buf[2]; 584 | // load an invalid instruction 585 | jtag_buf[jtag_buf_i++] = 0xaa; 586 | jtag_send(); 587 | ret = jtag_recv(buf, 2); 588 | return (ret | (buf[0] != 0xfa) | (buf[1] != 0xaa)); 589 | } 590 | 591 | // read jtag idcode 592 | int jtag_get_idcode(int * idcode) 593 | { 594 | unsigned char buf[4]; 595 | 596 | // shift in IDCODE instruction 597 | jtag_ir_write(JTAG_INSTR_IDCODE); 598 | 599 | if(jtag_dr_read(buf, 32)) 600 | return 1; 601 | 602 | *idcode = (buf[3] << 24) | (buf[2] << 16) | (buf[1] << 8) | buf[0]; 603 | 604 | return 0; 605 | } 606 | 607 | // swap the bits in the byte 'c' points to 608 | void bit_swap(unsigned char * c) 609 | { 610 | *c = ((*c & 0xf0) >> 4) | ((*c & 0x0f) << 4); 611 | *c = ((*c & 0xcc) >> 2) | ((*c & 0x33) << 2); 612 | *c = ((*c & 0xaa) >> 1) | ((*c & 0x55) << 1); 613 | } 614 | 615 | unsigned char * fdata = NULL; 616 | int flength = 0; 617 | 618 | // malloc fdata and read from stdin 619 | int load_fdata(char * filename) 620 | { 621 | int i; 622 | FILE * fin; 623 | 624 | if(fdata == NULL) 625 | fdata = malloc(FDATA_SIZE); 626 | if(fdata == NULL) 627 | return 1; 628 | 629 | fin = fopen(filename, "rb"); 630 | 631 | if(fin == NULL) 632 | return 1; 633 | 634 | flength = fread(fdata, 1, FDATA_SIZE, fin); 635 | 636 | fclose(fin); 637 | 638 | if((flength < 1) || (flength >= FDATA_SIZE)) 639 | return 1; 640 | 641 | for(i = 0; i < flength; i++) 642 | bit_swap(&fdata[i]); 643 | 644 | return 0; 645 | } 646 | 647 | //////////////////////////////////////////////////////////////////////// 648 | // main routine and exit function for cleaning up 649 | //////////////////////////////////////////////////////////////////////// 650 | 651 | int main_exit(int ret, char * s) 652 | { 653 | if(ret) 654 | printf("error: main: %s\n", s); 655 | else 656 | printf("%s\n", s); 657 | 658 | if(fdata != NULL) 659 | { 660 | free(fdata); 661 | fdata = NULL; 662 | } 663 | jtag_to_tlr(); 664 | jtag_send(); 665 | jtag_close(); 666 | return ret; 667 | } 668 | 669 | int main(int argc, char * argv[]) 670 | { 671 | int idcode, i; 672 | unsigned char c[2]; 673 | 674 | if(argc < 2) 675 | { 676 | printf("usage: %s \n", argv[0]); 677 | return 1; 678 | } 679 | 680 | // initialize ftdi device for jtag 681 | if(jtag_init()) 682 | { 683 | printf("error: jtag_init failed\n"); 684 | return 1; 685 | } 686 | 687 | if(jtag_mpsse_sync()) 688 | return main_exit(1, "could not sync mpsse controller"); 689 | 690 | printf("testing 1 byte transfer, send 0xaa\n"); 691 | c[0] = 0xaa; 692 | if(ftdi_write_data(&ftdi, c, 1) < 0) 693 | return main_exit(1, "ftdi write 1 byte failed"); 694 | jtag_recv(c, 2); 695 | printf("receive 0x%02x 0x%02x\n", c[0], c[1]); 696 | 697 | 698 | // put jtag tap into TLR state 699 | jtag_to_tlr(); 700 | 701 | // put jtag tap into RTI state 702 | jtag_tlr_to_rti(); 703 | 704 | if(jtag_get_idcode(&idcode)) 705 | return main_exit(1, "could not get idcode"); 706 | 707 | printf("idcode = 0x%08x\n", idcode); 708 | 709 | // check company code and family sections of idcode 710 | if((idcode & 0x001fffff) != 0x00008093) 711 | return main_exit(1, "non xilinx fpga device id"); 712 | 713 | // load file data 714 | if(load_fdata(argv[1])) 715 | return main_exit(1, "could not load data from file"); 716 | 717 | // enable in system configuration 718 | jtag_ir_write(JTAG_INSTR_JSHUTDOWN); 719 | 720 | // spin in RTI waiting for FPGA to shut down 721 | for(i = 0; i < JTAG_SHUTDOWN_DELAY; i++) 722 | jtag_rti_spin(); 723 | 724 | // load CFG_IN instruction 725 | jtag_ir_write(JTAG_INSTR_CFG_IN); 726 | 727 | // write fdata to data register 728 | if(jtag_dr_write(fdata, flength * 8)) 729 | return main_exit(1, "could not write configuration to data register"); 730 | 731 | printf("sent %d configuration bytes to fpga\n", flength); 732 | 733 | // disable in system configuration 734 | jtag_ir_write(JTAG_INSTR_JSTART); 735 | 736 | // spin in RTI waiting for FPGA to restart 737 | for(i = 0; i < JTAG_STARTUP_DELAY; i++) 738 | jtag_rti_spin(); 739 | 740 | // put jtag into TLR state 741 | jtag_to_tlr(); 742 | 743 | if(jtag_send()) 744 | return main_exit(1, "could not disable isc"); 745 | 746 | return main_exit(0, "configuration complete"); 747 | } 748 | --------------------------------------------------------------------------------