« 2007年10月 | トップページ | 2007年12月 »

2007.11.25

SHの4バイト境界で例外発生の落とし穴

SHマイコン(SH7144F)のプログラムを組んでいて、はまったことがあります。

配列があって、その20番目~23の要素にunsigned long 型の値を格納したいとします。
そこで、こんなふうにプログラムを書きました。

void hogehoge(unsigned long val)
{
unsigned char tmp[32];
・・・
・・・
*(unsigned long *)&tmp[20] = val;
・・・
}

なんでもない普通のCの記述です。ポインタのキャストがちょっと気になりますが。

ところが、これを実行すると例外が発生して吹っ飛ぶことがあるようです。
この構文をアセンブラにすると、こんな感じになります。

mov r14,r1 ← ここでr1にtmpの先頭アドレスが入る
add #20,r1 ← ここでtmp[20]のアドレスが計算される
mov.b r8,@r1 ← アドレスエラー発生

SHは、4バイトの(ロングワード)データをメモリとやりとりする場合、
ロングワード境界をまだいでしまうと、アドレスエラーという例外が発生してしまいます。
つまり、例えば0x0e番地から4バイトのデータを書き込む場合には、
2回のワードアクセスにわけてやらなければなりません。

普通はlong型やint型の配列を作れば、コンパイラは自動的に各要素がロングワード境界に並ぶようにしてくれるとは思うのですが、今回のケースではchar型の自動変数で配列を作ったため、ロングワード境界をまたぐことになってしまい、このようなエラーになったのでしょう。
コンパイルするたびにアドレスが微妙に変わるから、原因を発見しにくかったです。

SH系のプログラムを組むときにはアドレスエラー例外を必ず捕捉して、ブザーを鳴らすとか赤ランプ点滅とか、とか警告を出さないと、いけませんね。アドレスエラー例外を無視して何もルーチンをつくらないでおくと、ブレークポイントも仕掛けられないですし。
GCCを使っていたら何気ないプログラムでこんな例外にはまってしまいました。
ちなみに、今回使ったコンパイラは、gcc3.3です。
ご参考までに。

| | コメント (1)

2007.11.20

アドバンスドJTAGファンクションジェネレータの紹介ページ

FPGAを論理合成せずに、C言語で書いたとおりに動かす新製品、「アドバンスドJTAGファンクションジェネレータ」の製品紹介ページを作りました。
http://www.tokudenkairo.co.jp/ajfg.html

Ajfgpage

どうぞよろしくお願いします。

| | コメント (0)

2007.11.14

ステートマシンがOneHotになるのを防止する

XILINXのFPGAで、ステートマシンが思い通りに動かないときがあります。

XILINXのXSTは、ステートマシンをOne Hotで作ろうとします。
たとえユーザが最適化したステート割り当てを考えて、
VHDLやVerilogで、エンコード方法まで丁寧に記述しても、勝手にOneHot化してくれます。

つまり、
case hoge_state is
when "000" =>
・・・ hoge_state <="001";
when "001"=>
・・
when others=>
・・・ hoge_state <="000";
・・

このように記述しても、hoge_state(0)やhoge_state(1)という信号がそのデザインで直接参照されないようであれば、XSTは気を利かせてステートマシンがOneHot化し、信号を消してしまうのです。

そのときXSTは、こんなメッセージを出します。
INFO:Xst:2117 - HDL ADVISOR - Mux Selector of Case statement line 479 was re-encoded using one-hot encoding. The case statement will be optimized (default statement optimization), but this optimization may lead to design initialization problems. To ensure the design works safely, you can:
- add an 'INIT' attribute on signal - use the attribute 'signal_encoding user' to avoid onehot optimization
- use the attribute 'safe_implementation yes' to force XST to perform a safe (but less efficient)

リセット時に全部のFFがゼロになったり、ノイズやその他の原因で未定義のステートに入ったときが怖いです。
これでもちゃんと動いてくれればよいのですが、動いてくれないことが多いです。
確かにワンホットは高速なのですが、困ります。

例えば、hoge_state(2 downto 0)を3ビットの信号とすると、
XSTは最大8個のワンホット用のフリップフロップを作ります。
したがって、最大256個のステートが存在してしまうわけですが、
どうやらXSTがワンホット化したステートマシンでは、
変なステートに入ってしまうと、when othersで定義した式さえ実行されないことがあるようなのです。

もちろん、ステートマシンにリセットの記述を入れればいいのですが、
ステートマシンを適切にリセットしていない場合、
正しいステートから開始せず、そのステートマシンの
ステートや出力信号は信頼できないものになります。

これを防止するには、
testpoint <= hoge_state(0)のように、
ステートマシンの信号のうちの1本を抜き出すようにして、論理合成で消えないようにするという手や、
Translateのオプションでステートマシンのエンコード方法を指定する方法があります。

ただ、信号の1本を抜き出す方法は面倒だし、
Translateのオプションで指定する方法ではデザイン全体に効いてしまいます。

上記のINFO:Xst:2117のメッセージによると、
初期値に問題があるから'signal_encoding user' を設定しろ、と読めます。

そこで、次のようにしてみました。

architecture Behavioral of main is
・・・
signal hoge_state : std_logic_vector(2 downto 0);
attribute SIGNAL_ENCODING : string;
attribute SIGNAL_ENCODING of hoge_state : signal is "user";
・・・
begin

ワンホット化させたくないステートマシン、つまり、自分でエンコードの方法を指定したステートマシンについては、SIGNAL_ENCODINGをUSERに設定することによって、自分で指定したエンコードで合成してくれるようになりました。

論理合成中のメッセージは、次のようになりました。
Set property "SIGNAL_ENCODING = user" for signal .

これで、リセットを入れなくても変なステートに入ることはなくなりました。
XSTは、ユーザが定義したとおりにステートマシンを作ってくれるようになりました。

ステートマシンが思うように動かない場合、SIGNAL_ENCODINGを試してみてはいかがでしょうか。

| | コメント (0)

2007.11.12

携帯でスミスチャート

少しづつ、少しづつ、C#の勉強をしながら進めています。

解析する、開始周波数と終了周波数を入力できるようにしました。
Conf

周波数は等比的または等差的にスウィープできます。

LC並列共振回路の周波数特性を計算してみました。
Cは100pFの純コンデンサですが、Lは10nFのリアクタンスのほかに純抵抗が入れられるようにしました。純抵抗の大きさはいろいろと変えられます。

こんな感じです。
Chart

周波数が低いほうから高いほうへスイープさせると、コイルに寄生した純抵抗の場所からはじまりってゼロに向いますが、抵抗が小さいといったん誘導性になってから実数軸を横切り、再び容量性になってゼロに向います。
面白い。

今日は行き帰りの電車の中でいろいろシミュレーションを楽しんでみることにします。

| | コメント (0)

2007.11.07

C#の勉強をはじめました

今日は、某秘密集会があるので、手土産をつくるため早起きしました。

はじめて使うC#とVisualStudio.NET 2005に戸惑いながら、朝10時ごろにはこのようなものが出来上がりました。
Pocketsmith
まだスミスチャートが描画できて、画面をタッチしたときに始点と終点のインピーダンスが表示されるというだけの単純なものですが、携帯で動くというのが面白いところです。

今はただ押したところのインピーダンスが出るだけですが、これから計算機能や、解析機能なども作っていきたいところです。

電車の中で携帯ゲームをやっているとおもったら、実は回路解析をやっていたなんていう時代もそう遠くはないでしょう。

| | コメント (0)

2007.11.06

USB2.0 HighSpeedモードの実効速度と高速化のための工夫

1年くらい前、当ブログに「USB2.0の転送速度に関する一考察」というのを書きました。その後、いろいろな考察を行い、USB2.0 HighSpeedの最高速度はどれくらいかということと、USB2.0をちょっとだけ高速化するためのアイデアを得ました。
その後ある会誌に寄稿したのですが、本情報は一般にも公開したほうが良いと思いましたので、今日はそれを少し手直ししてブログに載せます。

------------------------------------------------------------
●はじめに
USB2.0 HighSpeedモード(以下、USB2HSと略す)は非常に高速で手軽なインタフェースです。このインタフェースの速度は480Mbpsと謳われていますが、真の性能は、いったいどのくらいなのでしょうか?
おそらく街で販売されているUSB機器には「理論値480Mbps」などとあいまいな記載しかなく、実効速度についてはっきりとは書いていないでしょう。
本稿では、そんなUSB2.0の速度について考察してみることにします。

●USBの実効速度の測定
図1の構成の装置を作り、通信速度を測定してみました。


Usbmax1

図1 USB速度測定のための実験環境

図2はIN方向(ターゲット→パソコン)のデータ転送を行う際の波形です。オシロのCH2はFPGAからUSBへデータを送る際のストローブ信号を、CH3はUSBのD-信号を見ています。D-信号は高速ディジタル信号なので正確に見えてはいませんが、通信が行われたタイミングを知ることはできます。


Usbmax2a

図2(a) データ転送時の波形


Usbmax2b

図2(b) データ転送時の波形

今回使用したUSB ICは内部のデータバッファがダブルバッファの構造になっています。USB ICからパソコンにデータが送信されて送信バッファに空きができると、FPGAから次のデータが送られます。大きなデータを連続して送るときには、IC内のバッファにはあらかじめ常に十分な量のデータを溜めておき、USBバスにデータが送信された後、IC内のバッファにFPGAからデータが補充するようにします。
 図2(b)の波形を見ると、125μ秒ごとに似たような形が繰り返されているのがわかります。USB2.0ではマイクロフレームといって125μ秒ごとにタイムスロットが区切られています。今回構築した実験装置では、この125μ秒の間に11回のデータ転送が行われたと推測されます。

USBはデータをパケット単位で送受信しますが、1回のデータサイズは最大512バイトです。今回の実験環境では512バイトのデータパケットを125μ秒の間に11回転送できたため、速度は毎秒45Mバイト出たことになります。実際にはOSやデバイスドライバのオーバーヘッドが入るため、実効転送速度はこれより下がることになりますが、数Mバイトの大きなデータを一括で送れば近い値が出ます。
USBのデータパケットの前後には、トークンやハンドシェイクという制御用のパケットが送受信されます。トークンとデータとハンドシェイクを合わせてトランザクションとよびます。
結局のところ、USBの実効速度は、1マイクロフレームにどれだけの数のトランザクションを発行できるかということで決まります。もし、1マイクロフレームが9トランザクションならば、実効レートは512×8×9/125μ秒= 294Mbps。10なら327Mbps。11なら360Mbpsになります。


Usbmax3

図3 トランザクション数と実効速度の関係

では、なぜ今回の実験ではトランザクションが11回なのでしょうか。
図2(a)によると、1回のトランザクションには10μ秒強の時間がかかっていることがわかります。
データサイズは512バイトなので、データだけならば8.53μ秒で送れるはずですが、実際にはトークンパケットや、ハンドシェイクパケット、パケット間の待ち時間(ギャップ)などがあるため多少余分に時間がかかってしまいます。また、今回の実験ではIN方向で転送しているので、トークンとハンドシェイクはパソコン側が送信し、データはUSB IC側が送信しています。送受信が交代するためどうしても空き時間が生じてしまいます。


Usbmax4

図4 USBパケット間の詳細

こういった理由によってパケットごとに1.3μ秒ほどの追加の時間が生じてしまいます。そのため実際には1トランザクションあたり10μ秒強の時間がかかることになります。待ち時間はパソコンのCPUの処理速度にも影響されるので、速いパソコンのほうが当然速くなります。

さらに、マイクロフレームの先頭を示すSOFパケットから、最初のトランザクションが開始するまでの無駄なアイドル時間も無視できません。この時間は実測で約5~7μ秒ありました。


●送信するデータの種類によって速度が低下することがある
この実験装置にVGAのカメラをつないでUSBカメラを構成してみたところ、明るいシーンを撮影した時に転送レートが低下するという現象が発生しました。


Usbmaxp1
写真1 USBカメラで撮影した通常のシーン


Usbmaxp2
写真2 USBカメラで撮影した極度に明るいシーン

このUSBカメラは、通常のシーンの撮影時には約320Mbpsの速度でデータを転送できるのですが、極度に明るいシーンでは292Mbpsと、約10%も低下してしまいました。オシロで観察したところ、明るいシーンを撮影した際には、1マイクロフレーム間のトランザクション数が10個に減少していることがわかりました。減少した理由は、USBがNRZI符号を採用しているためだと考えられます。


Usbmax5

図5 1マイクロフレーム間に10回のトランザクションしか行えていない

NRZI符号とは、図6のように、データ’0’を送りたいときには現在の信号線の状態を反転し、'1'を送りたいときには信号線の状態を反転しないという符号化方式です。


Usbmax6_2

図6 NRZI符号のエンコードと、ビット挿入

NRZI符号では、‘1’が続くと信号が反転しない状態が続いてよくないため、6回続いたら強制的に‘0’が挿入されるようになっています。すると、本来のデータは後ろに1ビットシフトされので、フレーム長が1ビット伸びることになります。‘1’が連続で続くことが多いデータを送信した場合には、フレームが伸びてしまい、その結果トランザクションあたりの通信時間は長くなります。
明るく飽和した画像を送信した場合、NRZIの符号化によってデータ長が伸び、ひとつのマイクロフレームに詰め込むことができるトランザクションの数が減ってしまいます。このようにわずかな時間ロスの増加によって、送信できるトランザクション数の減少し、実効速度が低下するので注意が必要です。

●常に最大速度で通信するための工夫
‘1’が連続するデータを送ると遅くなるので、‘1’が連続しないようにデータにあらかじめスクランブルしてから送り、受信したパソコンでデスクランブルをかけて複合すればよいだろうと、思いつくでしょう。
スクランブルはFPGAで行いますが、デスクランブルはパソコンのCPUで行うので、できるだけ単純な仕組みが良いでしょう。ここでは明るいシーンを撮って飽和してしまった画素(0xFF)を送るのを回避したいので、図7のように送信するデータに0x55でXORしたものを送信するようにしてみました。


Usbmax7_2

図7 通信路上でスクランブルをかけると、速度の低下を防ぐことができる


結果は非常に効果があったといえます。FFに飽和した画像を送信しても遅くなることはなくなりました。逆に、通常の画像を送信した場合にかえって通信が遅くなるということもありませんでした。

改良前はVGA画像1枚(320kバイト)あたり7.7ミリ秒、飽和した画像では8.4ミリ秒と送信時間にばらつきが生じていましたが、この工夫を行うことで、画像の内容に関係なく1枚あたり平均7.7ミリ秒でデータを送信することができるようになりました。
なお、画像1枚あたりのデスクランブルはCPUで処理しているため、0.2ミリ秒を追加で要するようになってしまいましたが、トータルではメリットが生じたといえるでしょう。

●まとめ
表1と、式1~2に、USB2.0の最大実効速度の計算方法を示します。
Usbmax8_2

USB2.0 HighSpeedモードは、マイクロフレームの間隔にトランザクションを詰め込む仕組みになっているため、実効通信速度はホストやターゲットの処理速度によっても変化します。

最近のパソコン(デュアルコアクラス)ではN=10~11となるでしょう。NRZIの符号化によって送信するデータの中身によってはNが1程度減少することがありますが、スクランブルをかけることで回避できるのを確認しました。

理論上のNの最高値は13で、最大実効速度は425.984Mbps(53MBytes/s)です。
この速度は'1'を連続で送信すると達成できないでしょう。
N=13の最高速を目指すには、まず適度なスクランブルをかけてNRZIのビット挿入が起こらないようにしなければなりません。
また、USBターゲット側とホスト側のソフトウェアの処理を十分高速にして、ハンドシェイクや次のトークンを極力早く出し、パケット間のギャップを詰めれば、ぎりぎり達成できる可能性はあります。

スクランブルをかけた方が高速になるか否か、またどのようなスクランブル方式が適切かということは送信するデータの種類によって変わります。そのデータの特徴があらかじめわかっていれば、スクランブルの方式を動的に変更するというのも面白いでしょう。

このレポートが皆様のお役に立てば幸いです。

| | コメント (0)

2007.11.01

ISO9001は取得されていますか?

ある会社から弊社の製品の問い合わせをいただき、その際にISO9001の取得の有無をたずねられました。
「取得していない」と答えると、それならアンケートに答えてくれということで、
品質に関するアンケートとかいうA4の紙が送られてきました。


まず、会社概要、従業員数、年商などなどを書くところがあって、
「あなたの会社では***を***していますか 評点 1~5」
「あなたの会社では***を***していますか 評点 1~5」
「あなたの会社では***を***していますか 評点 1~5」
「あなたの会社では***を***していますか 評点 1~5」
「これらを全従業員に周知徹底して理解して実行していますか? 評点 1~5」
「ISO9000または14000を取得する予定はありますか?」
みたいな質問事項が列挙していました。

新規取引先はみなこのアンケートを書くのだとおっしゃっていますが、
なんでこんなことを書かなきゃならないの?って感じです。
いままで何百社かとお取引させてきましたが、こんなのは始めてです。

その会社の購買部は、おそらく、原則としてISO9000を取得している企業・団体からしか調達できないように、マニュアルか何かで縛ってしまったのでしょう。
ISOを取得していない会社に対しては、社内でISOのような品質管理をやっているかどうかを調べようとしているのでしょう。

仕方がないので、こう書いてFAXを送り返しました。
「恐れ入りますが、アンケートの全項目について回答を控えさせていただきます。」
もう、こことは取引できなくてもいいや、という気分です。

すぐに担当者から電話がきました。
「アンケートは結構ですから、空白のままその紙を送り返してください。そうしないと社内の手続きが始まらないもので・・」
「うちは、従業員数と年商、事業年度も公開していませんが。お出しできるのは住所と電話番号くらいですよ。」
「では、非公開でいいです」

なーんだ。結局何も情報を出さなくよかったのですね。

ISO9000に何を書くかはそれぞれの会社の自由ですが、取引相手に何かの負担を求めたり、不快にするような規定は作ってはいけません。社内を縛るだけにするべきです。
ISO9000は使い方を間違えると、相手先に迷惑をかけて売上も減少するという、とても危険なものになるのだと思います。

| | コメント (4)

« 2007年10月 | トップページ | 2007年12月 »