From e8a6d6d2c0cd6cbe134041ae3d875610f0a2eaf6 Mon Sep 17 00:00:00 2001 From: Wanda Date: Sat, 9 Dec 2023 23:40:28 +0000 Subject: [PATCH] xc9500xl docs --- docs/xc9500/bitstream-xc9500xl.rst | 3 +- docs/xc9500/jtag.rst | 372 ++++++++++++++++++++++++----- 2 files changed, 309 insertions(+), 66 deletions(-) diff --git a/docs/xc9500/bitstream-xc9500xl.rst b/docs/xc9500/bitstream-xc9500xl.rst index 15319e1f..0fa90b2d 100644 --- a/docs/xc9500/bitstream-xc9500xl.rst +++ b/docs/xc9500/bitstream-xc9500xl.rst @@ -25,8 +25,9 @@ the high 2 bits of columns 0-8 are used to store everything else. When programmed or read via JTAG, the bitstream is transmitted as words. Each word is 8 bits per FB. Each word of the bitstream has its address. Not all addresses are valid, and valid addresses are not contiguous. -Address is 12 bits long, and is split to several fields: +Address is 16 bits long, and is split to several fields: +- bits 12-15: FB index (only used for JTAG ``FERASE`` operation, doesn't matter for reading and programming) - bits 5-11: row - bits 3-4: column / 5 - bits 0-2: column % 5 diff --git a/docs/xc9500/jtag.rst b/docs/xc9500/jtag.rst index b8ef7d9f..fda1c087 100644 --- a/docs/xc9500/jtag.rst +++ b/docs/xc9500/jtag.rst @@ -103,22 +103,23 @@ The following DR registers exist on XC9500: - bit ``num_fbs``: when set, powers up flash access circuitry for the UIM wire-AND area - bits ``num_fbs + 1`` - ``num_fbs + 3``: unknown, set to 0 -2. ``ISPCONFIGURATION`` (27 bits): used to load and store bitstream bytes +2. ``ISPCONFIGURATION`` (27 bits): used to trigger programming operations + + - bits 0-1: control + + - ``0b10``: trigger value, starts the operation + - ``0b11``: neutral value and successful result - - bit 0: valid bit - - bit 1: strobe bit - bits 2-9: data byte - bits 10-26: address 3. ``ISPDATA`` (10 bits): a subset of ``ISPCONFIGURATION`` used by instructions with autoincrementing address - - bit 0: valid bit - - bit 1: strobe bit + - bits 0-1: control - bits 2-9: data byte Programming operations are triggered when the ``ISPDATA`` or ``ISPCONFIGURATION`` register -is written with the strobe bit set and the valid bit unset (ie. with the bottom two bits set -to ``0b10``). Once the operation succeeds, the valid bit will be set by the device, and the +is written with the bottom two bits set to ``0b10``. Once the operation succeeds, the bottom two bits of the register will read as ``0b11``. This should be checked by the programmer. @@ -167,8 +168,7 @@ To unlock write protection: - shift ``FERASE`` or ``FBULK`` to IR - shift the following value to DR: - - bit 0 (valid): 0 - - bit 1 (strobe): 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): don't care - bits 10-26 (address): ``0x1aa55`` @@ -192,13 +192,13 @@ revision older than 2. An erase operation is triggered by the following sequence: -1. The DR is written in one of the above opcodes with strobe set to 1 and valid set to 0 +1. The DR is written in one of the above opcodes with the bottom two bits set to ``0b10`` 2. The Run-Test/Idle state is entered Once started, the erase operation is self-timed. The maximum programming time can be obtained from the database. When successful, the low two bits of -DR will become ``11``. Note that shifting DR again before the operation is complete will -abort it and return ``00`` in the low bits. +DR will become ``0b11``. Note that shifting DR again before the operation is complete will +abort it and return ``0b00`` in the low bits. .. note:: The timeout value of 1.3s present in the database is taken directly from ISE SVFs, but it appears to be too small for the two devices I (@wanda-phi) personally possess, @@ -212,8 +212,7 @@ To erase fuses: - ensure the ``ISPENABLE`` bit corresponding to the area being erased is set - shift a value into DR: - - bit 0 (valid): 0 - - bit 1 (strobe): 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): don't care - bits 10-27 (address): @@ -227,11 +226,11 @@ To erase fuses: - go to Run-Test/Idle state for at least the time specified in the database for this device - shift a neutral value into DR: - - bits 0-1 (valid and strobe): 0 + - bits 0-1 (control): ``0b11`` - all other bits: don't care - Verify that the low 2 bits of the value shifted out are ``11``. Any other value is an error. - Value ``00`` could mean that the erase was still in progress. Value ``10`` could mean that + Verify that the low 2 bits of the value shifted out are ``0b11``. Any other value is an error. + Value ``0b00`` could mean that the erase was still in progress. Value ``0b10`` could mean that device is write protected. Other values are unknown. @@ -241,17 +240,17 @@ Programming fuses — XC9500 Fuses are programmed a byte at a time in random-access fashion. The ``FPGM`` and ``FPGMI`` opcodes are used for programming. A program operation is triggered by the following sequence: -1. The DR is written in one of the above opcodes with strobe set to 1 and valid set to 0 +1. The DR is written in one of the above opcodes with the bottom two bits set to ``0b10`` 2. The Run-Test/Idle state is entered Once started, the programming operation is self-timed. The maximum programming time depends on the device and can be obtained from the database. When successful, the low two bits of -DR will become ``11``. Note that shifting DR again before the operation is complete will -abort it and return ``01`` in the low bits. +DR will become ``0b11``. Note that shifting DR again before the operation is complete will +abort it and return ``0b01`` in the low bits. As usual with flash devices, a program operation can only change a ``1`` bit to a ``0`` bit. Bits can be reset back to ``1`` only by an erase operation. A programming operation -that attempts to set an already-0 bit to 1 will fail, and result in ``01`` in the low DR bits. +that attempts to set an already-0 bit to 1 will fail, and result in ``0b01`` in the low DR bits. To program a single byte: @@ -260,29 +259,28 @@ To program a single byte: - shift ``FPGM`` into IR - shift a value into DR: - - bit 0 (valid): 0 - - bit 1 (strobe): 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): the data to be programmed - bits 10-26 (address): the address to program - go to Run-Test/Idle state for at least the time specified in the database for this device - shift a neutral value into DR: - - bits 0-1 (valid and strobe): 0 + - bits 0-1 (control): ``0b11`` - all other bits: don't care - Verify that the low 2 bits of the value shifted out are ``11``. Any other value is an error. + Verify that the low 2 bits of the value shifted out are ``0b11``. Any other value is an error. -When more than one byte is to be read, the DR shifts can be overlapped — instead of shifting +When more than one byte is to be programmed, the DR shifts can be overlapped — instead of shifting in a neutral DR value when reading back the status, the shift can be used to trigger the second program: - prepare ISP mode, shift ``FPGM`` into IR -- shift first address + data + strobe into DR +- shift first address + data + control into DR - go to RTI for programming time -- shift second address + data + strobe into DR, verify low 2 bits of the value shifted out +- shift second address + data + control into DR, verify low 2 bits of the value shifted out - go to RTI for programming time -- shift third address + data + strobe into DR, verify low 2 bits of the value shifted out +- shift third address + data + control into DR, verify low 2 bits of the value shifted out - ... - shift neutral value into DR, verify low 2 bits of the value shifted out @@ -290,21 +288,20 @@ When a block of sequential addresses is to be programmed (including programming the ``FPGMI`` auto-incrementing instruction can be used as follows: - prepare ISP mode, shift ``FPGM`` into IR -- shift first address + data + strobe into DR +- shift first address + data + control into DR - go to RTI for programming time - shift ``FPGMI`` into IR -- shift second data + strobe into DR, ie. shift the following value into DR: +- shift second data + control into DR, ie. shift the following value into DR: - - bit 0 (valid): set to 0 - - bit 1 (strobe): set to 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): second data byte Verify low two bits of the value shifted out are ``11`` - go to RTI for programming time -- shift third data + strobe into DR, verify status +- shift third data + control into DR, verify status - go to RTI for programming time - ... -- shift neutral value (strobe and valid 0) into DR, verify status of the last byte +- shift neutral value (control ``0b11``) into DR, verify status of the last byte Since ``FPGMI`` skips over invalid addresses when auto-incrementing, the above sequence can be used to program the entire device in one go. @@ -316,7 +313,7 @@ Reading fuses — XC9500 Fuses are read a byte at a time in random-access fashion. The ``FVFY`` and ``FVFYI`` opcodes are used for reading. A read is triggered by the following sequence: -1. The DR is written in one of the above opcodes with strobe set to 1 and valid set to 0 +1. The DR is written in one of the above opcodes with low two bits set to ``0b10`` 2. The Run-Test/Idle state is entered The reads are immediate — they require only one TCK cycle to be spent in the Run-Test/Idle state. @@ -332,21 +329,19 @@ To read a single byte of fuses: - shift ``FVFY`` into IR - shift a value into DR: - - bit 0 (valid): 0 - - bit 1 (strobe): 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): don't care - bits 10-26 (address): the address to read - go to Run-Test/Idle state for at least 1 clock - shift a neutral value into DR: - - bits 0-1 (valid and strobe): 0 + - bits 0-1 (control): ``0b11`` - all other bits: don't care The data read will be: - - bit 0 (valid): 1 if operation succeeded (0 if error) - - bit 1 (strobe): always 1 + - bits 0-1 (control): ``0b11`` if operation succeeded (``0b10`` if error) - bits 2-9: the data byte read - bits 10-26: the address @@ -355,11 +350,11 @@ in a neutral DR value when reading back the first data byte, the shift can be us trigger the second read: - prepare ISP mode, shift ``FVFY`` into IR -- shift first address + strobe into DR +- shift first address + control into DR - go to RTI for one clock -- shift second address + strobe into DR, grab first data from the value shifted out +- shift second address + control into DR, grab first data from the value shifted out - go to RTI for one clock -- shift third address + strobe into DR, grab second data from the value shifted out +- shift third address + control into DR, grab second data from the value shifted out - ... - shift neutral value into DR, grab final data from the value shifted out @@ -367,21 +362,20 @@ When a block of sequential addresses is to be read (including reading the whole the ``FVFYI`` auto-incrementing instruction can be used as follows: - prepare ISP mode, shift ``FVFY`` into IR -- shift first address + strobe into DR +- shift first address + control into DR - go to RTI for one clock - shift ``FVFYI`` into IR -- shift second strobe into DR, ie. shift the following value into DR: +- shift second control into DR, ie. shift the following value into DR: - - bit 0 (valid): set to 0 - - bit 1 (strobe): set to 1 + - bits 0-1 (control): ``0b10`` - bits 2-9 (data): don't care Grab first data byte from the value shifted out - go to RTI for one clock -- shift third strobe into DR, grab second data from the value shifted out +- shift third control into DR, grab second data from the value shifted out - go to RTI for one clock - ... -- shift neutral value (strobe and valid 0) into DR, grab final data from the value shifted out +- shift neutral value (control ``0b11``) into DR, grab final data from the value shifted out Since ``FVFYI`` skips over invalid addresses when auto-incrementing, the above sequence can be used to read the entire device in one go. @@ -412,22 +406,23 @@ The following DR registers exist on XC9500XL/XV: 1. ``ISPENABLE`` (6 bits): function and contents unclear 2. ``ISPCONFIGURATION`` (``18 + num_fbs * 8`` bits): used to load and store bitstream words - - bit 0: valid bit - - bit 1: strobe bit + - bits 0-1: control + + - ``0b11``: trigger value, starts the operation + - ``0b01``: neutral value and successful result + - bits 2-``(num_sbs * 8 + 1)``: data word - bits ``(num_fbs * 8 + 2)``-``(num_fbs * 8 + 17)``: address 3. ``ISPDATA`` (``2 + num_fbs * 8`` bits): a subset of ``ISPCONFIGURATION`` used by instructions with autoincrementing address - - bit 0: valid bit - - bit 1: strobe bit + - bits 0-1: control - bits 2-``(num_fbs * 8 + 1)``: data word 4. ``ISPADDRESS`` (18 bits): a subset of ``ISPCONFIGURATION`` used by some instructions: - - bit 0: valid bit - - bit 1: strobe bit - - bits 2-17: address + - bits 0-1: control + - bits 2-17: address @@ -442,7 +437,7 @@ is unknown. To enter ISP mode: - shift ``ISPEN`` or ``ISPENC`` into IR -- shift 0s into DR +- shift ``0b000101`` into DR - go to Run-Test/Idle state for at least 1 clock If the ``ISPEN`` instruction is used, all outputs will be put in high-Z with weak pull-ups while ISP mode is active. @@ -459,31 +454,278 @@ When ISP mode is exitted, the device will initialize itself and start normal ope .. todo:: verify, see if anything can be figured out about the DR +Blank check — XC9500XL/XV +------------------------- + +The blank check (``FBLANK``) instruction performs a check whether the device is blank +(ie. all fuses are ``0``). It is used as follows: + +- enter ISP mode, if not already entered +- shift ``FBLANK`` to IR +- shift the following value to DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-17 (address): don't care + +- go to Run-Test/Idle state for at least 500 µs +- shift a neutral value (low two bits ``0b01``) into DR, look at the low two bits of the value shifted out: + + - ``0b00``: device is write protected + - ``0b01``: device is blank + - ``0b10``: operation interrupted (wait too short) + - ``0b11``: device is not blank + + + +Write protection — XC9500XL/XV +------------------------------ + +If the device is write protected (which can be determined by reading bit 2 of IR), it cannot +be written (erased or programmed) without unlocking write protection first. + +To unlock write protection: + +- enter ISP mode, if not already entered +- shift ``FERASE`` or ``FBULK`` to IR +- shift the following value to DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-17 (address): ``0xaa55`` + +Once that value is shifted in, the device is unlocked, and bit 2 of IR goes to 0. However, +this unlock only lasts for the duration of the current ISP mode session — once ``ISPEX`` is +executed (or the device is reset), the write protection status will be reloaded from the flash. + + Erasing fuses — XC9500XL/XV --------------------------- -.. todo:: write me +Like on XC9500, there are two instructions that erase fuses: + +- ``FERASE``: erases one FB at a time +- ``FBULK``: erases the entire device at once + +An erase operation is triggered by the following sequence: + +1. The DR is written in one of the above opcodes with the bottom two bits set to ``0b11`` +2. The Run-Test/Idle state is entered + +Once started, the erase operation is self-timed. The maximum programming time can be obtained +from the database. When successful, the low two bits of +DR will become ``0b11``. Note that shifting DR again before the operation is complete will +abort it and return ``0b10`` in the low bits. + +To erase fuses: + +- enter ISP mode, if not already entered +- shift a value into DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-17 (address): + + - bits 0-11 (row, column): don't care + - bits 12-15: + + - for ``FERASE``: FB index + - for ``FBULK``: don't care + +- go to Run-Test/Idle state for at least the time specified in the database for this device +- shift a neutral value into DR: + + - bits 0-1 (control): ``0b01`` + - all other bits: don't care + + Verify that the low 2 bits of the value shifted out are ``0b01``. Any other value is an error. + Value ``0b10`` could mean that the erase was still in progress. Value ``0b00`` could mean that + device is write protected. Other values are unknown. Programming fuses — XC9500XL/XV ------------------------------- -.. todo:: write me +The programming sequence is markedly different from XC9500 — while data is uploaded +to the device a word at a time, the actual programming happens a row at a time. + +As on XC9500, the opcodes used for programming are ``FPGM`` and ``FPGMI``. + +The device has a "row buffer", which stores a row worth of data. Writing to DR with +any of the above opcodes will place the data bits into the row buffer, at the position +determined by the column encoded in the address. + +A program operation will write the entire contents of the row buffer into the array. +It is triggered by the following sequence: + +1. The DR is written in one of the above opcodes with the bottom two bits set to ``0b11`` +2. The Run-Test/Idle state is entered + +Once started, the programming operation is self-timed. The maximum programming time depends +on the device and can be obtained from the database. When successful, the low two bits of +DR will become ``0b01``. Note that shifting DR again before the operation is complete will +abort it and return ``0b11`` in the low bits. + +If the device is write protected, the operation will fail, and ``0b00`` will be returned +in the bottom two bits. + +To program a row of data: + +- enter ISP mode, if not already entered +- shift ``FPGM`` into IR +- for first 14 columns: + + - shift a value into DR: + + - bits 0-1 (control): ``0b01`` + - bits 2-... (data): the data to be programmed + - top 16 bits (address): the address to be programmed + +- for the final column: + + - shift a value into DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-... (data): the data to be programmed + - top 16 bits (address): the address to be programmed + +- go to Run-Test/Idle state for at least the time specified in the database for this device +- shift a neutral value into DR: + + - bits 0-1 (control): ``0b01`` + - all other bits: don't care + + Verify that the low 2 bits of the value shifted out are ``0b01``. Any other value is an error. + +When more than one row is to be programmed, the final shift can be overlapped with loading the +first word of the next row. + +When a block of sequential addresses is to be programmed (including programming the whole device), +the ``FPGMI`` auto-incrementing instruction can be used as follows: + +- prepare ISP mode, shift ``FPGM`` into IR +- shift first address + data + ``0b01`` control into DR (loading first word of first row) +- shift ``FPGMI`` into IR +- for 13 more words: shift data + ``0b01`` control into DR +- for the final word of first row: shift data + ``0b11`` control into DR +- go to RTI for programming time +- for every remaining row: + + - for first 14 words: shift data + ``0b01`` control into DR; for first word, additionally check result of previous operation + - for last row: shift data + ``0b11`` control into DR + - go to RTI for programming time + +- shift neutral value (control ``0b11``) into DR, verify status of the last row + +Since ``FPGMI`` skips over invalid addresses when auto-incrementing, the above sequence +can be used to program the entire device in one go. Reading fuses — XC9500XL/XV --------------------------- -.. todo:: write me +Fuse reading works like on XC9500, except that the array is read a word at a time +(a byte from each FB), and the FB index in address is ignored. +The ``FVFY`` and ``FVFYI`` opcodes are used for reading. A read is triggered by the following sequence: -Blank check — XC9500XL/XV -------------------------- +1. The DR is written in one of the above opcodes with low two bits set to ``0b11`` +2. The Run-Test/Idle state is entered + +The reads are immediate — they require only one TCK cycle to be spent in the Run-Test/Idle state. + +The data is read from the currently set address and placed in the ``ISPCONFIGURATION`` / ``ISPDATA`` +data field. If the ``FVFYI`` opcode was used, the address is then auto-incremented to the next +valid address in the device. + +To read a single word of fuses: -.. todo:: write me +- enter ISP mode, if not already entered +- shift ``FVFY`` into IR +- shift a value into DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-... (data): don't care + - top 16 bits (address): the address to read + +- go to Run-Test/Idle state for at least 1 clock +- shift a neutral value into DR: + + - bits 0-1 (control): ``0b01`` + - all other bits: don't care + + The data read will be: + + - bits 0-1 (control): ``0b01`` if operation succeeded + - bits 2-... (data): the data word read + - top 16 bits (address): the address + +When more than one word is to be read, the DR shifts can be overlapped — instead of shifting +in a neutral DR value when reading back the first data word, the shift can be used to +trigger the second read: + +- prepare ISP mode, shift ``FVFY`` into IR +- shift first address + control into DR +- go to RTI for one clock +- shift second address + control into DR, grab first data from the value shifted out +- go to RTI for one clock +- shift third address + control into DR, grab second data from the value shifted out +- ... +- shift neutral value into DR, grab final data from the value shifted out + +When a block of sequential addresses is to be read (including reading the whole device), +the ``FVFYI`` auto-incrementing instruction can be used as follows: + +- prepare ISP mode, shift ``FVFY`` into IR +- shift first address + control into DR +- go to RTI for one clock +- shift ``FVFYI`` into IR +- shift second control into DR, ie. shift the following value into DR: + + - bits 0-1 (control): ``0b11`` + - bits 2-... (data): don't care + + Grab first data word from the value shifted out +- go to RTI for one clock +- shift third control into DR, grab second data from the value shifted out +- go to RTI for one clock +- ... +- shift neutral value (control ``0b01``) into DR, grab final data from the value shifted out + +Since ``FVFYI`` skips over invalid addresses when auto-incrementing, the above sequence +can be used to read the entire device in one go. + +If any read protection fuse was programmed in the device as of the time of last ``ISPEN`` / ``ISPENC``, +the device is considered read protected, and most addresses cannot be read (reads from them will +return all-0 instead of the actual data). The only readable fuses are: + +- row in range 0-11 +- bit (within byte) in range 6-7 + +This corresponds (roughly) to global configuration bits, including the USERCODE. + +Note that read protection remains active until the ISP mode is exited even after the device has +been completely erased — for that reason, one should perform ISP mode exit and re-entry after +erasing the device. Programming sequence ==================== -.. todo:: write me \ No newline at end of file +The programming sequence for XC9500 family devices is as follows: + +1. Shift ``IDCODE``, verify the device matches the bitstream. +2. Enter ISP mode. +3. Optionally, perform one of the following (as needed): + + - a blank check + - an erase operation + + - for old XC9500 devices: run ``FERASE`` on each area + - for non-old XC9500 devices: run ``FBULK`` twice, for main areas and UIM wire-AND areas + - for XC9500XL/XV devices: run ``FBULK`` once + + - a write protect override, then an erase operation + +4. If an erase was performed, exit and reenter ISP mode (to clear read protect state). +5. Perform the main sequence of programming operations: program everything other than read protection, write protection, and ``DONE`` fuses. +6. Optionally, perform verification: read the entire device, verify it matches the programmed data. +7. Perform a final programming pass, writing the read protection, write protection, and ``DONE`` bits (if any). +8. Exit ISP mode.