Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

Binary format for Stratix IV Image in a NOR CFI Flash?

My application requires that a host system can write a new FPGA image into an on board Nor Flash (CFI intel P30 style 16 bit flash).

Without using a JTAG pod, or Quartus Programmer.

Instead, the flash becomes memory mapped to a host CPU PCI Express address space. The question is how to format the data correctly from the system host?

The board uses Altera's Parallel Flash Loader in a MAXII CPLD to configure the FPGA from NOR flash in Fast Passive Parallel Mode.

I can program the flash successfully using the Quartus programming JTAG tools, and the FPGA loads those designs up correctly.

When I examine the flash contents, I see a 4 byte preamble at the start of the memory partition, that is not included in a Raw Binary File (.rbf) when I use the Quartus "Convert Programming File" tools.

It looks like this:

0x0000

0x042D

Then the data following that preamble matches the .rbf contents (except for byte swapping).

Is this preamble documented anywhere? Is there more at the back end as well?

I have been unable to find any documentation on this preamble..

6 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Replying to this post since it does quite well on Google, and I spent a lot of time tracking down the details.

    The 0x04 is a version number of the pof header. The PFL Parallel Flash Loader IP inside the configuration CPLD expects to find this, if your bitstream binary header (0xffff, repeating) is found in it's place, the PFL configuration fails. You can inspect generated VHDL code for the PFL flash to determine the format but it is not fun. The .pof headers also include 13-15 bits of length/checksum information, depending on version. Once that many bytes are read, another pof header is expected.

    I found this Altera ticket helpful to generate a binary file with PFL headers: http://www.altera.co.uk/support/kdb/solutions/rd08082012_952.html

    Briefly:

    1) Generate .sof files during Quartus compilation.

    2) Use 'Convert Programming File' tool to lay out multiple bitstreams in the same file, in expected locations, and write header bits, giving .pof file.

    Page0 - not present

    Page 1 @ 0x00040000

    Page 2 @ 0x02140000

    3) Use quartus_cpf to get a .hexout file. This contains the bitstreams with PFL/.pof packetisation, but is in a 7-bit ascii/Intel HEX .hexout representation.

    $ quartus_cpf -c c:\\workspace\\flash_topboot.pof c:\\workspace\\flash_topboot.hexout

    4) use nios2-elf-objcopy to convert .hexout to .rbf

    $ nios2-elf-objcopy.exe -I ihex -O binary c:\\workspace\\flash_topboot.hexout c:\\workspace\\flash.rbf

    5) check format with od

    $ od -A x -t x4 /cygdrive/c/workspace/flash.rbf

    000000 ffffffff 20860040 41862140 ffffffff <- PFL options block (no Page0, defined Page1 and Page2) as documented in PFL docs

    000010 ffffffff ffffffff ffffffff ffffffff

    *

    000080 ffffff03 ffffffff ffffffff ffffffff

    000090 ffffffff ffffffff ffffffff ffffffff

    *

    040000 05fc0401 ffffffff ffffffff ffffffff <- start of first bitstream, POF Version x04 for block 1

    040010 ffffffff ffffffff ffffffff ffffffff

    *

    040080 ffffffff 6a6a6a6a fffff236 fffffa77

    040090 fffff1b6 fffff03d fffff7f6 fffff477

    0400a0 fffff9b3 fffff8ba fffff35a fffff27a

    0400b0 fffff61b fffff759 fffff87a fffff959

    0400c0 fffff418 fffff6bc fffff07d fffff698

    0400d0 fffff47d fffff63f fffff27a fffff19c

    0400e0 fffff118 fffff1fd fffff7fd fffff519

    0400f0 fffff059 fffff019 fffff2d9 fffff019

    040100 fffff29d fffff15d fffff71c fffff75d

    040110 fffff30b fffff75f fffff49a fffff46a

    040120 fffff19a fffff96a 551b0000 ffffffff

    040130 ffffffff ffffffff ffffffff ffffffff

    *

    040600 05940401 00000000 00000000 00000000 <- repeat of POF Header for block two, 600 bytes after

    040610 00000000 00000000 00000000 00000000

    040620 00000000 00000000 00000000 48004800

    040630 48004800 00000000 00000000 48004800

    040640 00000000 00000000 00000000 00000000

    *

    040790 00000000 40000000 00000000 00000000

    0407a0 00000000 00000000 00000000 00000000

    0407b0 40000000 00000000 00000000 00000000

    *

    0407d0 00000000 00000000 00000000 00000000

    *

    0408b0 00000000 00000000 00000000 48004800

    0408c0 00000000 00000000 00000000 00000000

    *

    0408e0 00000000 00000000 48004800 00000000

    0408f0 00000000 48004800 00000000 48004800

    040900 48004800 00000000 00000000 00000000

    040910 00000000 00000000 00000000 00000000

    *

    040940 00000000 00000000 40000000 00000000

    040950 40000000 00000000 40000000 00000000

    040960 40000000 40000000 00000000 00000000

    040970 40000000 40000000 40000000 40000000

    040980 00000000 00000000 40000000 00000000

    040990 40000000 00000000 40000000 00000000

    0409a0 40000000 00000000 00000000 40000001

    0409b0 40000001 00000001 40000001 00000001

    0409c0 00000001 40000001 00000001 00000001

    0409d0 00000001 00000001 40000001 40000001

    0409e0 00000001 40000001 00000001 00000001

    0409f0 00000001 40000001 01000001 40000000

    040a00 00000000 00000000 00000000 00000000

    040a10 40000000 00000000 00000000 40000000

    040a20 00000000 00000000 00000000 00000000

    040a30 00000000 00000000 00000000 41020000

    040a40 00000000 00000000 01020000 41020000

    040a50 01020000 01020000 00000000 00000000

    *

    040a70 01020000 00000000 40000000 40000000

    040a80 00020000 01020000 00000000 00000000

    040a90 00020000 00000000 01020000 00000000

    040aa0 00020000 00000000 00020000 00000000

    040ab0 00020000 00000000 01000000 00000000

    040ac0 00000000 00000000 00000000 00000000

    *

    040ae0 00000000 00000000 00000000 00020000

    040af0 00000000 00000000 00000000 00000001

    040b00 00000001 00020001 00000001 41020001

    040b10 41020001 41000000 41000001 00000001

    040b20 40000001 00000001 40000001 00000001

    040b30 40000000 01020000 00000000 01020000

    040b40 40000000 00020000 00020000 01020000

    040b50 00020000 410000c0 00020000 000000c0

    040b60 000000c0 00000000 00020000 00000000

    040b70 00020000 41020000 00020000 01000000

    040b80 00020000 00000000 00020000 00000000

    040b90 40000000 21530000 05940401 00000000 <- repeat of POF Header for block three

    040ba0 01020000 00000000 01020000 00000000

    040bb0 00000000 000000c0 010200c0 000000c0

    040bc0 000000c0 00ec002f 00000000 01020000

    040bd0 00000000 01020000 00000000 00000000

    040be0 00000000 01020000 00000000 01020000

    040bf0 00000000 00000000 00000000 01020000

    040c00 00000000 01020000 00ec00ef 00000000

    040c10 00000000 00ec002f 01ee002f 00ec00ef

    040c20 01ee002f 00000000 00000000 41ee002f

    6) If you want to flash specific regions of this file, use $dd to cut out byte ranges and use your flash programming routines to write them.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Awesome! Thanks shuckc, exactly what I needed.

    I spent some time trying to figure out why when I convert a sof to rbf directly using the quartus_cpf command

    i.e. quartus_cpf -c <input_sof_file> <output_rbf_file>

    the rbf file would not match what I saw in the flash (i.e. it lacks the "PFL/.pof packetisation" headers you mentioned).

    However, your method of sof->pof->hexout->rbf matches what I see in the flash.

    It is unfortunate that Altera provides different ways to generate a rbf file from an sof, each with different results.

    I wish Altera would make these things more obvious instead of searching through forum posts and knowledgebase tickets for obscure details.
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Great information. I have the same configuration. Flash connected to cpld and uses the PFL to configure the fpga at power up. In the fpga code I've added the ability to connect the fpga IO lines to the flash (of course disconnect from cpld) and have memory mapped the flash into my pcie memory space. I used the tristate controller and tristate bridge to connect the Avalon bus to the flash IO pins. (BAR2 starting address 0x0) I have some questions.

    When you use od to dump the rbf file I'm assuming the * are gaps in the file?

    So after I erase the entire flash, do I program the flash by writing the rbf file starting at flash address 0x0 and increment the address every write cycle? (Assuming I'm using the slow write one word at a time method for my question.)
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Answered my question about OD, so the * are just covering redundant information, the -v option displays all.

    So I'm assuming if I erase the entire flash just to write the data starting at address 0x0?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    That's correct, "*" in OD simply hides addresses that duplicate the previous row in the memory dump. The PFL options block should lie at physical address zero within the flash space. You can do a partial erase on most flash chips, check the flash chip command set for details. Once I have the options block programmed and working I leave it protected and just erase/unlock the sectors required to write the flash image, e.g. 0x040000- above.

    On my board the CPLD and FPGA arbitrate tri-state access to the flash with a simple request/grant protocol on 2 separate pins. Since both chips have the configuration clock used during configuration it's easy to arbitrate within the same clock domain. I have my own QSYS module that wraps up the indirect read/write/erase of the flash chips which is then mapped into PCIe space BAR0 (any BAR will do). I prefer *indirect* access for this type of thing as you don't want an errant process invalidating the bitstream configuration, and the flash controllers usually require some slow command protocol for programming that is better left to software rather then fully implementing in hw to get a writeable flash space. Plus you don't really need the 32mb or so directly exposed to the host anyway.

    The configuration mode I use is 32bit fast parallel, so I use 2x 16-wide flash chips to supply this. The PFL loader is fine driving both in read mode (during configuration) since the address bits are common. For programming you need to take care of duplicating the commands on both of the 16bit data bus to make sure you keep both flash command state machines in the same state.