Skip to content

Instantly share code, notes, and snippets.

@Chester-Gillon
Last active September 14, 2025 17:23
Show Gist options
  • Save Chester-Gillon/4f79dc0b21b19d6df25a9da202ba2ef2 to your computer and use it in GitHub Desktop.
Save Chester-Gillon/4f79dc0b21b19d6df25a9da202ba2ef2 to your computer and use it in GitHub Desktop.
Xilinx Stacked Silicon Interconnect (SSI) bitstream format

0. Introduction

xilinx_7_series_bitstream.c was originally written for Xilinx 7 series devices, before subsequently adding support for Xilinx UltraScale and UltraScale+ devices.

1. 7K160T has no unprocessed data at the end of the bit stream

The 7K160T doesn't use SSI.

Convert the bit to bin file, to remove the header so the contents of the file is word aligned:

 ~/fpga_sio/software_tests/eclipse_project/bin/debug/xilinx_quad_spi/xilinx_bit_to_bin TEF1001_dma_stream_crc64_wrapper.{bit,bin}
Wrote 3443072 bytes to TEF1001_dma_stream_crc64_wrapper.bin

The file sizes:

$ ls -l TEF1001_dma_stream_crc64_wrapper.{bit,bin}
-rw-rw-r-- 1 mr_halfword mr_halfword 3443072 Sep 13 21:31 TEF1001_dma_stream_crc64_wrapper.bin
-rw-rw-r-- 1 mr_halfword mr_halfword 3443231 Jun 19 16:39 TEF1001_dma_stream_crc64_wrapper.bit

parse_bitstream_file reports a bitstream length (3443072) which matches the size of the bin file, so not unprocessed data at the end of the bitstream:

$ ~/fpga_sio/software_tests/eclipse_project/bin/debug/xilinx_quad_spi/parse_bitstream_file TEF1001_dma_stream_crc64_wrapper.bin
Successfully parsed bitstream of length 3443072 bytes with 28639 configuration packets
Read bitsteam from file TEF1001_dma_stream_crc64_wrapper.bin
Sync word at byte index 0x130
  Type 1 packet opcode NOP
  Type 1 packet opcode write register BSPI words 0000026C
  Type 1 packet opcode write register CMD command BSPI_READ
  Type 1 packet opcode NOP
  Type 1 packet opcode write register TIMER words 00000000
  Type 1 packet opcode write register WBSTAR words 00000000
  Type 1 packet opcode write register CMD command NULL
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command RCRC
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register AXSS 9B3309E3 - 19/06/2025 16:39:35
  Type 1 packet opcode write register RBCRC_SW words 00000000
  Type 1 packet opcode write register COR0 words 02303FE5
  Type 1 packet opcode write register COR1 words 00000000
  Type 1 packet opcode write register IDCODE 7K160T
  Type 1 packet opcode write register CMD command SWITCH
  Type 1 packet opcode NOP
  Type 1 packet opcode write register MASK words 00000401
  Type 1 packet opcode write register CTL0 words 00000501
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00001000
  Type 1 packet opcode NOP (8 consecutive)
  Configuration data writes consisting of:
    9461 NOPs
    9158 FAR writes
    225 WCFG commands
    225 FDRI writes with a total of 90799 words
    47 MFW commands
    8980 MFWR writes with a total of 36108 words
    67 Type 2 packets with a total of 695688 words
  Type 1 packet opcode write register CRC words D7986A21
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command GRESTORE
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command DGHIGH_LFRM
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00000000
  Type 1 packet opcode NOP (100 consecutive)
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register FAR words 03BE0000
  Type 1 packet opcode write register MASK words 00000501
  Type 1 packet opcode write register CTL0 words 00000501
  Type 1 packet opcode write register CRC words 615009A6
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (329 consecutive)

2. U200 with 3 SLRs causes parse_bitstream_file to have unprocessed data

An Alevo U200 which corresponds to a VU9P, which has 3 SLRs.

Convered the bit to bin file:

$ ~/fpga_sio/software_tests/eclipse_project/bin/debug/xilinx_quad_spi/xilinx_bit_to_bin U200_100G_ether_simplex_tx_wrapper.{bit,bin} 
Wrote 30972872 bytes to U200_100G_ether_simplex_tx_wrapper.bin

Size of the files:

$ ls -l U200_100G_ether_simplex_tx_wrapper.{bit,bin}
-rw-rw-r-- 1 mr_halfword mr_halfword 30972872 Sep 13 21:41 U200_100G_ether_simplex_tx_wrapper.bin
-rw-rw-r-- 1 mr_halfword mr_halfword 30973076 Sep 12 20:01 U200_100G_ether_simplex_tx_wrapper.bit

parse_bitstream_file only parses 13,483,216 out of the 30,973,076 bytes in the bin file:

$ ~/fpga_sio/software_tests/eclipse_project/bin/debug/xilinx_quad_spi/parse_bitstream_file U200_100G_ether_simplex_tx_wrapper.bin
Successfully parsed bitstream of length 13483216 bytes with 423612 configuration packets
Read bitsteam from file U200_100G_ether_simplex_tx_wrapper.bin
Sync word at byte index 0x50
  Type 1 packet opcode NOP
  Type 1 packet opcode write register BSPI words 0000066C
  Type 1 packet opcode write register CMD command BSPI_READ
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register TIMER words 00000000
  Type 1 packet opcode write register WBSTAR words 00000000
  Type 1 packet opcode write register CMD command NULL
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command RCRC
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register AXSS 64B33E72 - 12/09/2025 19:57:50
  Type 1 packet opcode write register FAR words 00000000
  Type 1 packet opcode write register RBCRC_SW words 00000000
  Type 1 packet opcode write register COR0 words 383E3FE5
  Type 1 packet opcode write register COR1 words 00400000
  Type 1 packet opcode write register IDCODE XCU200
  Type 1 packet opcode write register CMD command FALL_EDGE
  Type 1 packet opcode write register CMD command SWITCH
  Type 1 packet opcode NOP
  Type 1 packet opcode write register MASK words 00000001
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00001000
  Type 1 packet opcode NOP (8 consecutive)
  Configuration data writes consisting of:
    320481 NOPs
    50439 FAR writes
    1172 WCFG commands
    1172 FDRI writes with a total of 325035 words
    242 MFW commands
    242 NULL commands
    49267 MFWR writes with a total of 689738 words
    135 Type 2 packets with a total of 1880274 words
  Type 1 packet opcode write register CRC words 67AD151F
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command GRESTORE
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DGHIGH_LFRM
  Type 1 packet opcode NOP (20 consecutive)
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00000000
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register FAR words 07FC0000
  Type 1 packet opcode write register MASK words 00000101
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register CRC words 5FFE959E
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (391 consecutive)

Used the following to look at the hex dump:

xxd -g 4 U200_100G_ether_simplex_tx_wrapper.bin |less

Searched for aa995566 which is the Sync Word:

  1. At the start of the bitstream, which is what parse_bitstream_file finds:
    00000000: ffffffff ffffffff ffffffff ffffffff  ................
    00000010: ffffffff ffffffff ffffffff ffffffff  ................
    00000020: ffffffff ffffffff ffffffff ffffffff  ................
    00000030: ffffffff ffffffff ffffffff ffffffff  ................
    00000040: 000000bb 11220044 ffffffff ffffffff  .....".D........
    00000050: aa995566 20000000 3003e001 0000066c  ..Uf ...0......l
    00000060: 30008001 00000012 20000000 20000000  0....... ... ...
    00000070: 30022001 00000000 30020001 00000000  0. .....0.......
    
  2. Part way through:
    00cdbcb0: 20000000 20000000 20000000 20000000   ... ... ... ...
    00cdbcc0: 20000000 20000000 20000000 20000000   ... ... ... ...
    00cdbcd0: aa995566 20000000 30008001 0000000b  ..Uf ...0.......
    00cdbce0: 20000000 30008001 00000007 20000000   ...0....... ...
    00cdbcf0: 20000000 3003c000 5042b618 ffffffff   ...0...PB......
    00cdbd00: ffffffff ffffffff ffffffff ffffffff  ................
    00cdbd10: ffffffff ffffffff ffffffff ffffffff  ................
    00cdbd20: ffffffff ffffffff ffffffff ffffffff  ................
    00cdbd30: ffffffff ffffffff ffffffff 000000bb  ................
    00cdbd40: 11220044 ffffffff ffffffff aa995566  .".D..........Uf
    00cdbd50: 20000000 3003e001 0000066c 30008001   ...0......l0...
    00cdbd60: 00000012 20000000 20000000 30022001  .... ... ...0. .
    
    Offset hex 00cdbcd0 is 13483216 decimal, which means the Sync Word at offset 00cdbcd0 is when parse_bitstream_file stops parsing the file.
  3. Part way through:
    012f22c0: 20000000 20000000 20000000 20000000   ... ... ... ...
    012f22d0: 20000000 20000000 20000000 20000000   ... ... ... ...
    012f22e0: aa995566 20000000 30008001 0000000b  ..Uf ...0.......
    012f22f0: 20000000 30008001 00000007 20000000   ...0....... ...
    012f2300: 20000000 3003c000 502a5c85 ffffffff   ...0...P*\.....
    012f2310: ffffffff ffffffff ffffffff ffffffff  ................
    012f2320: ffffffff ffffffff ffffffff ffffffff  ................
    012f2330: ffffffff ffffffff ffffffff ffffffff  ................
    012f2340: ffffffff ffffffff ffffffff 000000bb  ................
    012f2350: 11220044 ffffffff ffffffff aa995566  .".D..........Uf
    012f2360: 20000000 3003e001 0000066c 30008001   ...0......l0...
    012f2370: 00000012 20000000 20000000 30022001  .... ... ...0. .
    

While UltraScale Architecture Configuration User Guide (UG570) doesn't seem to describe it, looks like for devices which use SLRs:

  • The bitstream has has sections for each SLR.
  • If a Sync Word occurs after the final NOP (0x20000000) for one SLR than means the bitstream for the next SLR follows.

Decoding from 2) from the Sync Word:

  • 00cdbcd0: aa995566 Sync Word
  • 00cdbcd4: 20000000 NOP
  • 00cdbcd8: 30008001 0000000b Write SHUTDOWN command
  • 00cdbce0: 20000000 NOP
  • 00cdbce4: 30008001 00000007 Write RCRC command
  • 00cdbcec: 20000000 NOP
  • 00cdbcf0: 20000000 NOP
  • 00cdbcf4: 3003c000 Write with no data. Register address 0x1e. UG570 doesn't describe that register address
  • 00cdbcf8: 5042b618 Type 2 packet with 4371992 (0x42b618) words. In theory, that would put the next bitstream offset at 0x1D8955C, which is near the end of the 3rd SLR.

3. Update to fully parse a bitstream with SLRs

Commit 77e057c updated the code to be able to parse the complete bitstream for a U200 which has 3 SLRs. The code automatically detects the number of SLRs based upon reverse engineering enough of the foramt.

The output is unchanged for the TEF1001_dma_stream_crc64_wrapper, which doesn't contain SLRs.

For the U200 now reports:

$ xilinx_quad_spi/parse_bitstream_file ~/fpga_sio/fpga_tests/U200_100G_ether_simplex_tx/U200_100G_ether_simplex_tx_wrapper.bit
Successfully parsed bitstream of length 30972872 bytes with 1447885 configuration packets with 3 SLRs
Read bitsteam from file /home/mr_halfword/fpga_sio/fpga_tests/U200_100G_ether_simplex_tx/U200_100G_ether_simplex_tx_wrapper.bit
.bit format header:
  design_name=U200_100G_ether_simplex_tx_wrapper;UniqueID=3f80fcef;ParentID=00000000;UserID=0XFFFFFFFF;COMPRESS=TRUE;Version=2025.1;SW_CRC=129db51a
  part_name=xcu200-fsgd2104-2-e
  date=2025/09/12
  time=20:01:04
SLR[0] Sync word at byte index 0x50
  Type 1 packet opcode NOP
  Type 1 packet opcode write register BSPI words 0000066C
  Type 1 packet opcode write register CMD command BSPI_READ
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register TIMER words 00000000
  Type 1 packet opcode write register WBSTAR words 00000000
  Type 1 packet opcode write register CMD command NULL
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command RCRC
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register AXSS 64B33E72 - 12/09/2025 19:57:50
  Type 1 packet opcode write register FAR words 00000000
  Type 1 packet opcode write register RBCRC_SW words 00000000
  Type 1 packet opcode write register COR0 words 383E3FE5
  Type 1 packet opcode write register COR1 words 00400000
  Type 1 packet opcode write register IDCODE XCU200
  Type 1 packet opcode write register CMD command FALL_EDGE
  Type 1 packet opcode write register CMD command SWITCH
  Type 1 packet opcode NOP
  Type 1 packet opcode write register MASK words 00000001
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00001000
  Type 1 packet opcode NOP (8 consecutive)
  Configuration data writes consisting of:
    320481 NOPs
    50439 FAR writes
    1172 WCFG commands
    1172 FDRI writes with a total of 325035 words
    242 MFW commands
    242 NULL commands
    49267 MFWR writes with a total of 689738 words
    135 Type 2 packets with a total of 1880274 words
  Type 1 packet opcode write register CRC words 67AD151F
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command GRESTORE
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DGHIGH_LFRM
  Type 1 packet opcode NOP (20 consecutive)
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00000000
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register FAR words 07FC0000
  Type 1 packet opcode write register MASK words 00000101
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register CRC words 5FFE959E
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (391 consecutive)
SLR[1] Sync word at byte index 0xCDBD4C
  Type 1 packet opcode NOP
  Type 1 packet opcode write register BSPI words 0000066C
  Type 1 packet opcode write register CMD command BSPI_READ
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register TIMER words 00000000
  Type 1 packet opcode write register WBSTAR words 00000000
  Type 1 packet opcode write register CMD command NULL
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command RCRC
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register AXSS 64B33E72 - 12/09/2025 19:57:50
  Type 1 packet opcode write register FAR words 00000000
  Type 1 packet opcode write register RBCRC_SW words 00000000
  Type 1 packet opcode write register COR0 words 383E3FE5
  Type 1 packet opcode write register COR1 words 00400000
  Type 1 packet opcode write register IDCODE unknown (0x4b22093)
  Type 1 packet opcode write register CMD command SWITCH
  Type 1 packet opcode NOP
  Type 1 packet opcode write register MASK words 00000001
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00001000
  Type 1 packet opcode NOP (8 consecutive)
  Configuration data writes consisting of:
    371323 NOPs
    71831 FAR writes
    32 WCFG commands
    32 FDRI writes with a total of 3069 words
    31 MFW commands
    31 NULL commands
    71799 MFWR writes with a total of 1005186 words
  Type 1 packet opcode write register CRC words 4B4A6B87
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command GRESTORE
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DGHIGH_LFRM
  Type 1 packet opcode NOP (20 consecutive)
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00000000
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register FAR words 07FC0000
  Type 1 packet opcode write register MASK words 00000101
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register CRC words 5FFE959E
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (391 consecutive)
SLR[2] Sync word at byte index 0x12F235C
  Type 1 packet opcode NOP
  Type 1 packet opcode write register BSPI words 0000066C
  Type 1 packet opcode write register CMD command BSPI_READ
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register TIMER words 00000000
  Type 1 packet opcode write register WBSTAR words 00000000
  Type 1 packet opcode write register CMD command NULL
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command RCRC
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register AXSS 64B33E72 - 12/09/2025 19:57:50
  Type 1 packet opcode write register FAR words 00000000
  Type 1 packet opcode write register RBCRC_SW words 00000000
  Type 1 packet opcode write register COR0 words 383E3FE5
  Type 1 packet opcode write register COR1 words 00400000
  Type 1 packet opcode write register IDCODE unknown (0x4b24093)
  Type 1 packet opcode write register CMD command SWITCH
  Type 1 packet opcode NOP
  Type 1 packet opcode write register MASK words 00000001
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00001000
  Type 1 packet opcode NOP (8 consecutive)
  Configuration data writes consisting of:
    378114 NOPs
    62842 FAR writes
    2837 WCFG commands
    2837 FDRI writes with a total of 768273 words
    563 MFW commands
    563 NULL commands
    60005 MFWR writes with a total of 840070 words
    85 Type 2 packets with a total of 592689 words
  Type 1 packet opcode write register CRC words FA4C0AFA
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command GRESTORE
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DGHIGH_LFRM
  Type 1 packet opcode NOP (20 consecutive)
  Type 1 packet opcode write register MASK words 00001000
  Type 1 packet opcode write register CTL1 words 00000000
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register FAR words 07FC0000
  Type 1 packet opcode write register MASK words 00000101
  Type 1 packet opcode write register CTL0 words 00000101
  Type 1 packet opcode write register CRC words 5FFE959E
  Type 1 packet opcode NOP (2 consecutive)
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (397 consecutive)
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (10 consecutive)
  Type 1 packet opcode write register CMD command START
  Type 1 packet opcode NOP
  Type 1 packet opcode write register CMD command DESYNC
  Type 1 packet opcode NOP (404 consecutive)

The reported bitstream length of 30972872 matches that of the bin file (i.e. without the bit header) which means is no reading to the end of the bitstream.

The output shows:

  • 3 SLRs, which matches the documentation for the U200.
  • The ID code of the 1st SLR is XCU200, but the 2nd and 3rd SLR have the unknown ID code of 0x4b24093. Can't find that IDCODE documented, and grep -r -i 4b24093 /opt/Xilinx/2025.1/Vivado/data didn't find it. Presumably the slave SLRs have a different IDCODE
  • The 3rd SLR has 3 pairs of START and DESYNC commands. Whereas the 1st and 2nd SLR have just one DESYNC command.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment