Xilinx MultiBoot module
This page describes the xil_multiboot module, a VHDL module for remote reprogramming a Xilinx FPGA. The module will be capable of writing bitstreams for Xilinx FPGAs only and will contain Xilinx IP modules.
Its main features are:
- software controls operation of the module:
- a finite-state machine (FSM) controls writing to the flash chip and sending the IPROG command to the FPGA
- modular, easily modifiable design
- flash chip is controlled by software, so virtually any 8-bit SPI flash chip is supported by writing software to send the various commands to the chip
- Wishbone interface can easily be replaced by some other interconnect (e.g., AXI) by implementing the multiboot_regs module
MultiBoot basics
Xilinx MultiBoot technology [1] allows reprogramming an FPGA by downloading a bitstream to a PROM chip external to the FPGA and then issuing an IPROG command to the configuration logic of the FPGA. This command triggers deleting the configuration of the FPGA and rewriting it with the new configuration written to the PROM.
Multiple bitstreams may exist in the PROM at the same time, as outlined in the figure below:
- Header bitstream - contains sync word, multiboot and golden bitstream addresses and the IPROG command
- MultiBoot bitstream - the bitstream that is normally loaded when the IPROG command is issued
- Golden bitstream - the bitstream loaded if the multiboot bitstream load fails
A strike count is used to select which bitstream gets loaded. In Xilinx FPGAs, two kinds of errors can exist when loading a bitstream:
- CRC error - the CRC at the end of the bitstream does not correspond to what is calculated by the programming logic
- Watchdog timer timeout - the Watchdog timer used to detect the configuration synchronization word [1] counts to its maximum value
The strike count increments on either of these two errors and bitstreams are selected based on this count as below:
- if it is 0..2, the MultiBoot bitstream gets loaded
- if it is 3..5, the golden bitstream gets loaded
- if it is 6..8, the header bitstream gets loaded, and multiboot and golden bitstreams are attempted three more times
- if it is 9, configuration is halted
Note that for this scheme to work, the flag -g reset_on_error must be set when running bitgen.
This strike count can only be reset by power-on reset or pulling low the special PROGRAM_B pin of the FPGA, so once the strike count hits three, one cannot go back into reprogramming the MultiBoot bitstream.
Workflow
In order to remotely reprogram a Xilinx FPGA using the xil_multiboot* module, the following workflow is employed [2]:
- Prepare a Xilinx FPGA bitstream
- Erase the sector if on a sector boundary, or erase the number of sectors needed to write the bitstream
- Split the bistream into flash pages and send it to the flash via the FAR register
- Repeat the previous two steps until the bitstream has been sent
- Write the MultiBoot bitstream start address and flash chip read command op-code into the MBBAR register
- Write the Golden bitstream start address and flash chip read command op-code into the GBBAR register
- Unlock the IPROG bit in the FPGA by setting the CR.IPROG_UNL bit
- Issue a reprogramming command to the FPGA by setting the CR.IPROG bit
In order to check if reprogramming succeeded, a firmware version number should be implemented in a separate register and read via the Wishbone interface. This firmware number should be different from the Golden bitstream version number. By reading this firmware version number and making sure it is not that of the Golden bitstream address, MultiBoot can be validated.
Unfortunately, the BOOTSTS register in the Spartan-6 configuration logic [1] which should be used to detect if fallback has occured does not get set after an unsuccessful MultiBoot attempt and therefore cannot be used to detect fallback. The BOOTSTS register only gets set after a POR, as outlined in this Xilinx answer record.
Generating bitstreams for Xilinx FPGA reprogramming
This section gives guidelines on how to generate bitstreams to be used in MultiBoot designs.
General guidelines
First and foremost, all bitstreams must have the -g reset_on_error flag set when generating the bitstream. Otherwise, in case of an error in the MultiBoot bitstream, the reconfiguration logic will not try to load the Golden bitstream.
Early in the design cycle, map your flash memory into three bitstreams:
-
the Header bitstream always starts from address 0 and is usually 68 bytes long*
-
the Golden bitstream usually starts from address 0x44 (68 in hex), if generated automatically (see below)
-
if generated and changed manually, it should be set on a sector boundary
-
the MultiBoot bitstream should be set after the Golden bitstream, on a sector boundary
As an example, using the M25P32 flash chip to store the three bitstreams for a Spartan-6 X6SLX45T. The M25P32 has 256-byte pages packed into 256-page sectors, and the X6SLX45T has a 1484472 bytes in the bitstream. Considering the size of the bitstream, 5799 pages of memory would be needed, or a total of 23 sectors
The following flash memory map can be used if the Golden bitstream is automatically generated:
* Address * | * Bitstream * |
0x000000 | Header |
0x000044 | Golden |
0x170000 | MultiBoot |
On the other hand, should it be desired to manually change the Golden and Header bitstreams, the following address map can be selected:
* Address * | * Bitstream * |
0x000000 | Header |
0x010000 | Golden |
0x180000 | MultiBoot |
Generating the Golden bitstream
Some bitgen flags need to be set in order to automatically generate the golden bitstream during design implementation:
- -g reset_on_err:Yes
- -g next_config_register_write:Enable
- -g next_config_reboot:Enable
- -g next_config_addr:<8-digit hex string> (two digits for Flash op-code and six digits for MultiBoot bitstream address)
- -g next_config_new_mode:Yes
- -g next_config_boot_mode:001 (to keep SPI master mode programming)
- -g golden_config_address:<8-digit hex string> (two digits for Flash op-code and six digits for Golden bitstream address)
All this can be done from the GUI of Xilinx ISE:
- Right-click Generate Programming File in the ISE processes pane
- In the General Options tab, tick -g reset_on_error
- In the Configuration Options tab:
- Tick Place MultiBoot Settings into Bitstream
- Set -g next_config_reboot to Enable
- Set -g next_config_addr to the MultiBoot bitstream address
- Tick -g next_config_new_mode
- Set -g next_config_boot_mode to 001
- Click OK
Generating the MultiBoot bitstream
Apart from setting the -g reset_on_error switch, the -g next_config_register_write switch should also be set to Disable*, to keep the values of the GENERAL configuration registers intact between subsequent reprograms. This must be done, otherwise a corrupted multiboot image will not boot back to the Golden image and the card will require a power-on reset.
Adding the BitGen flags can be done in two ways:
- If running from command line, provide the flags to bitgen:
- -g reset_on_err:Enable
- -g next_config_register_write:Disable
- If running from the ISE GUI:
- Right-click Generate Programming File in the ISE processes pane
- In the General Options tab, tick -g reset_on_error
- In the Other Bitgen Command Line Options field of the General Options tab, write the following command: -g next_config_register_write:Disable
- Click OK
Architecture
A block diagram of the xil_multiboot module is shown below. It consists of the following blocks:
Block | Description |
multiboot_regs | Wishbone interface and registers |
multiboot_fsm | Main FSM of the multiboot block |
icap_spartan6 | Xilinx ICAP IP core |
spi_master | SPI master from the bootloader design under the SVEC project |
Register map
Register | * Offset * | * Access * | Description |
CR | 0x000 | R/W | Control Register |
IMGR | 0x004 | R/O | Configuration Image Register |
GBBAR | 0x008 | R/W | Golden Bitstream Base Address Register |
MBBAR | 0x00C | R/W | MultiBoot Bitstream Base Address Register |
FAR | 0x010 | R/W | Flash Access Register |
The GBBAR and MBBAR are images of the GENERAL1..4 configuration registers [1] in the Xilinx Spartan-6 FPGA.
CR
Offset: 0x00*
Bits | Field | * Default * | Description |
31..4 | Reserved | X | Reserved bits read undefined; they should be written as '0' |
17 | IPROG | 0 | When 1, it triggers the FSM to send the IPROG command to the ICAP controller This bit needs to be unlocked by setting the IPROG_UNL bit in a previous cycle |
16 | IPROG_UNL | 0 | Unlock bit for the IPROG command. This bit needs to be set to 1 prior to writing the IPROG bit |
15..7 | Reserved | X | Reserved bits read undefined; they should be written as '0' |
6 | RDCFGREG | 0 | Initiate a read from the FPGA configuration register at address CFGREGADR |
5..0 | CFGREGADR | 0 | The address of the FPGA configuration register to read |
Notes on the control register:
- In order to read a configuration register, the following steps are
needed
- set the address of the configuration register in the CFGREGADR field (see the Configuration Registers section in [1] for configuration register descriptions)
- set the RDCFGREG bit to initiate the read
- the value of the configuration register can be found in the image register (IMGR), if the IMGR.VALID bit is set
- In order to issue the IPROG command to the FPGA, the IPROG bit first needs to be unlocked by setting the IPROG_UNL bit
- After the IPROG command is issued, the FPGA will initiate the programming sequence
- The status of the FPGA after reprogramming can be checked via the BOOTSTS and STAT configuration registers (see the Configuration Registers section in [1])
IMGR
Offset: 0x04*
Bits | Field | * Default * | Description |
31..17 | Reserved | X | Reserved bits read undefined; they should be written as '0' |
16 | VALID | 0 | Indicates the SR contents are valid, i.e., a read from a configuration register has been performed |
15..0 | CFGREGIMG | 0 | Image of the FPGA configuration register |
Notes on the status register:
- the IMGR is only valid after read from the FPGA's configuration register has been performed, by setting bit 0 in CR
- the VALID bit (bit 16) can be used to see if the current readout of the IMGR is valid
- the VALID bit is set by the FSM when a read from the configuration register has been performed via the ICAP and cleared on reprogramming
- bits 15..0 are an image of the configuration register (for details, see the Configuration Registers section in [1])
GBBAR
Offset: 0x08*
This register is an image of the GENERAL3,4 [1] configuration registers in Xilinx Spartan-6 FPGAs. Its contents are copied to the configuration registers as part of the configuration sequence of the FPGA.
Bits | Field | * Default * | Description |
31..24 | OPCODE | 0x00 | Read op-code to be sent to Flash chip |
23..0 | GBA | 0x000000 | Golden bitstream start address in Flash memory |
Guidelines on selecting a GBBAR:*
- When generating the header image via Xilinx ISE, the address of GBBAR is (usually) automatically set by the software to 0x44
- If different than the default, the starting address of the golden bitstream should be set to a flash sector boundary (e.g., for the M25P flash series, an integer multiple of 0x10000)
MBBAR
Offset: 0x0C*
This register is an image of the GENERAL1,2 [1] configuration registers in Xilinx Spartan-6 FPGAs. Its contents are copied to the configuration registers as part of the configuration sequence of the FPGA.
Bits | Field | * Default * | Description |
31..24 | OPCODE | 0x00 | Read op-code to be sent to Flash chip |
23..0 | MBA | 0x000000 | MultiBoot bitstream start address in Flash memory |
Guidelines on selecting an MBBAR:*
- The MultiBoot bitstream should start on a flash sector boundary (e.g., for the M25P flash series, an integer multiple of 0x10000)
FAR
Offset: 0x10*
This register should be used by software to access the Flash chip.
It contains the values of a maximum of three data bytes to send to the flash, as well as control bits for sending the data. The data in this register is in little-endian order.
Follow these steps to write to the flash (note that the steps can all be done at the same time via one write to the FAR):
- write the NBYTES field to select the number of data bytes to send
- write NBYTES+1 DATA fields with the data to send to the chip
- set CS to enable chip selection (leaving it cleared and setting XFER will lead to a "dummy" transfer, the equivalent of waiting for a full SPI cycle)
- set XFER to start the transfer; this bit clears itself automatically
- when the READY bit is high, NBYTES data fields have been sent (in the order DATA [0], DATA [1], DATA [2]), and the DATA fields contain NBYTES+1 bytes read from the flash chip.
Bits | Field | * Default * | Description |
31..29 | Reserved | X | Reserved bits read undefined; they should be written as '0' |
28 | READY | 1 | 1: SPI transfer is ready (NBYTES sent and received) 0: SPI transfer in progress |
27 | CS | 0 | Chip select bit. Inverted with respect to SPI chip select, which is normally active low. 1: Selects the Flash chip (CS pin = 0) 0: Flash chip not selected (CS pin = 1) |
26 | XFER | 0 | 1: Start sending NBYTES over SPI 0: No effect This bit clears itself automatically |
25..24 | NBYTES | 0 | Number of bytes to send during one transfer 0: send DATA [0] 1: send DATA [0], DATA [1] 2: send DATA [0], DATA [1], DATA [2] 3: Reserved |
23..16 | DATA [2] | 0x00 | Write this register with the value of data byte 2 After an SPI transfer, this register contains the value of data byte 2 read from the flash |
15..8 | DATA [1] | 0x00 | Write this register with the value of data byte 1 After an SPI transfer, this register contains the value of data byte 1 read from the flash |
7..0 | DATA [0] | 0x00 | Write this register with the value of data byte 0 After an SPI transfer, this register contains the value of data byte 0 read from the flash |
The example below shows the setting of the FAR register for different number of data bytes sent to the chip.
Sending bytes 0xAA 0xBB (in that order) to the flash chip:
DATA[0] = 0xAA
DATA[1] = 0xBB
DATA[2] = unimportant
NBYTES = 0x1
XFER = 1
CS = 1
FAR = 0x0D00BBAA
Sending bytes 0x11 0x22 0x33 (in that order) to the flash chip:
DATA[0] = 0x11
DATA[1] = 0x22
DATA[2] = 0x33
NBYTES = 0x2
XFER = 1
CS = 1
FAR = 0x0E332211
Finite-state machine
SPI master interface
The spi_master module in the xil_multiboot module implements an eight-bit SPI master interface with the following settings:
- CPOL = 0
- CPHA = 1
Thus, the idle state of SCL is high and bits are shifted out on the MOSI line on the falling edge of SCL, and shifted in on the MISO line on the rising edge of SCL.
References
[1] Xilinx UG380: Spartan-6 FPGA Configuration, User
Guide
[2] Xilinx SP605 MultiBoot
Design
Theodor-Adrian Stana, Oct. 2013