0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

SOF ファイルフォーマット リバエベース 解説

Posted at

概要

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 プログラマで使用する

フォーマット概要

image.png


12 Byte からなるファイルヘッダと複数のパケットで構成される。一番最後のパケットはターミネータパケットとなる

File Header 部(12 Byte 固定?)

image.png


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+可変長)

image.png
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

解析例

image.png
同じコンパイルで得られた Max10 の SOF, POF

解析app

main.go
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])
		}
	}
}

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?