概要
Altera / Intel 製 FPGA のビットファイル(コンフィグレーションデータ)のフォーマットをリバエベースで解説する
本記事では確認できたことのみを述べるにとどまる
(不具合、故障等は責任を持ちません)
環境
Quartus Prime Lite 22.1
Ubuntu
FPGA : MAX10(10M25SAE144A7G)
実装回路:1 Hz Lチカ
SOF と POF (多分)
現時点(23/11/09)では SOF と POF においてファイルフォーマットの違いは確認できなかった
SOF : Sram Object File
FPGA の SRAM 部へ書き込む際に Quartus プログラマで使用する
POF : Programmer Object File
MAX 等の Flash へ書き込む際に Quartus プログラマで使用する
フォーマット概要
12 Byte からなるファイルヘッダと複数のパケットで構成される。一番最後のパケットはターミネータパケットとなる
File Header 部(12 Byte 固定?)
File Header 部はフォーマットID、謎、パケット数で構成される
ID(3 Byte)
3 Byte で構成される
SOF なら S
O
F
POF なら P
O
F
となる
謎(5 Byte)
詳細不明
SOF では 0
0
0
0
0
POF では 0
0
0
1
0
が確認できている
パケット数(4 Byte)
以降に続くパケットの数を格納している
エンディアンはリトル
Packet 部(6+可変長)
Packet 部はパケットTag、パケット長、データで構成される
Tag(16 bit)
パケットが何のデータなのか記載されている
エンディアンはリトル
Tag = 8 のときターミネータとなり2 Byte のデータ部に CRC が記載される
Length(32 bit)
パケット長を格納している
data(可変長)
データ
Tag について
詳細は公開されていない
ref -> https://community.intel.com/t5/Programmable-Devices/I-want-knowing-POF-file-format-structures/td-p/74357?profile.language=ja
Appendix
解析例
解析app
package main
import (
"os"
"encoding/binary"
"fmt"
)
type Header struct {
Fmt []byte
Ln uint32
Z []byte
}
type Packet struct {
Tag uint16
Ln uint32
D []byte
}
func main() {
println(os.Args[1])
fp, err := os.Open(os.Args[1])
defer fp.Close()
if err != nil {
println("File Open Error")
}
fi, _ := fp.Stat()
fs := fi.Size()
println("File Size =", fs, "\n")
var h Header
h, fs = rdHead(fp, fs)
println("Left = ", fs)
p := make([]Packet, h.Ln)
for i := uint32(0); i < h.Ln; i++ {
println("\nN =", i)
p[i], fs = rdPacket(fp, fs)
printPacketHead(p[i])
if p[i].Tag == 8 {
printPacketData(p[i])
}
println("Left = ", fs)
}
}
func rdHead (fp *os.File, fs int64) (Header, int64) {
var h Header
h.Fmt = make([]byte, 3)
h.Z = make([]byte, 5)
binary.Read(fp, binary.LittleEndian, &h.Fmt)
binary.Read(fp, binary.LittleEndian, &h.Z)
binary.Read(fp, binary.LittleEndian, &h.Ln)
println(string(h.Fmt))
for i := 0; i < len(h.Z); i++ {
// fmt.Printf("%d : %02x = %d\n", i, h.Z[i], h.Z[i])
}
println("Packet NUM =", h.Ln)
return h, fs - 12
}
func rdPacket (fp *os.File, fs int64) (Packet, int64) {
var p Packet
binary.Read(fp, binary.LittleEndian, &p.Tag)
binary.Read(fp, binary.LittleEndian, &p.Ln)
p.D = make([]byte, p.Ln)
binary.Read(fp, binary.LittleEndian, &p.D)
return p, fs - int64(p.Ln + 6)
}
func printPacketHead(inp Packet) {
fmt.Printf("id : %d \n",inp.Tag)
fmt.Printf("length : %d \n", inp.Ln)
}
func printPacketData(inp Packet) {
if inp.Id == 8 {
fmt.Printf("%c %c : %02x %02x", inp.D[0], inp.D[1], inp.D[0], inp.D[1])
println()
} else {
for i := uint32(0); i < inp.Ln; i++ {
fmt.Printf("%d : %02x = %d\n", i, inp.D[i], inp.D[i])
}
}
}