[IP][Avalon] I2C master controller wrapper

2010/05/19FPGA::IPimport

はじめに

自作部分はAvalon SlaveにWISHBONEモジュールをぶら下げるためのBridgeのみなので、ほかのモジュールにも転用できるかと思います。

【注意】本記事は、16ヶ月ほど前のコードと資料を元に作成しており、i2c_masterもversionがあがっております.WISHBONEおよびI2Cインタフェース部分にも修正が入っているようなので、最新版での動作保障はありません.現状、環境がないので確認できません…

自製部分のみ、_IP_I2C_v000.zipとして置いておきます。tclも入れておきますが、FatFSのときのように動作確認をしていませんので、ご了承いただきたく。実際に使ったサンプルコードも置いておきます(avalon_i2c.zip)。\いまさらですが、writeしか使ってない模様…。WM8731へは書きっぱなしでよかったのかな... 記憶があいまいデスすみません.

概要

I2C MasterとなるIPです.\本IPは,opencores.orgで開示されている,以下のものをベースとしました.

http://www.opencores.org/
  "I2C controller core"
  Category :: Communication controller
  Name: i2c
  Created: 25-Sep-2001 10:15:03
  Updated: 03-Nov-2008 14:55:35

  Category :: Communication controller
  Language :: Verilog
  Language :: VHDL
  Phaze :: ASIC proven
  Phaze :: Design done
  Phaze :: FPGA proven
  Standard :: Wishbone compliant core
  Development status :: Production/Stable



Rev. 0.9  Release data: 03/07/03
i2c_specs.pdf

収録ファイルと個々の概要説明

  • avalonif_i2c.txt

このファイル.IPの簡単な説明等を記載する

  • avalonif_i2c_hw.tcl

SOPC builderが食うファイル. Avalon-MM I/Fの仕様や追加すべきファイル,パラメータ初期値などの情報が入っている.

  • avalonif_i2c.v

Avalon I/Fを含む本モジュールのtopレベルモジュールを記述したファイル. "i2c_master_top.v"と同等の機能を有す.(moduleとSystem BUSの仲介だけ)

以下、i2cオリジナルに含まれるものです。

  • timescale.v
  • i2c_master_defines.v
  • i2c_master_byte_ctrl.v
  • i2c_master_bit_ctrl.v
  • i2c_master_top.v

実装時の注意事項

I2Cバスの信号である,SDA/SCKは外部Pull Upになり,master/slaveはopen drainで駆動します.本IPも,各信号をLowに落とすときだけ,Padのenable信号を出すように作られています.tope level moduleには,以下の信号が出ています.

  sda_padoen_o
  sda_pad_o
  sda_pad_i
  scl_padoen_o
  scl_pad_o
  scl_pad_i

PADの出力値は,sda_pad_o(scl_pad_o)に出てきます.ただし常にLowでGND接続になります.\PADからの入力は,sda_pad_i(scl_pad_i)を通して行います.\最後に,PADの出力制御は,sda_padoen_o(scl_padoen_o)を用い,active lowです.\highのときは,PADはドライブせず,Hi-Z状態としてください.\※詳細はオリジナルのドキュメントを参照していただきたく.

Verilog-HDLでの記述例を示します.\NEEKなど,シングルマスタを想定してプルアップしていない回路では,コメントアウトしたほうを用いてください.ただしデータに関しては双方向と成るため,Pull Upは必須と成ります.\# I2Cとした時点で,CLK/DAT双方ともPullUpすべきだと思うのですが...

module xxx (
  inout HC_I2C_SDAT,
  HC_I2C_SCLK,
  ...
 ) ;


assign sda_pad_i = HC_I2C_SDAT ;
assign HC_I2C_SDAT = (sda_padoen_o==1'b0 ? sda_pad_o : 1'bz) ;
assign scl_pad_i = HC_I2C_SCLK ;
assign HC_I2C_SCLK = (scl_padoen_o==1'b0 ? scl_pad_o : 1'bz) ;
// assign HC_I2C_SCLK = scl_padoen_o ; // if Single Master and No-Pull Up(for NEEK)


slave address = 7'b0011010 @ CSB = Low at NEEK


ハードウェア仕様

モジュールのアドレス空間

offset symbol description
0Status / RxData
1Command Register
2Control / TxData
3preI2C clock prescaler

"Command"

7STASTART condition
6STOSTOP condition
5RDRead Data
4WRWrite Data
3ACKwhen receiver(1:ACK/0:NACK)
2-
1-
0IACK1書き込みで要因クリア

"Control / TxData"

31ENEnable I2C core
30IENinterrupt enable
29-24-reserved
23-8-reserved
7-0txdataTransmit data. slaveアドレス送信時はLSBがdirection(1:R/0:W)を示す

"Status"

31-16-reserved
15RxACKスレーブからのACK受領ステータス.0で受信,1で未受信
14Busy1:STArt detected, 0:STOp detected
13ALArbitration Lost
12-10reserved
9TIP1: 転送中, 0:転送完了
8IF割込みフラグ.転送完了もしくはArbitration Lostでたつ
7-0rxdata

プリスケーラの値は,下記の算出式により得ることができます.

(document 3.2.1参照)
IPの動作クロックを f_clk[Hz],SCLKの周波数を f_sclk[Hz]とします
  value of pre-scaler = f_clk / (5 * f_sclk) - 1

ex.)
  f_clk  = 18.432MHz
  f_sclk = 500kHz

  value of pre-scaler = 18432 / (5 * 500) - 1  = 6.3728 => 7 

2009/03/02(月)[SOPC][IP] MMC/SPI FatFs - f_writeベンチマーク

[SOPC][IP] MMC/SPI FatFs - f_writeベンチマーク

[SOPC][IP] MMC/SPI FatFsで紹介しているFatFsについて,コメント欄で問合せいただいたファイル書き込み速度のベンチマークをとってみました.


ベンチマーク概要

FatFsのfopen("wb"相当)で確認する

File systemを使う場合でのベンチマークをとることをテーマとする.*1


脳内シミュレーション(a.k.a.妄想)

FatFs(R0.06)ソースコードより,以下の特徴が推定できる.

  • FatFsはマルチセクタライトもサポートしている模様.
  • セクタ境界・クラスタ境界でクラスタ調整・更新・buffer吐き出し処理を走らせる模様.

上記を踏まえてベンチマークを取得すべきケースは以下のパターンを考えた.

  • クラスタサイズでの一括書き込みが最高スループットを出すだろう
  • クラスタをまたぐ,ランダムアクセスが最低速になる.
  • バッファサイズ(またはセクタサイズ)をまたぐ場合も同様.

ベンチマーク対象とコード

[NiosII][ACM] 動画再生装置(お試し版)の構成で試しているため,キャッシュの影響が結構効いてくることも考えられるので,データ転送量を2Mbytesとします.

実行時間測定には,パフォーマンスカウンタを用います.カウンタを3つとして合成してあるので,測定対象を以下のように絞ります.(なんとなく時間のかかりそうなところ,短縮できそうなところに目星をつけてみたつもりです)

  • 総合時間(規定サイズ・規定回数のブロック転送に要した時間.出力されたファイルの検証は行うべき)
  • SPI転送待ち時間
  • 書き込みデータのCRC計算
ベンチマーク部分本体
const int trans_size[] =
	{
	512*64,
	512*128,
	512,
	4096,
	1024,
	64,
	256,
	768,
	1280,
	1636,
	2048,

	0
	} ;

const int sz_write = 512*2*1024*2 ;

~~~
	while (*sz) {
        f_unlink( fn ) ;    // delete the file before test

        if ((res = f_open (&fp, fn, FA_WRITE|FA_OPEN_ALWAYS|FA_CREATE_ALWAYS)) != FR_OK) {
            return (res | 0x1000);
        }
		// size / loop
		i = 0 ;
		PERF_RESET( PERFORMANCE_COUNTER_BASE );
		PERF_START_MEASURING( PERFORMANCE_COUNTER_BASE );
		PERF_BEGIN( PERFORMANCE_COUNTER_BASE, 1);
		do {
			res = f_write(&fp, sdbuf[ i  ], *sz, &rsz) ;
			if (res != FR_OK || rsz == 0) {
				printf ("Error : Bench-fwrite (%d/%d)\n", res, rsz);
				break;
			}
			i +=  rsz;
		} while (i<sz_write) ;
		PERF_END(PERFORMANCE_COUNTER_BASE, 1);

		PERF_STOP_MEASURING(PERFORMANCE_COUNTER_BASE) ;
		printf( "*** fwrite-size = %d ***\n", *sz );
		perf_print_formatted_report( (void*)PERFORMANCE_COUNTER_BASE, alt_get_cpu_freq(), 3, "total ", "xmit","CRC" );
		WAIT_SEC(5) ;

        f_close(&fp);

		sz++ ;
	}

データ転送部・CRC計算部の処理時間測定位置(mmc.c)
BOOL MMC_xmit_datablock(const BYTE * buff,  /* 512 byte data block to be transmitted */
                    BYTE token  /* Data/Stop token */
    )
{
    BYTE resp, wc = 0;
#ifdef _CALC_CRC
PERF_BEGIN( PERFORMANCE_COUNTER_BASE, 3);
    WORD crc = CRC16((BYTE *) buff, 512);
PERF_END(PERFORMANCE_COUNTER_BASE, 3);
#endif

    if (MMC_wait_ready() != 0xFF)
        return FALSE;

PERF_BEGIN( PERFORMANCE_COUNTER_BASE, 2);
    MMC_xmit_spi(token);            /* Xmit data token */
    if (token != 0xFD) {        /* Is data token */
        do {                    /* Xmit the 512 byte data block to MMC */
            MMC_xmit_spi(*buff++);
            MMC_xmit_spi(*buff++);
        } while (--wc);
#ifdef _CALC_CRC
        MMC_xmit_spi(crc >> 8);     /* CRC */
        MMC_xmit_spi(crc & 0xff);
#else
 @       MMC_xmit_spi(0xFF);         /* CRC (Dummy) */
 @       MMC_xmit_spi(0xFF);
#endif
        resp = MMC_rcvr_spi();      /* Reveive data response */
        if ((resp & 0x1F) != 0x05)      /* If not accepted, return with error */
            return FALSE;
    }
PERF_END(PERFORMANCE_COUNTER_BASE, 2);

    return TRUE;
}

*1 : SDカード本来の性能を最大限に生かすのであれば,マルチセクタライトコマンドを放っておけばよいだろう.

測定結果

使用用したカードは,Transcend mini SDカード 2GBをSDアダプタに挿したものです.

    • セクタあたりのバイト数は,512bytes.
    • クラスタあたりのセクタ数は,32です.
    • データセクタエリアの理想write回数は,4096回,128クラスタを消費します.
    • FATエリアの1セクタあたりのクラスタ数:FAT16ならば1セクタに256個,FAT12なら341個を格納できます.

2MBytesのファイルがクラスタ不連続になっているかどうかの確認をしていません.個人的に使用しているSDカードで,この評価用に使っていないため,テスト用のファイルがクラスタ連続で使用しているかは未確認です.あき暮らす他の探索は先頭からのシーケンシャル探索であり,ファイルのunlink処理では空きクラスタにしているため,パフォーマンスの比較に影響は無いと考えました.


結果のまとめと考察

測定結果と主要項目一覧
転送サイズ総時間512byte書込転送要求回数着目点
655364.03239+712クラスタ,マルチセクタCMD
327684.92526+891クラスタ,マルチセクタCMD
40964.43872+5138セクタ連続書込み,1/8クラスタ,マルチセクタCMD
20484.43872+10254セクタ連続書込み,マルチセクタCMD
1636204.466+12713セクタ連続書込み,100バイトコピー,クラスタ境界をまたぐ,マルチセクタ+シングルセクタCMD
1280135.29+16152セクタ連続書込み,256バイトコピー,マルチセクタ+シングルセクタCMD
10247.80936+20491/32クラスタ,マルチセクタCMD
768199.459+13セクタ連続書込み,クラスタ境界をまたぐ
51213.9297+11/64クラスタ, 1セクタ,シングルライトコマンド
25614.0029+01/2セクタ,シングルライトコマンド
6414.0578+61/8セクタ,シングルライトコマンド
  • セクタ境界をまたがないときは,内部バッファへのコピー処理が走る\→ セクタ数の整数倍ではないモノ全てが対象.\とくに小さいものはコピー処理とループ処理で時間を消費する
  • セクタ境界をまたぐと,書き込み処理が走る.\場合によってはリード処理も走る.
  • DRAM間のコピー処理は効率も悪く,処理時間が延びる傾向にある

考察

転送呼び出し回数と,処理時間とが比例していないのは,MMC側の書き込みバッファがあって,連続した書き込み要求は待たされるが,完結して呼び出す分にはFLASHへの書き込みと,ソフトの走行がパラで走っている状況である,と推察する.

512の整数倍・約数を除く転送サイズでは,軒並み桁違いの遅さが目立つ.メモリコピー処理に加えて,セクタ・クラスタ境界をまたぐ処理が追加されるためと考えらる.加えて,端数はシングルセクタライトコマンドを用いるため,転送効率が悪化すると見られる.

1024byte時に中途半端な速度になっているのは,SD内のFLASH書込み待ち時間が発生しているためと考えられる.

512以下の約数では,不要なコピー処理が走らないが,シングルライトコマンドによるコマンド・レスポンス処理時間がかかるため,カードのbuffered-writeが機能しないのかもしれない.




実行結果ナマデータ

fwrite-size = 32768

Total Time: 4.92526 seconds (487789773 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total1004.925264877897671
xmit29.91.471581457432374185
CRC51.52.534742510364714185

fwrite-size = 65536

Total Time: 4.03239 seconds (399361828 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total1004.032393993618221
xmit36.31.465131451044754167
CRC62.52.518662494441814167

fwrite-size = 512

Total Time: 13.9297 seconds (1379575366 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total10013.9296913795753601
xmit10.51.457821443799864097
CRC19.72.741222714866154097

fwrite-size = 4096

Total Time: 4.43872 seconds (439603921 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total1004.438724396039151
xmit331.463601449530084609
CRC64.32.854522827077134609

fwrite-size = 1024

Total Time: 7.80936 seconds (773427070 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total1007.809367734270641
xmit18.71.461001446947596145
CRC50.83.966453928315936145

fwrite-size = 64

Total Time: 14.0578 seconds (1392260079 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total10014.0577713922600731
xmit10.41.465021450932744102
CRC20.12.831102803873134102

fwrite-size = 256

Total Time: 14.0029 seconds (1386825298 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total10014.0029013868252921
xmit10.41.462951448886934096
CRC202.801532774594664096

fwrite-size = 768

Total Time: 199.459 seconds (19754119034 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total100199.45907197541190281
xmit0.7321.460151446106294097
CRC1.32.594872569914484097

fwrite-size = 1280

Total Time: 135.29 seconds (13398914257 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total100135.29001133989142511
xmit1.081.461521447470515711
CRC2.683.623653588810705711

fwrite-size = 1636

Total Time: 204.466 seconds (20250035225 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total100204.46638202500352191
xmit0.7181.467311453200055367
CRC1.663.392833360204435367

fwrite-size = 2048

Total Time: 4.88632 seconds (483933442 clock-cycles)

Section %Time (sec) Time (clocks)Occurrences
total1004.886324839334361
xmit301.463841449761165121
CRC65.33.190863160180685121


今後の課題

SD側の応答待ち時間の計測,f_write内の分岐処理回数を付け加えれば,想像の裏づけを取ることもできるだろう.

カードの性能にも左右されるベンチマークであるため,必ずしも上記の結果どおりとはならないでしょう.カード性能を測定するベンチマークハードウェアを作るのも面白いかもしれませんね.File systemを無視して,SDのwrite buffer sizeや応答時間なんかの測定を自動的にやってくれるのがあると,実力チェックに使えて面白そうです.

実使用に耐えるかどうかを判断するためには,file system経由での(sequential|random)(read|write)も必要でしょう.

まぁ,あくまでもMMCのベンチマークということで... :p

2009/02/12(木)[SOPC][IP] MMC/SPI FatFs

[SOPC][IP] MMC/SPI FatFs

MMC/SDカードのアクセスを行うためのIPです.\ オリジナルは長船さん作成のVHDLで記述されたものでした.\ Verilogに移植して,ソフトウェア部分もFatFs(R0.06, Apr 01, 2008)に 差し替え,BBSにあったLFN対応パッチもマージしました*1.\ それぞれNEEK向けに修正*2してあります.


*1 : ただし,7bit文字のみ対応.2バイト文字はUNICODEになるので,このままではうまく認識されません.

*2 : WP/CS信号を常時Lowに変更.tclを編集\ set_interface_property avalon_slave_0 addressSpan 1024

収録ファイルと個々の概要説明

  • avalonif_mmcdma.txt\ このファイル.IPの簡単な説明等を記載する
  • avalonif_mmcdma_hw.tcl\ SOPC builderが食うファイル. Avalon-MM I/Fの仕様や追加すべきファイル,パラメータ初期値などの情報が入っている.
  • avalonif_mmcdma.v\ Avalon I/Fを含む本モジュールのtopレベルモジュールを記述したファイル.
  • SDIF.v\ SPIモードのビット転送モジュール.
  • SDIF_MEM.v\ Mega Wizardで生成したSRAMモジュール.\ 8bit write, 32bit readの512bytesメモリ.\ 出力にはバッファを設けず,readaddressにしたがってq出力が出てくるようにしてある.

ダウンロード


ハードウェア仕様

モジュールのアドレス空間

offset symbol description
0statusSPIステータス,送受信データ(8bit)
1divideSPI clockに用いるmodule入力クロックの分周比(FofSCK = 入力周波数/divide/2)
2timerタイムアウト検出用ダウンカウンタ(module input clockで動作).0で止まる
3reserved0(予約/現実装ではstatusが見える)
4dmastatusDMAステータス
5~reserved[123](予約)
128~readbuff[128]DMA転送バッファ(現状読み出しのみ)

※offsetは,32bit word指定.CPUからのアドレスは x4して見える.※使用メモリ256Word = 1024Byte = 10bit

ビットフィールド

status(MMC IF status) レジスタ
bit description mmc_spi.hシンボル
31-16const zero-
15割込み許可フラグ1:mmc_irq_enable
14-13const zero-
12MMC I/F FRCゼロフラグ1:mmc_zf_bitmask
11MMC-Write Protect1:mmc_wp_bitmask
10MMC-Card Detection1:mmc_cd_bitmask
9MMC I/F転送フラグ(0書き込みで転送開始要求)1:mmc_commexit / 0:mmc_commstart
8MMC Chip Select(Active Low)1:mmc_selnegete / 0:mmc_selassert
7-0MMC I/F受信データ8bitデータ.読み出し=RxData,書き込み=TxData(txdataのリードバック不可)

dmastatus レジスタ
bit description mmc_spi.hシンボル
31-16const zero-
15DMA function IRQ enable bit(1:enable, 0:disable)mmc_dmairq_enable
14assert(0->1) when transfer-endsmmc_dmadone_bitmask
131:受信データエラー@SPImmc_dmade_bitmask
121:受信タイムアウト@SPImmc_dmato_bitmask
11const zero-
10w1:転送開始,r1:転送中/r0:転送終了mmc_dmastart
9const zero-
8-0転送バイト数-


ハードウェアの動作イメージ

MMC/SDからのデータ読み出し

読み出し時,DMA機能を用いることで,本モジュールのアドレス空間に配置されているバッファメモリにSDからのデータを転送することができます.
MMC/SDからの転送は,byte単位で行われるため,CPUで転送するよりは高速な読み出しが可能でしょう.\ただし,転送できるメモリは本モジュール内の先頭からのみという制約もあります.

※ポートを読み出してのPIO転送も勿論可能です.

Avalon-MM Master portを増設し,Avalon-DMAを内包すれば,任意の空間への転送も可能となるでしょう.


MMC/SDへのデータ書き出し

書き込みについては,バッファからの転送は未サポートであり,PIO転送する必要があります.



注意事項

DMA転送を要求した際には,SDIF module(SDIF.v)のアクセスを本IPのtop level moduleが行うため,ユーザがCPU等からアクセスしてはいけません.\dmastatusの読み出し動作のみ許容します.(DMA転送の終了をポーリングで知るため)\SDIFのほかのレジスタへのアクセスを試みても,本IPのステートマシンがSDIFへのアクセスを占有し,statusレジスタの値しか参照できない状態となります.

2009/02/10(火)[NiosII][ACM] 動画再生装置(お試し版)

はじめに

NEEKを使用したACM code*1データの再生装置を試作してみた.ALTERA FPGA/cyclone IIIを用いて,NiosIIコア,SOPC Builder・QuartusIIなどの使用に慣れることを目的とした事例である.

実機動作動画

ニコニコのほうにうpしておいたので,会員の方は参照されたい.


構成

cycloneIII内部のブロック図を以下に記す.(UWXGAであればpixel/dotで表示できるだろう)

system_block.png
\図中,背景色が赤いモジュールが自主開発となるモジュールである.\制御ソフトやHDL記述については,別所で記載したいと思う.(ゼロから作り上げたものは少なく,多くは参照したコードやHDL記述がある)

また,システム構成として,NEEKのブロック図を引用させていただく.

Blk_LCD.png
Blk_NEEK.png

本試作においても,全てのリソースを使用しつくしていない.半田付けもせずに.それなりに遊べる評価ボードであると考える.


緒言

ITEM Description part name
FPGAAltera Cyclone IIIEP3C25F324
Parallel Flash Memory8M x16 low voltage parallel flashPC28F128P30B85
DDR SDRAM4M x16 x 4 DDR SDRAMA2S56D40CTP-G5PP
Syncronus SRAM256K x 32 synchronous SRAMIS61LPS25636A-200TQL1


*1 : 適応的コードマッピング(Adaptive Code Mapping).ALTERAで行こう!にて公開されている軽量動画フォーマットです.ここでは,Rev20080421を便宜上v0.1と書かせていただきます.

ブロック説明

前述したブロック図を,SOPC Builderで配置・接続した例を以下に示す.

SOPC_view_ALL.PNG

基本的には,NEEKサンプルの"picture_viewer"をベースとして捕らえ,QuartusIIでフルスクラッチでプロジェクトを作成した.\チュートリアルでは,既存プロジェクトを改変して云々とあるが,新規に自主開発を行ううえで必要となる知識を得ることができないと判断した.\そもそもQuartusIIのver.upに伴う差分に対応できるかも不安であり,また,SDカードI/F等,サードパーティ製のIPを用いている点が引っかかった.\ためしに無償評価ライセンスを取り寄せてみたりもしたが,期限が一月ということもあり,個人でまったりと遊ぶには心もとない.\無ければ作るの精神で,増築していく方針で進めた.


NiosIIコアの構成

ゲート規模から考えると,余力が十分にあるため,Nios II/fコアの採用とした./eについては,1命令の実行に複数サイクルを要することから,今回のようにCPU演算量が多くなりそうな用途の場合,不向きである.SOPC Builderで,Nios II Processorの編集ダイアログを見ておきましょう.


cpucore_01.png
乗除算器もH/Wで実装させます.cyclone IIIにはmultiplierが載っているので,コレを使わせます.使用するものが無ければ,LUTでテーブルを作ってくれるのでしょう….\リセットベクタ・割込みベクタはSRAMに割り付けておきます.\DDRSDRAMに比べてオーバーヘッドが少ないためです.(今となってはTCMのほうが良いかな)\MMUは未使用としておきます.テーブルルックアップ処理などで,メモリアクセスのオーバヘッドが増えるため,OSが要求してこない限りは使わなくて良いかと思います.


cpucore_02.png
\cacheを有効にします.サイズは適当.本来ならばアプリケーション作成後にチューニングしていくと良いかと思います.D-cacheのline sizeは,SDRAMのburst readサイズにあわせておくのが無難でしょう.


cpucore_03.png
\例外処理等.まぁ特に要らないかなぁ.まじめに製品化を考えるなら,fail safeやエラートラップ・障害発生時のログ機能を作りこんでおくと良いでしょう.


cpucore_04.png
\MMU/MPU設定.今回は MMUを無効化しているので設定はできません.


cpucore_05.png
\デバッグ機能の設定.あまりまじめにやる気が無かったのでlevel2で.1でも十分:)\現段階では,trace機能を使う必要がでるほどチューニングも行っていません.


cpucore_06.png
\カスタム命令の追加.YCbCr→RGB変換の演算をHWで処理してしまいます.ソフトのみでコーディングするのに比べてかなり高速化されます.\カスタム命令の(実装|使用法|概要)については,[NiosII][ACM] 高速化・ベンチマーク測定を参照してください.



記憶領域

コアのインストラクション・データは,それぞれがAvalon-MM Masterとなっています.PCからのダウンロードで,全てのメモリへのデータ供給後にCPU startとなるようです.\それ以外はconfig ROMから吸い上げorスタートアップルーチンがFLASHから吸い上げて転送してくれるのかどうか(未確認).

基本的にSRAMにマッピングしておるので,DDRSDRAM側へのアクセスは少ないはずです.ただし,heap領域およびVRAM(裏面含む)を配置してあるので,データ転送量は相当*2なものとなります.CPUコアによる展開処理での転送と,LCD表示のためのSGDMAによる読み出しの転送とが発生しますので,さらに負荷があがります.LCDは,800x480x60FPSなので,92,160,000 Bytes/Secとなります.

このLCD用のSG-DMAは,DDRSDRAMコントローラとは64bitバスで接続されているので,帯域としては66.5x8=532 Mbytes/sec を有するので,占有は2割ほどです.ただし,コントローラのオーバヘッドや,CPUからのアクセス・SGDMA自身のデスクリプタテーブル読み出しによるアクセスが衝突することで,転送レートに大きな影響を与えます.*3


LCDC

前述のとおり,VRAMとしてDDRSDRAMを用いております.CPUとシェアしており,裏RAMからの転送処理が不要な反面,アクセス衝突によるパフォーマンス劣化が生じえます.

LCDとは,MAX IIを介して接続されており,レベル変換・demax処理をさせています.FPGAからは,RGB各8bitのデータを時分割で送信する形態をとっています.

現状は,picture viewerに習って,altera-video-sync-generatorを用いています.これはAavlon-STを受け取って,LCDに必要な同期信号・フロントポーチ・バックポーチ信号(クロック)を生成します.データはAvalon-ST Packetのback pressure機能を用いて,データ本体の未送出時には取り出さないようにさせています.

SG-DMAと,video sync generatorとは動作クロックも異なり,データ幅も異なります.途中でDFAやFIFOを噛ませて所望の形に直していきます.

表示装置や,Dot Per Pixelに手を加えるには,このあたりのモジュールや接続部分を変更していくと便利かもしれません.



MMC SPI

長船さんが公開されているVHDLのIPをVerilogに移植してみました.無償版のModelSimでのHDL混在シミュレーションができないため,やむを得ず移植しました.本来なら流用してウマーという流れなのでしょうが,無念ですw


その他

ALTERAの基本IPをぺたぺたと貼り付けただけなので,説明は不要でしょう.適宜邦訳版コンテンツやメモ,ALTERAから出ている資料に目を通してください;)



*2 : 240 x 160 x 24bpp x 24fps で 3,686,400Bytes/Sec.

*3 : SOPC Builderの接続図で細サイクル数を指定しているのも,裏RAMアクセス時にLCD表示が乱れたので手を入れてあるのです….

ドライバレベルソフト

ALTERA IPについては,基本的にドライバ(Hardware Adaption Layer)が用意されています.newlibの標準入出力関数に適応したドライバも用意されており,シリアル入出力ポートを用意しておけばデバッグ時に便利でしょう.\無論,JTAG debug機能が有効であれば Eclipse上(NiosII IDE上)からGDB経由でらくらくデバッグが可能でしょうが.


LCDC

NEEKサンプルのソフトを流用します.

C:\altera\72\kits\cycloneIII_3c25_niosII_eval\examples\picture_viewer\software_examples\app\picture_viewer\alt_video_display

SGDMAドライバも内部で使用しています.個人的にVsyncカウントもほしかったので,このソフトにも手を入れています.

SGDMAをPackモードで使用せず,デスクリプタチェインの終了を要因とした割り込みを用いてソフトで再キックしています.プロジェクトが落ち着いてから公開しましょう.恥ずかしいコメントだらけなので(ぇ-


MMC

当該IP制御に関するコードは長船さんのコードをパク…参考に,もってきました.FAT File Systemについては,おなじみのFatFsを使わせていただきます*4

個人でいじっている分には自己責任でアレですが,製品や人に配布するものとして適用してしまうとゲイツ陣営と争う必要が出てくるかもしれません.

また,SDカードの使用については,MMCへのアクセスを行っているだけである,という主張でSDカード非対応を宣言すればライセンシ不要という見方もあるようですが,軽くWEBサイトを見てまわった感じだと,わかりかねます.

データライン4本で転送してみたいものですがね….SPI 25MHz*5だとちょっときつい.



DAI

今回のACM v0.1対応版お試し公開では未使用.MMC I/Fのテストとして,waveファイルオープン・DAI経由でDACへデータを流して再生までは確認済.DAIモジュールにもFIFOを用意してあり,FIFO残量が減ってきたときに割り込みをかけて,FIFOへのデータ転送を行う.将来的にはAvalon-ST sinkポートを設けて,DMA経由で流し込めればCPUの処理を削減することができよう.

現状,ソフトでメモリ上にFIFOを構築して,割込みハンドラでデータを吐き出させている.メイン処理ではメモリ上のFIFO残量をポーリングして,ファイルからデータを吸い出している.


ACM decoder

ALTERAで行こう!暫定公開 → 軽量動画フォーマットの研究を参照ください.\更新されて名前が変わったりしているかもしれませんが,適宜対応ください(^^;




*4 : ChaN氏のFatFs Rev.0.06を取り込み,MMCを論理番号0と成るようにするなどの修正をしています.

*5 : MMCは20MHzまでの仕様だから,それ以上の使用はNGか!? デバイス内のレジスタに上限値が入っているから問題なし?

アプリケーションレベルソフト

Test Programとしてのみ実装.RTOSは未使用であり,単純にSDからデータを吸い出してデコード・表示しているだけです.

frame rateにあわせて時間間隔を所望の時間に近い値でウェイトを入れている.frame rateに対応する待ち時間はシステムクロックの整数倍にはならないので,誤差を吸収する措置を入れてある.(誤差を積算してウェイト値に加算するだけですが)





[コラム] SDカード

つい本日(2009年2月10日)のことです.

トラ技2009年3月号 BASICS [連載] Cによるマイコン操作術〈第12回〉SPIを利用してSDメモリーカードにアクセスしてみよう

ちょうど,この記事を目にできた.立ち読み程度で申し訳ないが,FATFSのライセンス・SDカード使用のライセンスについて,伝聞調で記されていた.参照資料も特別明記無く,商用利用時は調査すべきだ,程度で終わっている.

軽くググってみたものの,SDライセンス・FATライセンスに関する詳細がみあたらない.MSのパテントとして2007年末に米国で認められているようだが,パテント期限が17年(スラドJP過去ログ)とかなんとか….FAT12/FAT16/FAT32/VFATそれぞれで期限が異なるのかしら?

相変わらず疑問だけが残るけれども,ここでも解決せずに筆をおくことになる…(ゴメンナサイ)

  • 切れるとしていつごろ切れるのか.
  • 切れないとして無断使用はNGということで認識は正しいか.
  • linuxのfile systemとしてサポートが残っているが,ライセンス問題はどうなっているのか.

容易に組込み機器とPCとの間でデータをシェアしようと考えると,SD+FATFSが現状の最適解だと思う.active syncプロトコル自体もライセンスが要るようだし

最悪,セガサターンのRAMカセット並みのフォーマットで作ってもいいわけだが….MSDOSのメモリチェーン並みのしょぼさだけど(笑)