AS-series programming

ATF15xxAS devices are always controlled by the contents of the integrated Flash memory. They are in-system programmable via JTAG using a command set close to but not entirely compatible with IEEE 1532.

See also programming options.

JTAG instructions

AS-series CPLDs have a 10 bit long instruction register, and support the following programming-related JTAG instructions:

Instruction

IR value

Selected DR

DR length

IDCODE

059

IDCODE

32

ATF_READ_UES

270

UES

16

ATF_CONFIG

280

FLASH_KEY

10

ATF_READ

28c

BYPASS

1

ATF_DATA0..3

290..293

FLASH_DATA

varies

ATF_PROGRAM_ERASE

29e

BYPASS

1

ATF_ADDRESS

2a1

FLASH_ADDR

11

ATF_LATCH_ERASE

2b3

BYPASS

1

ATF_UNKNOWN

2bf

BYPASS

1

Todo

Update the description and usage for the ATF_UNKNOWN instruction based on recent discoveries.

Memory layout

The geometry of the Flash memory varies with the CPLD density. The following table describes the memory layouts for all device densities:

Device

ATF1502AS

ATF1504AS

ATF1508AS

Region

Address(es)

Width

Address(es)

Width

Address(es)

Width

A-side

00..6c

86

00..6c

166

00..6c

326

B-side

80..e5

86

80..e9

166

80..fb

326

Config

100

32

100

32

100

32

JTAG

200

4

200

4

200

4

UES

300

16

300

16

300

16

During programming or reading, the actual DR size is determined by the contents of FLASH_ADDR and the table above.

Programming flows

In all programming flows below, after shifting into IR or DR, enter Run-Test/Idle.

Read UES

To read the user signature ues:

  1. Shift ATF_READ_UES into IR.

  2. Shift ues out of DR.

  3. Bit-reverse ues.

Enable

To enter programming mode:

  1. Shift ATF_CONFIG into IR.

  2. Shift 1b9 into DR.

This sequence disables normal operation and enables programming operations. It also disables the output buffers. If bus keepers are enabled with the corresponding fuse, the outputs will weakly hold their current state during programming.

Disable

To leave programming mode:

  1. Shift ATF_CONFIG into IR.

  2. Shift 000 into DR.

This sequence disables programming operations and enables normal operation. It also resets both the macrocells and the JTAG TAP.

Erase

To erase the currently programmed configuration:

  1. Shift ATF_LATCH_ERASE into IR.

  2. Shift ATF_PROGRAM_ERASE into IR.

  3. Wait 210 ms.

Program

To program a configuration word data to address addr:

  1. Shift ATF_ADDRESS into IR.

  2. Shift addr into DR.

  3. Shift ATF_DATA0 + (addr >> 8) into IR.

  4. Shift data into DR. DR length is determined by the address and the memory layout.

  5. Shift ATF_PROGRAM_ERASE into IR.

  6. Wait 30 ms.

Read

To read a configuration word data from address addr:

  1. Shift ATF_ADDRESS into IR.

  2. Shift addr into DR.

  3. Shift ATF_READ into IR.

  4. Wait 20 ms.

  5. Shift ATF_DATA0 + (addr >> 8) into IR.

  6. Shift data out of DR. DR length is determined by the address and the memory layout.

Fuse packing

Running the place & route tool produces a fuse map; a 1d sequence of fuses. However, the device’s Flash memory is organized as a series of words; a 2d array of cells. Fuses can be packed into and unpacked from the Flash memory by applying the permutations described below.

In all of the code fragments below, let jed_index be the index of a fuse, svf_row be the address of a word, and svf_col be the bit offset into the word. Then, packing and unpacking are bit copy operations between the two representations.

ATF1502AS

The following snippet implements the packing (jed_to_svf_coords) and unpacking (svf_to_jed_coords) permutations for ATF1502AS:

 1def jed_to_svf_coords(jed_index):
 2    if jed_index in range(    0,  7680):
 3        return  12 + (jed_index -     0)  % 96, 79 - (jed_index -     0) // 96
 4    if jed_index in range( 7680, 15360):
 5        return 128 + (jed_index -  7680)  % 96, 79 - (jed_index -  7680) // 96
 6    if jed_index in range(15360, 16320):
 7        return   0 + (jed_index - 15360) // 80, 79 - (jed_index - 15360)  % 80
 8    if jed_index in range(16320, 16720):
 9        return 224 + (jed_index - 16320)  %  5, 79 - (jed_index - 16320) // 5
10    if jed_index in range(16720, 16750):
11        return 224 + (jed_index - 16320)  %  5, 85 - (jed_index - 16320) // 5 + 80
12    if jed_index in range(16750, 16782):
13        return 256, 31 - (jed_index - 16750)
14    if jed_index in range(16782, 16786):
15        return 512,  3 - (jed_index - 16782)
16    if jed_index in range(16786, 16802):
17        return 768, 15 - (jed_index - 16786)
18    if jed_index in range(16802, 16808):
19        return # reserved
20    assert False
21
22def svf_to_jed_coords(svf_row, svf_col):
23    if svf_row in range(  0,  12):
24        if svf_col in range(0, 80):
25            return 15360 + (svf_row -   0) * 80 + (79 - svf_col)
26        else:
27            return # always 1
28    if svf_row in range( 12, 108):
29        if svf_col in range(0, 80):
30            return     0 + (svf_row -  12) + (79 - svf_col) * 96
31        else:
32            return # always 1
33    if svf_row in range(128, 224):
34        if svf_col in range(0, 80):
35            return  7680 + (svf_row - 128) + (79 - svf_col) * 96
36        else:
37            return # always 1
38    if svf_row in range(224, 229):
39        if svf_col in range(0, 80):
40            return 16320 + (svf_row - 224) + (79 - svf_col) * 5
41        else:
42            return 16720 + (svf_row - 224) + (85 - svf_col) * 5
43    if svf_row == 256:
44        return 16750 + (31 - svf_col)
45    if svf_row == 512:
46        return 16782 + ( 3 - svf_col)
47    if svf_row == 768:
48        return 16786 + (15 - svf_col)
49    assert False

ATF1504AS

The following snippet implements the packing (jed_to_svf_coords) and unpacking (svf_to_jed_coords) permutations for ATF1504AS:

 1def jed_to_svf_coords(jed_index):
 2    if jed_index in range(    0,   15360):
 3        return  12 + (jed_index -      0)  % 96,  165 - (jed_index -     0) // 96
 4    if jed_index in range(15360,   30720):
 5        return 128 + (jed_index -  15360)  % 96,  165 - (jed_index - 15360) // 96
 6    if jed_index in range(30720,   32640):
 7        return   0 + (jed_index -  30720) // 160, 165 - (jed_index - 30720)  % 160
 8    if jed_index in range(32640,   34134):
 9        return 224 + (jed_index -  32640)  %  9,  165 - (jed_index - 32640) // 9
10    if jed_index in range(34134, 34166):
11        return 256, 31 - (jed_index - 34134)
12    if jed_index in range(34166, 34170):
13        return 512,  3 - (jed_index - 34166)
14    if jed_index in range(34170, 34186):
15        return 768, 15 - (jed_index - 34170)
16    if jed_index in range(34186, 34192):
17        return # reserved
18    assert False
19
20def svf_to_jed_coords(svf_row, svf_col):
21    if svf_row in range(  0,  12):
22        if svf_col in range(6, 166):
23            return 30720 + (svf_row -   0) * 160 + (165 - svf_col)
24        else:
25            return # always 1
26    if svf_row in range( 12, 108):
27        if svf_col in range(6, 166):
28            return     0 + (svf_row -  12) + (165 - svf_col) * 96
29        else:
30            return # always 1
31    if svf_row in range(128, 224):
32        if svf_col in range(6, 166):
33            return 15360 + (svf_row - 128) + (165 - svf_col) * 96
34        else:
35            return # always 1
36    if svf_row in range(224, 233):
37        if svf_col in range(0, 166):
38            return 32640 + (svf_row - 224) + (165 - svf_col) * 9
39        else:
40            return # always 1
41    if svf_row == 256:
42        return 34134 + (31 - svf_col)
43    if svf_row == 512:
44        return 34166 + ( 3 - svf_col)
45    if svf_row == 768:
46        return 34170 + (15 - svf_col)
47    assert False

ATF1508AS

The following snippet implements the packing (jed_to_svf_coords) and unpacking (svf_to_jed_coords) permutations for ATF1508AS:

 1def jed_to_svf_coords(jed_index):
 2    if jed_index in range(    0, 30720):
 3        return  12 + (jed_index -     0)  %  96, 325 - (jed_index -     0) // 96
 4    if jed_index in range(30720, 61440):
 5        return 128 + (jed_index - 30720)  %  96, 325 - (jed_index - 30720) // 96
 6    if jed_index in range(61440, 65280):
 7        return   0 + (jed_index - 61440) // 320, 325 - (jed_index - 61440)  % 320
 8    if jed_index in range(65280, 74082):
 9        return 224 + (jed_index - 65280)  %  27, 325 - (jed_index - 65280) // 27
10    if jed_index in range(74082, 74114):
11        return 256, 31 - (jed_index - 74082)
12    if jed_index in range(74114, 74118):
13        return 512,  3 - (jed_index - 74114)
14    if jed_index in range(74118, 74134):
15        return 768, 15 - (jed_index - 74118)
16    if jed_index in range(74134, 74136):
17        return # reserved
18    assert False
19
20def svf_to_jed_coords(svf_row, svf_col):
21    if svf_row in range(  0,  12):
22        if svf_col in range(6, 326):
23            return 61440 + (svf_row -   0) * 320 + (325 - svf_col)
24        else:
25            return # always 1
26    if svf_row in range( 12, 108):
27        if svf_col in range(6, 326):
28            return     0 + (svf_row -  12) + (325 - svf_col) * 96
29        else:
30            return # always 1
31    if svf_row in range(128, 224):
32        if svf_col in range(6, 326):
33            return 30720 + (svf_row - 128) + (325 - svf_col) * 96
34        else:
35            return # always 1
36    if svf_row in range(224, 251):
37        if svf_col in range(0, 326):
38            return 65280 + (svf_row - 224) + (325 - svf_col) * 27
39        else:
40            return # always 1
41    if svf_row == 256:
42        return 74082 + (31 - svf_col)
43    if svf_row == 512:
44        return 74114 + ( 3 - svf_col)
45    if svf_row == 768:
46        return 74118 + (15 - svf_col)
47    assert False