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 |
---|---|---|---|
|
|
|
32 |
|
|
|
16 |
|
|
|
10 |
|
|
|
1 |
|
|
|
varies |
|
|
|
1 |
|
|
|
11 |
|
|
|
1 |
|
|
|
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 |
|
86 |
|
166 |
|
326 |
B-side |
|
86 |
|
166 |
|
326 |
Config |
|
32 |
|
32 |
|
32 |
JTAG |
|
4 |
|
4 |
|
4 |
UES |
|
16 |
|
16 |
|
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
:
Shift
ATF_READ_UES
into IR.Shift
ues
out of DR.Bit-reverse
ues
.
Enable¶
To enter programming mode:
Shift
ATF_CONFIG
into IR.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:
Shift
ATF_CONFIG
into IR.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:
Shift
ATF_LATCH_ERASE
into IR.Shift
ATF_PROGRAM_ERASE
into IR.Wait 210 ms.
Program¶
To program a configuration word data
to address addr
:
Shift
ATF_ADDRESS
into IR.Shift
addr
into DR.Shift
ATF_DATA0 + (addr >> 8)
into IR.Shift
data
into DR. DR length is determined by the address and the memory layout.Shift
ATF_PROGRAM_ERASE
into IR.Wait 30 ms.
Read¶
To read a configuration word data
from address addr
:
Shift
ATF_ADDRESS
into IR.Shift
addr
into DR.Shift
ATF_READ
into IR.Wait 20 ms.
Shift
ATF_DATA0 + (addr >> 8)
into IR.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