金曜日, 12月 07, 2007

FPGA PARK

えふ・ぴー・じー・えー・ぱーく

FPGAを使ったかなり積極的な実験や自作のIPを公開されています。
ざっと見ただけですが、詳細なレポートがあるのでいろいろと勉強になりそうです。

履歴を見ると以前から公開されていたようですが、ぜんぜん知りませんでした。

IPの中には"MR16"という自作の16bit RISC CPUもあります。

残念ながらCコンパイラは現在のところ無いようで、アセンブラでの開発になりますが
iverilogでもシミュレーションができるようなので、CPUの動作を見てみたいなどという場合にはLattice Mico32などよりはこちらのほうが良いかもしれません。
(iverilogでLattice Mico32のシミュレーションをやってみようとしたのですが、どうもそのままではうまくいかないようでした。どこかいじる必要があります。)

また、このMR16はインタフェース誌の記事にも載っていたようなので、日本語の情報源も他のフリーのソフトコアCPUよりは多いかもしれません。

火曜日, 12月 04, 2007

IP-XACT

ちょっととりとめもなく書きますが
最近、IP-XACTというものが気になってます。

ActelのツールにCoreConsoleというGUIでSoCを構成するツールがあってそれを使っているときにはじめて知ったのですが、IPの仕様をXMLで記述したようなものだと思います。

私もまだ詳細を理解していないので↓こちらなどをご参考に。
IP-XACTを使った効果的な設計フロー統合

CoreConsoleを使って思ったのですが、部品をポン、ポン、ポンと置くだけで細かいところはツールが自動的にやってくれて、SoCを構成できるので非常に便利です。

現在のCoreConsoleはユーザーが作成したIPを追加することはできませんが、将来的には適切なIP-XACTの記述があれば、ユーザーが作成したIPも同様に簡単に接続できるようになるとのこと。

これからのSoC設計はこういった流れになっていくのかなと感じました。

各ベンダーが同様のツールを出していますが、SoCの構成を自動化するためには、IPに加えてそのインタフェースがどのようなものであるかなどの情報を付加する必要があり、そのためにユーザが手作業で情報を追加したり、またはベンダーごとに独自の仕様であったりといったのが現状だと思います。

この追加が必要な情報がIP-XACTのように標準化されれば、IPの再利用化も進み、IPプロバイダの裾野が広がると思うんですけどね。

日曜日, 11月 25, 2007

Nios II をASICで

アルテラとシノプシス、Nios IIプロセッサ・コアのASICへの適用拡大に向けて協力

ソフトコア・プロセッサの話題が続きますが。

実際のところ、これを待っていたメーカーは結構いるのではないでしょうか。

これで家電向けのSoCも、FPGAでプロト、初期ロット→ASICでコストダウンといった流れが加速して行きそうです。

さて、Xilinxはどうするのか?

ところで、私はAlteraのデバイス自体は使ったことあるのですが、Niosは使ったことがありません。
オンチップバスは"Avalon"という独自のものになっているようですが使い勝手はどうなんでしょうね?

まあこの業界、シェアを取った者勝ちといった気もしますが。。。

木曜日, 11月 15, 2007

MicroBlazeにMMUが搭載される!

Xilinx社が32ビット・コアを改良、MMU搭載で仮想メモリーをサポートへ

MicroBlazeがメジャーバージョーンアップされたようです。

内部バスも最大128ビットまで拡張可能。

MMUを搭載してもSpartan-3E 1600の10%程度しかリソースを使わないらしい。
だとしたら結構なものだ。

ちなみに最大動作周波数はどのくらいなんだろうか?

評価してみたいけどなぁ。
時間があれば。。。

といいつつ、いろいろ先延ばしにしてしまう悪い癖。

月曜日, 11月 12, 2007

Icarus Verilog & GTKWave for Windows

このブログで使っているシミュレータは基本的にModelSimXE Staterなのですが、以前の記事でも書いたように、商用シミュレータの無償版はコードサイズに制限がある場合が多いと思います。

まあそれでも、自分でコーディングをする範囲であれば、勉強目的では十分ですし実際に仕事でもそこそこ使えるはずです。

しかし最近はオープンなIPコアなどもさまざまなものが入手可能になり
先のLatticeMico32のような大規模なコアでは
それだけでコードサイズの制限を越えるようなものもあります。

そのような場合に使えるフリーなシミュレータがIcarus Verilogです。
ModelSimのようなGUIのインタフェースはありませんが、コードサイズによる制限などはもちろんありません。
最近はドキュメントも(英語ですが)充実しつつあるように思います。
実際、業務で使用されているところもあるようです。

Windows環境では、cygwinなどでコンパイルも可能なようですが
コンパイル済みのものが↓こちらで配布されているのでそれを使ったほうが手っ取り早いと思います。

Icarus Verilog for Windows

波形はVCDなどをダンプして、GTKWaveでみることができます。
こちらもWindows版が配布されています。

http://www.dspia.com/gtkwave.html

DDLも一緒にダウンロードして、解凍したディレクトリのgtkw\binにgtkwave.exeをおけば使えるようになります。
パスを通すのを忘れずに。

こちらは、アプリケーションの起動はコマンドラインからになりますが
操作はModelSimのWaveウィンドウのようにGUIで扱えます。
以前のWindows版は使いづらかった記憶があるのですが
現在のものは使い勝手がだいぶ向上しているようです。


上記の2つはソースコードも配布されているので
ガンバレばMacで開発も可能!?

火曜日, 10月 30, 2007

LatticeMico32 シリアル通信の確認

前回、やり残していたシリアル通信の確認。


とその前に、以前はSpartan-3E Starter Kitのメス型の方のシリアルポートにアサインしていましたが、それをオス型の方に変更しました。

[ucfファイル]

# Period constraint for 50MHz operation
#
NET "clk" PERIOD = 20.0ns HIGH 50%;
#
# soldered 50MHz Clock.
#
NET "clk" LOC = "C9" | IOSTANDARD = LVTTL;
#
#
# Simple LEDs
# Require only 3.5mA.
#
NET "led<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
#
# Press buttons
# Must have pull DOWN resistors to provide Low when not pressed.
#
NET "btn_south" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN;
#
# UART connections
#
#NET "tx_female" LOC = "M14" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
#NET "rx_female" LOC = "R7" | IOSTANDARD = LVTTL;
NET "RS232_DTE_RXD" LOC = "U8" | IOSTANDARD = LVTTL ;
NET "RS232_DTE_TXD" LOC = "M13" | IOSTANDARD = LVTTL | DRIVE = 8 | SLEW = SLOW ;
# End of File
#


[ラッパー]

`define LEDOUT_BITS 2

module wrap_s3e_kit (/*AUTOARG*/
// Outputs
led, RS232_DTE_TXD,
// Inputs
clk, btn_south, RS232_DTE_RXD
);

input clk;
input btn_south;
output [`LEDOUT_BITS-1:0] led;
output RS232_DTE_TXD;
input RS232_DTE_RXD;


system_top system_top_i (
.clk_i(clk),
.rst_i_n(~btn_south),
.led_out(led),
.tx_out(RS232_DTE_TXD),
.rx_in(RS232_DTE_RXD)
);

endmodule


結果は以下のとおり。

↓ハイパーターミナルを起動して、LatticeMico32をリセット。


リセット直後にLatticeMico32から送信されるメッセージが表示されます。

↓その後、適当にキーボードから文字を打つと、


そのまま返ってきた文字が表示されます。

ハイパーターミナル側のボーレートは115200bpsに設定しています。

以上で無事、シリアル通信の動作も確認ができましたので
今後はこれを使って遊んでみようかなと思います。

金曜日, 10月 26, 2007

LatticeMico32 Spartan-3E スターターキットに実装(補足)

前回の補足

Spartan-3E スターターキット用のUCFは自作なので一応載せておきます。

[ucfファイル]

# Period constraint for 50MHz operation
#
NET "clk" PERIOD = 20.0ns HIGH 50%;
#
# soldered 50MHz Clock.
#
NET "clk" LOC = "C9" | IOSTANDARD = LVTTL;
#
#
# Simple LEDs
# Require only 3.5mA.
#
NET "led<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "led<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
#
# Press buttons
# Must have pull DOWN resistors to provide Low when not pressed.
#
NET "btn_south" LOC = "K17" | IOSTANDARD = LVTTL | PULLDOWN;
#
# UART connections
#
NET "tx_female" LOC = "M14" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 4;
NET "rx_female" LOC = "R7" | IOSTANDARD = LVTTL;
# End of File
#


あとは、DesignWaveに付いていたトップモジュールに次のラップをかぶせてチンしてください。

`define LEDOUT_BITS 2

module wrap_s3e_kit (/*AUTOARG*/
// Outputs
led, tx_female,
// Inputs
clk, btn_south, rx_female
);

input clk;
input btn_south;
output [`LEDOUT_BITS-1:0] led;
output tx_female;
input rx_female;


system_top system_top_i (
.clk_i(clk),
.rst_i_n(~btn_south),
.led_out(led),
.tx_out(tx_female),
.rx_in(rx_female)
);

endmodule


載せるほどのものでもないですが。。。
これでSpartan-3E スターターキットに実装できると思います。

リセットはプッシュボタンスイッチのBTN_SOUTHで
シリアルはメス型の DB9 DCE コネクタにアサインされています。

ちなみにシリアルのほうはまだ動作確認していないので
ご使用は自己責任でお願いします。

木曜日, 10月 25, 2007

LatticeMico32のページ

そういえば、LatticeMico32のページにリンクを貼っていなかったので一応リンクしときます。

ラティスMico32 オープン、無償の32ビット・ソフト・プロセッサ


基本的に英語ですが色々情報が手に入ると思います。

ちなみにLatticeMico32の主な特徴は

・RISCアーキテクチャ
・32ビットデータバス
・32ビット命令
・32汎用レジスタ
・最大32の外部割込み
・命令キャッシュ(オプション)
・データキャッシュ(オプション)
・デュアルWISHBONE メモリーインタフェース(命令とデータ)

などなど

デュアルウィッシュボーンってなんかクルマのサスっぽいな。

オープンソースなのでシミュレーションでCPU内部の動作を確認することもできますし
ソフトウェアの開発環境(GNU-Tools)もソースコードが公開されているので
(私には無理ですが)そのへんをいろいろいじったりもできるんじゃないでしょうか?

水曜日, 10月 24, 2007

LatticeMico32 Spartan-3E スターターキットに実装

前回の続き

とりあえず途中経過程度で。
ここのところ本業が忙しい時期に入ってきたのでなかなか進めれていません。

Spartan-3E スターターキット
に実装してみました。

↓LEDが点滅しているところ。


ちゃんと動いてますね。
ちなみにクロックの動作周波数は50MHzです。

あと、シリアルも繋げなきゃいけなかったのですが
適当なPCにシリアルポートが付いているものがなく。。。

最近はデスクトップでもレガシーI/Oついてないんですよね。

ということでこれは次回に持ち越し。

ここのところのLatticeMico32の話題に関しては、
DesignWaveの記事をほぼなぞっているだけということもあってあまり詳細は書いていません。

もし、同じようなことをやっていてうまく行かないという方がいれば
コメントに質問を入れてください。

ソースもほぼそのまま使っているのでここに載せるわけにもいけないため
ある程度落ち着いたら、自分で適当なトップモジュールを組んでアップしようと思います。

その前にソフトの開発環境のこと勉強しておかないとナ。

月曜日, 10月 15, 2007

LatticeMico32 シミュレーション

前回の続き

で、今回はシミュレーションまでやってみる。

ちなみにこの内容はDesignWaveMagazineの2007年10月号の記事を参考にしています。

RTL,テストベンチのコードはそのCD-ROMに収録されているものを使用していますのでお持ちでない方はあしからず。

まずシステムの構成ですが、プロセッサのコアと命令用およびデータ用のSRAM関連のほかにUARTインタフェースモジュールとLED制御用のレジスタがあります。

記事によると、まずスタートアップ後にUARTからmessage("This is a message from Mico32 processor.\n")が出力されます。
その後、UARTに関しては受信したキャラクタをそのまま送り返すようになっています。

また、LEDは約0.5秒ごとに2つのLEDが点灯・消灯を繰り返すとのこと。

ModelSimで約1秒間のシミュレーションを行った結果の波形は次のようになりました。



確かに2つのLED(ledの下位2ビット)が約0.5秒間隔で点灯と消灯を繰り返している模様。

次に先頭の部分を拡大。



詳細は確認していませんが、UARTがなにやら送信していることがわかります。

次にその少し後を拡大。



受信したコードをそのまま送信していることが確認できます。

というわけで、シミュレーションでなんとなく動作していることもわかりました。

ちなみに今回、ModelSim XE Starter とModelSim PE とで実行時間の比較を行いました。

結果は1,009,312,600nsのシミュレーションに対して、実行時間が

XE Starter・・・2921.70seconds
PE ・・・1024.16seconds


PCのスペックは
OS : Microsoft Windows XP SP2
CPU: Intel(R) Core(TM)2 CPU 6400 @ 2.13GHz
RAM: 2.75GByte

です。

Xilinxのサイトによると、10000行以下のデザインであればXE staterの実行速度はPEの30%とのことなので大体そのとおりになっているようです。

ただ、10000行を超えるとXE starterの性能はガタ落ちのようなので実際にプロセッサを組み込んでシミュレーションを行う場合はもっと上のグレードか他のシミュレータを選んだほうがよさそうです。

今回のデザインでコメントを除いた行数は大体8,500行ぐらいでした。

ただ1点気になるのは、DWMの記事ではボーレートを50MHzのクロック入力で115,200bpsに設定してあると書いてあるのですが(そしてソースコード上のパラメータもそうなっている)、テストベンチのクロックの周期は4000としてあります。
タイムスケールが設定されていないのでよくわかりませんがpsだとすると25MHz。
これは単純なミス?

たぶん実際は50MHz入れてやればよいのでしょう。

今日はここまで。

次回は実際にFPGAに実装して動作確認をしてみようと思います。

木曜日, 10月 11, 2007

LatticeMico32 Xilinx ISEで合成&インプリ

前回の続き

結果から先にいうと、
ISEで一応、合成とインプリまでできました。

デバイスはXC3S250E-4VQ100でオプションは特に変更せずに
スライスの利用率が51%、最大動作周波数が62.290MHzという結果が出ました。

DesignWaveの記事では、
スライスの利用率が54%、最大動作周波数が71.4MHzとのことなので大体そんなところかな。

問題になっていたエラーは、前回修正した2箇所目の部分を次のようにすれば出なくなりました。


[修正後]
parameter integer INTEGER_DIVISOR = i_divisor(BAUD_RATE, CLK_IN_MHZ);



あと、Designwaveの記事ではISEでコンパイルする場合

・generate文中でif文を使う場合はラベルが必要
・localparam宣言で関数が使えない

とありましたが、今回うちの環境(ISE9.2.03i)ではこの2つは特に変更することなくコンパイルできました。
まだ動作を確認したわけではないのでなんともいえませんが。

まあ何はともあれ、XilinxのFPGAに実装できそうだということがわかったので
次はシミュレーションでもやってみようかと思います。

水曜日, 10月 10, 2007

うまくいかない

DesignWaveの2007年10月号の記事を参考に
XilinxのISEで「LatticeMico32」を合成しようとしているのですがうまくいかない。

ISEのバージョンは9.2.03i。

まず引っかかったのがuart_core内のintfaceモジュール。

ここで"CLK_IN_MHZ"が定義されていないとエラーが出たがこれは次のように2箇所を修正すると回避できた。

intface.v

[修正前]
function integer i_divisor;
input integer baudrate;
begin
i_divisor = ((1048576.0 * (baudrate/100.0)) / (CLK_IN_MHZ*10000.0)) + 0.5;
end
endfunction // i_divisor



[修正後]
function integer i_divisor;
input integer baudrate;
input integer clkinmhz;
begin
i_divisor = ((1048576.0 * (baudrate/100.0)) / (clkinmhz*10000.0)) + 0.5;
end
endfunction // i_divisor



[修正前]
parameter INTEGER_DIVISOR = i_divisor(BAUD_RATE);



[修正後]
parameter INTEGER_DIVISOR = i_divisor(BAUD_RATE, CLK_IN_MHZ);




その後も試行錯誤して、やっと合成がはじまったかなーと思ったら次のエラーに遭遇。

FATAL_ERROR:Xst:Portability/export/Port_Main.h:127:1.17


Xilinxのサイトで調べてみたけど

FATAL_ERROR:Xst:Portability/export/Port_Main.h:127:1.17

ちょっと原因がわかりません。

どなたか試された方いませんか?

一応、解決しました。
詳細はこちら

水曜日, 10月 03, 2007

アンケート結果

1ヶ月ぐらい、アンケートを取ってました→

『使っているシミュレータ(検証環境)は何?』

結果は次のとおり。



やっぱり無償版もあるModelSimの利用者が多いみたいですね。
FPGAに限るともっと比率は上がりそう。

しかし、NC-VerilogやVCSなどの利用者の方もいらっしゃるようで。
さすがにこれらは個人で購入する人はいないと思うので、企業にお勤めのエンジニアの方かまたは大学関係の方か。
そういう方々にもこのブログを見ていただいていると思うと恐縮です。

知ってる人は知っている国産シミュレータのVeritakも18%と健闘です。
コストパフォーマンスはNo.1?

Icarus Verilogの利用者は意外と少ないようです。
日本語のドキュメントが少ないことが原因?

Aldecはマイナー?

その他はCverとかでしょうか?


以上、第1回のアンケート結果でした。
第2回以降があるかどうかは未定ですが。。。

もし、こんなアンケートをやってほしいというものがあればコメントにどうぞ。

月曜日, 10月 01, 2007

オンチップバス

ここのところ、新しく書くテーマを何にしようかなぁと考えてます。

オンチップバスなんかどうでしょうか?

オンチップバスとは、チップ内でモジュール間の接続を行なうバスの事で
有名なところでは、

・CoreConnect
・AMBA
・WISHBONE

等があります。

それぞれの概要は次のPDFを参照。

SoC Bus Review

で、オンチップバスを採用する利点ですが
まずは文書化されているということでしょうか。

上記の3つであればそれぞれ仕様をWEBから入手可能です。
AMBAは日本語のドキュメントも提供されています。

なので、毎回その場かぎりのインタフェースを設計して、デバッグして、
しかもドキュメントが不十分という状況から脱却することができます。

また、インタフェースが統一されていれば再利用性もあがりますし
広く使われているインタフェースであればIPとしての価値も上がります。

以上のことから、オンチップバスを採用することをお勧めしたい。

SoCやってることところであれば当然のことと思われるかもしれないが
そうでないところでは意外に使われてないんじゃないでしょうか?

今のところ、AMBA AHBかWISHBONEかで迷ってるんですけど
今月のDesign Waveの記事にWISHBONEを採用しているオープンソースのCPUコアのことが書いてあったのでこれを使ってみるのも面白いかな?

ただ今、仕事で基板の回路設計をやっているのでなかなかそっちのほうに頭が向かない。

回路設計はロジックと違って、サイズや構造、電気的なこともさることながら部品の入手性や価格のことなんかも考えなきゃいけないので大変だ。

あまり好きくはないのだがやらねばその先ができないのでしょうがない。

火曜日, 9月 25, 2007

現場の仕事がバリバリ進むソフトウェアテスト手法

現場の仕事がバリバリ進むソフトウェアテスト手法

私はソフト屋でもテスト屋でもありませんが
あまり堅苦しくないので読み流すにはいいかなと。

テスト管理者向けの本ですね。

でも、開発側の人がテスト側の仕事を知るにも
ちょうどいいくらいの本だと思います。

ところどころに出てくる「開発者はドキュメントを書かない」は痛いところ。
開発者も品質のことを考えないとね。

著者はMicrosoftに勤めていた経験があるそうでその話も良く出てきます。
Microsoftでそうだったんなら、そうなんだろうなぁ。

最後にはテスト担当者を採用する際の面接などについても書かれています。

他でも読んだことがありますが、Microsoftの面接で

「富士山をどうやって動かしますか?」

って聞かれるのは本当なんですかね。
有名な話みたいですが。

なぜ富士山が選ばれたか?ということのほうが気になるけど。

木曜日, 9月 13, 2007

有限狀態機的都會傳奇

タイトルが中国語なのは気まぐれです。
一応、『ステートマシンの都市伝説』と書いたつもりですがあってるかな?

さて、ステートマシンのエンコーディング方法について
それぞれ長所短所があって云々などといったことを
読んだり聞いたりしたことがあると思います。

実際のところどうなんでしょう?

FPGAをターゲットとして、ISEでちょっと実験してみました。

まずテストのコードはこれ。

module StateTestA (/*AUTOARG*/
// Outputs
DAT_O,
// Inputs
CLK_I, RST_I, DAT_I
);

input CLK_I;
input RST_I;

input [7:0] DAT_I;
output [7:0] DAT_O;

reg [7:0] DAT_O;

parameter [3:0]
STATE_A = 4'hA,
STATE_B = 4'hB,
STATE_C = 4'hC,
STATE_D = 4'hD,
STATE_E = 4'hE,
STATE_F = 4'hF;

reg [3:0] state_r;
reg [3:0] nxState;

reg [7:0] dataOut;

always @(posedge CLK_I or posedge RST_I) begin
if (RST_I)
state_r <= STATE_A;
else
state_r <= nxState;
end

always @* begin
nxState = state_r;
dataOut = 8'h00;
case (state_r)

STATE_A: begin
dataOut = 8'h00;
if (DAT_I==8'h03)
nxState = STATE_B;
end

STATE_B: begin
dataOut = 8'h05;
if (DAT_I==8'h0F)
nxState = STATE_C;
end

STATE_C: begin
dataOut = 8'h0A;
if (DAT_I==8'h3F)
nxState = STATE_D;
end

STATE_D: begin
dataOut = 8'h50;
if (DAT_I==8'hFF)
nxState = STATE_E;
end

STATE_E: begin
dataOut = 8'hA0;
if (DAT_I==8'hFC)
nxState = STATE_F;
end

STATE_F: begin
dataOut = 8'hFF;
if (DAT_I==8'hF0)
nxState = STATE_A;
end

default:; // No recovery

endcase
end

always @(posedge CLK_I)
DAT_O <= dataOut;

endmodule



6つのステートを作り、それをぐるっと1周させる単純なものです。
ステートのエンコーディングは適当。

まずは合成のプロパティの HDL Options で FSM Encoding Algorithm を One-Hot に設定。



合成結果のステートマシンの部分を View RTL Schematic で確認するとこんな感じ。



細かいところは見えないと思いますが、FFがステート数分の6つできていることは確認できると思います。

続いて、設定を Gray に変更してみると次のように変わりました。



こちらはFFの数は3つです。
回路の印象もずいぶん違うように見えます。

では次に、合成のレポートを見てみましょう。
主要な部分のみ抜粋します。

まずはワンホット。


[One-hot]

Optimizing FSM on signal with one-hot encoding.
-------------------
State | Encoding
-------------------
1010 | 000001
1011 | 000010
1100 | 000100
1101 | 001000
1110 | 010000
1111 | 100000
-------------------

Device utilization summary:
---------------------------

Selected Device : 3s500efg320-5

Number of Slices: 11 out of 4656 0%
Number of Slice Flip Flops: 10 out of 9312 0%
Number of 4 input LUTs: 21 out of 9312 0%
Number of IOs: 18
Number of bonded IOBs: 18 out of 232 7%
Number of GCLKs: 1 out of 24 4%

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 3.012ns (Maximum Frequency: 331.956MHz)
Minimum input arrival time before clock: 6.108ns
Maximum output required time after clock: 4.063ns
Maximum combinational path delay: No path found



続いてグレイコード。


[Gray]

Optimizing FSM on signal with gray encoding.
-------------------
State | Encoding
-------------------
1010 | 000
1011 | 001
1100 | 011
1101 | 010
1110 | 110
1111 | 111
-------------------

Device utilization summary:
---------------------------

Selected Device : 3s500efg320-5

Number of Slices: 12 out of 4656 0%
Number of Slice Flip Flops: 7 out of 9312 0%
Number of 4 input LUTs: 21 out of 9312 0%
Number of IOs: 18
Number of bonded IOBs: 18 out of 232 7%
Number of GCLKs: 1 out of 24 4%

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 3.078ns (Maximum Frequency: 324.839MHz)
Minimum input arrival time before clock: 6.843ns
Maximum output required time after clock: 4.063ns
Maximum combinational path delay: No path found



どうですか?
あなたのイメージと一致しているでしょうか?

ちなみにVHDLで似たようなことをやっているものを見つけたので紹介しておきます。
State machine encoding (Gray, Binary and One-hot)

他もいくつか試してみましたのでその結果も載せておきます。

ユーザーエンコードそのまま。


[User]

Optimizing FSM on signal with user encoding.
-------------------
State | Encoding
-------------------
1010 | 1010
1011 | 1011
1100 | 1100
1101 | 1101
1110 | 1110
1111 | 1111
-------------------

Device utilization summary:
---------------------------

Selected Device : 3s500efg320-5

Number of Slices: 16 out of 4656 0%
Number of Slice Flip Flops: 7 out of 9312 0%
Number of 4 input LUTs: 29 out of 9312 0%
Number of IOs: 18
Number of bonded IOBs: 18 out of 232 7%
Number of GCLKs: 1 out of 24 4%

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 3.904ns (Maximum Frequency: 256.144MHz)
Minimum input arrival time before clock: 6.834ns
Maximum output required time after clock: 4.063ns
Maximum combinational path delay: No path found



ジョンソン。


[Johnson]

Optimizing FSM on signal with johnson encoding.
-------------------
State | Encoding
-------------------
1010 | 000
1011 | 001
1100 | 011
1101 | 111
1110 | 110
1111 | 100
-------------------

Device utilization summary:
---------------------------

Selected Device : 3s500efg320-5

Number of Slices: 11 out of 4656 0%
Number of Slice Flip Flops: 7 out of 9312 0%
Number of 4 input LUTs: 21 out of 9312 0%
Number of IOs: 18
Number of bonded IOBs: 18 out of 232 7%
Number of GCLKs: 1 out of 24 4%

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 3.012ns (Maximum Frequency: 331.956MHz)
Minimum input arrival time before clock: 6.467ns
Maximum output required time after clock: 4.063ns
Maximum combinational path delay: No path found



オート。


[Auto]

Optimizing FSM on signal with sequential encoding.
-------------------
State | Encoding
-------------------
1010 | 000
1011 | 001
1100 | 010
1101 | 011
1110 | 100
1111 | 101
-------------------

Device utilization summary:
---------------------------

Selected Device : 3s500efg320-5

Number of Slices: 13 out of 4656 0%
Number of Slice Flip Flops: 7 out of 9312 0%
Number of 4 input LUTs: 24 out of 9312 0%
Number of IOs: 18
Number of bonded IOBs: 18 out of 232 7%
Number of GCLKs: 1 out of 24 4%

Timing Summary:
---------------
Speed Grade: -5

Minimum period: 4.038ns (Maximum Frequency: 247.620MHz)
Minimum input arrival time before clock: 6.441ns
Maximum output required time after clock: 4.063ns
Maximum combinational path delay: No path found



適当(いい加減)なエンコーディングをしているので
ユーザーエンコーディングそのままのものが結果が悪いのは予想がつきますが
なぜかAutoの場合もそれほど良くないですね。

Autoではバイナリエンコーディングされているようですが
FPGAの場合、グレイとバイナリではそれほど変わらないと思っていたのですが意外でした。

まあでも、この結果は今回たまたまで、他のオプションを変えたりもっと複雑なステート遷移のものだとまた違った結果が得られるかもしれません。

この結果が大きいと
感じるか感じないかはあなた次第です。

月曜日, 9月 10, 2007

verilog-modeでenum

Verification Engineerの戯言から

enumを使えば、、

SystemVerilogやVHDLならば列挙型が使えるので、
シミュレーション結果を波形で見るときASCIIで見れて便利だねというお話。

残念ながら普通のVerilogだと列挙型は使えない。

そこで、verilog-modeの/*AUTOASCIIENUM*/を使うという方法があります。
↓こんな感じ。

//== State enumeration
parameter [1:0] // synopsys enum state_info
ST_DoorClose = 2'b00,
ST_Opening = 2'b01,
ST_DoorOpen = 2'b10,
ST_Closing = 2'b11;
//== State variables
reg [1:0] /* synopsys enum state_info */
state; /* synopsys state_vector state_r */
//== ASCII state decoding
/*AUTOASCIIENUM("state", "_state__ascii", "ST_")*/


ここまで書いておいて、C-c C-aとタイプすると次の記述が自動で追加されます。

// Beginning of automatic ASCII enum decoding
reg [71:0] _state__ascii; // Decode of state
always @(state) begin
case ({state})
ST_DoorClose: _state__ascii = "doorclose";
ST_Opening: _state__ascii = "opening ";
ST_DoorOpen: _state__ascii = "dooropen ";
ST_Closing: _state__ascii = "closing ";
default: _state__ascii = "%Error ";
endcase
end
// End of automatics


こうしておくと、シミュレーション時の波形確認の際にステートをASCIIで見ることができます。
結果はこのとおり。


ステート表示に使う変数は回路で使用されるわけではないのでそのままでも問題はないと思いますが、論理合成ツールの警告が気になる場合は`ifdefなどでシミュレーション時のみ記述が有効となるようにすればよいでしょう。

詳しい使い方は↓こちらを参照してください。
Verilog-Mode: Reducing the Veri-Tedium
2.10 State Machines

水曜日, 9月 05, 2007

code*

ブログにソースコードを貼り付けるのに苦労していたのですが
↓次のサイトを利用させていただくことで便利な方法が見つかりました。

code*(コードなにがし)

こちらにコードを登録することで履歴管理や(反応してもらえれば)フィードバックを受けれます。

さらに↓こちらで提供されている『コードなにがしガジェット』使えば

コードなにがしがなにげに便利かも


このようにソースコードをブログに組み込めちゃう!



ちょっと感動しちゃいました。

ちなみにコードの色分けは google-code-prettify というものを使われているようで
これ自体はverilogに対応しているわけではないのですが、
verilogがCの文法に近いのである程度色分けをしてくれているみたいです。

便利なツールどうもありがとうございます。

火曜日, 9月 04, 2007

秋の夜長に

もう9月ですね。

年をとるごとに時が経つのがはやくなるというのはどうやら本当のよう。

さて、今回はゲームの紹介。

ニンテンドウDSのソフト

レイトン教授と不思議な町


最近やってみたのですが結構はまってました。

いくつか意地悪な問題もありますが、基本的には論理パズルがメインです。

「天秤とコイン」や「川渡りのパズル」、「Nクイーン問題」などの有名なものもあって
結構、論理的思考のトレーニングになります。

多分、脳トレよりも効く。

こういうのって、デバッグしているときの思考に似ていると思うのは私だけでしょうか?
可能性を1つづつ潰していって、最後に目標にたどり着くみたいな。

あと特筆すべきは、低解像度の画面なのにそれを感じさせないこと。
調べてみるとDSって1画面192×256ピクセルなんですね。
携帯よりも解像度が低いとは知らなかった。

自分なんか解像度が低いことを簡単に言い訳にしてしまいそうですが
ゲーム業界で画面を作ってる人たちってスゴイですね。

既に次回作の発売も決定しているようです。

仕事で行き詰ってるときに
こういうので気分転換してみるといいかも。

月曜日, 9月 03, 2007

Applied Hardware Verification

Applied Hardware Verification


オレゴン健康科学大学(?)の講義のシラバスのようです。

まだ細かいところは読んでいませんが、
表題のとおり実用的なハードウェア検証の講義。

講義のスライドがPDFで閲覧可能で
これを読むだけでも結構勉強になりそう。

もちろん英語ですけど。

PSLなんかについても書いてありますね。

私は学生時代は物理をやっていたので日本の大学の
情報系の講義がどんなものかは知らないのですが
最近はこういう内容をやっているんですかね?

少なくとも日本語のサイトでこれほど丁寧な資料はお目にかかったことはありません。

ネットが普及するにつれて英語の苦手な日本のエンジニアは
どんどんおいてきぼりを食ってしまうような気がする。

それとも自分が勝手にそう思っているだけなのかなぁ。
ウェブで見かけるエンジニアの方々は普通に英語使ってそうだし。

某S社の人と話したときは「この規格は英語版のものしか読んでない」という人もいたし
その関連会社の別の人は逆に「英語の資料はほとんど読んだ事がない」という人もいたし。

この業界の英語力ってどんなもんなんだろう?

私はというと、やっぱり日本語のほうが楽です。

火曜日, 8月 28, 2007

8歳から学べるFPGA?

EETIMES Japanから

8歳の天才児がFPGAを使いこなす

Actelなら簡単!と言いたい所だろうか?

でも、Actelのサイトに行ってみると資料はほとんど英語ですね。
最低、ネイティブの8歳児程度の英語力は必要なのかも。。。

FPGAはALTERAかXilinxしか使ったことはありませんが
Actelは独自のFPGAを出しているので少し興味はある。

ADCやFlashが内臓だったり。
CPUコアもARMだし。

その8歳児に送ったという基板付きの開発キット、
うちにも送ってくれないかなぁ。

月曜日, 8月 27, 2007

ステートマシン その5

前回の続き。

それでは、前回作成したRTL記述で正しく動作するかどうかシミュレーションをやってみましょう。

たとえターゲットがFPGAであったとしても、この程度の規模のステートマシンであれば
少なくともRTLシミュレーションで全ての状態と全ての遷移条件についてはカバーしておきたいものです。

今回の場合は次の4つのステートを通過すること。

・ST_DoorClose
・ST_Opening
・ST_DoorOpen
・ST_Closing

そして、次の7つの遷移(同じステートにとどまるものも含めるとさらに+4)が行なわれることです。
・ST_DoorClose -> ST_Opening
・ST_Opening -> ST_DoorOpen
・ST_DoorOpen -> ST_Closing (閉ボタン)
・ST_DoorOpen -> ST_Closing (5秒経過)
・ST_Closing -> ST_DoorClose
・ST_Opening -> ST_Closing
・ST_Closing-> ST_Opening

以上の動作を確認するためのテストベンチを作成しました。
主要な部分を次に示します。


initial begin
// Initialize Inputs
reset = 1'b1;
buttonOpen = ~PUSHED;
buttonClose = ~PUSHED;

// Wait 100 us for global reset to finish
#1;
reset <= 1'b0;
// Add stimulus here
#100;
pushOpenButton();
wait(doorPosition==DOOR_POS_MAX);
#100;
pushCloseButton();
wait(doorPosition==DOOR_POS_MIN);
#100;
pushOpenButton();
#20000; // 2.0sec
pushCloseButton();
#10000; // 1.0sec
pushOpenButton();
wait(doorPosition==DOOR_POS_MAX);
wait(doorPosition==DOOR_POS_MIN);
#100;
$finish(2);
end


StateMachineSampleTB.v←完全なコードはこちら。

StateMachine.zip←RTLを含めた検証環境一式のZIPファイル。

タイムユニットは100usです。
ドアが完全に閉まった状態から完全に開いた状態(またはその逆)までには約4秒かかるようにしています。

シミュレーションの流れは次のとおりです。

・シミュレーション開始

・初期状態でドアは閉まっている。

・"開"ボタンを押して、ドアが完全に開くまで待つ。

・ドアが完全に開いたら、"閉"ボタンを押してドアが完全に閉まるまで待つ。
↓(ここまででひとまず全てのステートは通過)

・もう一度"開"ボタンを押す。

・ドアが開いている途中で"閉"ボタンを押す。

・ドアが閉まっている途中で"開"ボタンを押す。

・ドアが完全に開くまで待つ。
↓(5秒経過して自動で閉まりだす)

・ドアが完全に閉まるまで待つ。

・シミュレーション終了

シミュレーションの出力結果は次のようになりました。

# State = ST_DoorClose @ 0
# Open button pushed.
# State = ST_Opening @ 115
# State = ST_DoorOpen @ 40815
# Close button pushed.
# State = ST_Closing @ 40915
# State = ST_DoorClose @ 81615
# Open button pushed.
# State = ST_Opening @ 81715
# Close button pushed.
# State = ST_Closing @ 101725
# Open button pushed.
# State = ST_Opening @ 111735
# State = ST_DoorOpen @ 142575
# State = ST_Closing @ 192585
# State = ST_DoorClose @ 233295


一応、波形も載せておきましょう。


ST_DoorClose -> ST_Opening


ST_Opening -> ST_DoorOpen -> ST_Closing (閉ボタン)


ST_Closing -> ST_DoorClose


ST_Opening -> ST_Closing


ST_Closing-> ST_Opening


ST_DoorOpen -> ST_Closing (5秒経過)


無事動いているようですね。
今回は省略していますが、これに加えて遷移条件が重なった場合に(今回ではST_OpeningやST_Closingから他のステートに遷移する場合)期待したとおりの動作となっているかどうかを確認することも重要です。

この程度のモジュールの単体試験用にちゃんとしたテストベンチを作る必要はあるのか?と聞かれるとなかなか自分もできていない場合が多いので偉そうなことは言えませんが、小さい単位だからこそ少し手間をかけてでも一度ちゃんとしたものを作っておけば、RTLに変更を加えた場合に、論理合成をかける前や後工程に渡す前、または自分が設計するより大きな単位のモジュールに組み込む前に、サッとシミュレーションを流すだけでかなりリスクを抑えることができると思います。

話はそれますが、ソフトのプログラミング言語に比べてHDLの参考になる記述をWebなどで探すのは大変ですよね。さらにテストベンチ用のシミュレーション記述となるとRTL記述に比べてさらに少ない。
結局自分もかなり自己流の記述になっていると思うので、そのあたりを考慮に入れてコードを読んでください。

とりあえず今回でステートマシン記述については終わり。

ステートマシンに関してはもっと書いてみたい事もあるのですがそれはまたの機会に。

木曜日, 8月 23, 2007

FPGAが論理合成しなくても動く!?

なひたふさんのところで面白い記事を発見。

FPGAが論理合成しなくても動く


ようはFPGAをFPGAとして使ってないのでなんでもアリ。
ボードのデバッグなどにはかなり使えそうですよね。

JTAGのバウンダリスキャンに対応してたら、FPGAじゃなくても良いのだろうから
いっそのことJTAGのバウンダリスキャンのみで端子を制御する安価なチップを作ってしまってもいいかもしれない。

「そんなもん、遅すぎて使えねーだろ!」
という意見もあるかもしれませんが、低速でもI/Oポートを自由に制御できると便利な分野もあると思うんですよね。

FA機器の制御とかはどうかな?
ちょっと環境が厳しいかもしれないけど。

何より、簡単なスクリプトのみでハードウェアを制御できるというのは何かしら可能性を感じます。

FPGAにこだわる必要はまったく無い。

月曜日, 8月 20, 2007

ステートマシン その4

前回の続き。

私がステートマシンを記述する場合、大きく分けて2通りの方法があります。

1つは出力レジスタが無い記述で、もう一つは出力レジスタ付きの記述です。

どのような感じか、ちょっと書いてみると

出力レジスタ無しの場合は、

always @(posedge clock or posedge reset) begin
if (reset)
state <= INITIAL_STATE;
else
state <= next_state;
end

always @* begin
next_state = state;
case(state)

INITIAL_STATE: begin
output_signal = 1'b0;
if (input_signal==1'b1) begin
output_signal = 1'b1;
next_state = SECOND_STATE;
end
end

SECOND_STATE: begin
output_signal = 1'b1;
if (input_signal==1'b0)
next_state = LAST_STATE;
end

LAST_STATE: begin
output_signal = 1'b1;
next_state = INITIAL_STATE;
end

default: begin // Recovery from illegal state
next_state = INITIAL_STATE;
output_signal = 1'b0;
end

endcase
end


出力レジスタ付きの場合は、

always @(posedge clock or posedge reset) begin
if (reset) begin
state <= INITIAL_STATE;
output_signal <= 1'b0;
end
else begin
case(state)

INITIAL_STATE: begin
output_signal <= 1'b0;
if (input_signal==1'b1) begin
output_signal <= 1'b1;
state <= SECOND_STATE;
end
end

SECOND_STATE: begin
output_signal <= 1'b1;
if (input_signal==1'b0)
state <= LAST_STATE;
end

LAST_STATE: begin
output_signal <= 1'b1;
state <= INITIAL_STATE;
end

default: begin // Recovery from illegal state
state <= INITIAL_STATE;
output_signal <= 1'b0;
end

endcase // case(state)
end
end


注意すべき点としては、出力レジスタがある場合と無い場合で出力のタイミングが若干異なるところです。
上記の例で言えば、INITIAL_STATEからSECOND_STATEに移る際のoutput_signalの変化点です。
出力レジスタが無い場合はINITIAL_STATEの最後の1サイクルはoutput_signal=1'b1ですが、出力レジスタ有りの場合は、INITIAL_STATEの最後の1サイクルはoutput_signla=1'b0で、SECOND_STATEの1サイクル目にはじめてoutput_signal=1'b1となります。

また、出力レジスタ無しの場合では出力のハザードにも注意が必要です。
上記の例ではSECOND_STATE,LAST_STATEともに出力output_signal=1'b1なのでコードからはその間のステートの遷移中に出力に変化はないように見えますが、例えば各ステートが次のようにエンコードされていた場合、

INITIAL_STATE=2'b00, SECOND_STATE=2'b01, LAST_STATE=2'b10

実際はSECOND_STATEからLAST_STATEに移る際の信号の変化の過程で

2'b10 -> 2'b00 -> 2'b10

となって、一瞬の間SECOND_STATEでもLAST_STATEでもない状態になり、その瞬間の出力がヒゲのように出てしまいます。

出力レジスタ付きの場合はこのような心配はありません。

今回は出力レジスタ付きの記述でステートマシンを書いてみました。
主要な部分を抜き出すと、次のようになります。

/*
* State Machine
*/
always @(posedge clock or posedge reset) begin
if (reset) begin
state <= ST_DoorClose;
doorControl <= DOOR_STOP;
end
else begin
case(state)

ST_DoorClose: begin
doorControl <= DOOR_STOP;
if (buttonOpen==PUSHED)
state <= ST_Opening;
end

ST_Opening: begin
doorControl <= DOOR_OPEN;
if (buttonClose==PUSHED)
state <= ST_Closing;
else if (doorPosition==DOOR_POS_MAX)
state <= ST_DoorOpen;
end

ST_DoorOpen: begin
doorControl <= DOOR_STOP;
if ((buttonClose==PUSHED)||
(openCounter==TIME_LIMIT))
state <= ST_Closing;
end

ST_Closing: begin
doorControl <= DOOR_CLOSE;
if (buttonOpen==PUSHED)
state <= ST_Opening;
else if (doorPosition==DOOR_POS_MIN)
state <= ST_DoorClose;
end

default: begin
doorControl <= DOOR_STOP;
end

endcase
end
end

StateMachineSample.v←完全なコードはこちら

前回の最後の状態遷移図からこのコードに落とすのはそれほど難しくないですよね。

ちなみにこのコードではクロック入力を1KHzと想定しています。
現在、実際の設計でそんなに遅いクロックを使うことはまず無いと思いますが
練習用として大目に見てください。

次回はこのコード用にテストベンチを書いて、シミュレーションをやってみたいと思います。

金曜日, 8月 17, 2007

機能検証関係の動きが活発

米XilinxがEDA大手3社と組み,大規模FPGAの機能検証で新フローを構築へ

米Cadenceと米Mentor,SystemVerilogベースの機能検証手法を統一へ

共に興味深い。

こちらの言葉を借りれば、FPGA業界もいよいよVerification3.0に突入か?

そして、オープン化の流れもできつつあるかもしれない。

しかしまだ、アサーションやカバレッジ機能を利用できるツールは普通に高い。

FPGAの統合環境である程度使える物が出てきると一気に裾野が広がって、ハードウェア設計・検証の分野に何かしらのブレークスルーが起きるような気がするのだけれども。

でなければ、1つのチップとしてのLSIの大規模化が収束していくか。

それを設計・検証できるインフラがないと、やれったってできませんからね。
そして大きくした分、かかったコストをペイできるのかっていうことになってしまう。

PSPとDS、PS3とWiiの状況を見るとなんでも1つで大量に高速に処理できればいいという分けではなさそうだし。

使う人または使われ方のバリエーションを増やすって考え方も重要ですねー。

水曜日, 8月 08, 2007

ステートマシン その3

前回、とりあえずの状態遷移図を描いてみました。

この状態遷移図では、仕様の中の次の機能が表されていません。

・ドアが完全に開いた状態で、5秒間"閉"ボタンが押されなければドアを閉じる

どうやって実現しますか?
多分、カウンタを用意する必要がありますね。

あと、仕様に明記されていることではありませんが

・ドアが開いている最中に"閉"ボタンを押した場合

及び

・ドアが閉まっている最中に"開"ボタンを押した場合

も考えておいた方が良さそうです。
そういうシチュエーションはよくありますよね。

隠れた仕様というものは設計を進めるうちに意外に出てくるものです。
いきなりコーディングをはじめるとそういったものにかき回されて、いつの間にかスパゲッティにということになりかねません。

特にHDLはソフトのプログラミング言語と違って必ずしも上から下へ流れていくわけではないので、ある程度静的な構造が見えていないと全体が把握しづらくなります。

それでは、仕様を満足する状態遷移図を見てみましょう。



ドア状態カウンタは外部に置いても良いと思いますが、今回は同じモジュールの中に置くことにします。

ではこの状態遷移図をコーディングの1歩手前まで持っていこうと思います。
とはいってもやることは単純で、日本語のままだと変数名として使えないのでそれっぽい英語に変換して、代入や条件判断を記号に変えるだけです。

次のようになります。



ここまでくれば、ほぼそのままコーディングに持っていけるはずです。

それでは次回、これを元にVerilogでステートマシンをコーディングしてみたいと思います。

木曜日, 8月 02, 2007

ステートマシン その2

ステートマシンの題材として、
エレベータのドアの制御のようなものを考えてみようと思います。

仕様は次のとおり。
実際のエレベータのドアがどのように行なわれているのか全く知らないので
以下の仕様は想像です。なので、かなり変かもしれませんがその辺は大目に。

[エレベータ ドアの制御モジュールの仕様]
・"開"ボタンと"閉"ボタンの入力
・"開"ボタンでドアが開き、"閉"ボタンでドアが閉まる
・外部にドア制御信号を出力
・ドア制御のバリエーションは「開ける」、「閉める」、「停止」の3つ
・ドア位置情報の入力
・ドア位置情報は完全に閉まった状態を"Min"、完全に開いた状態を"Max"とする
・ドアが完全に開いた状態で、5秒間"閉"ボタンが押されなければドアを閉じる


実際のモジュールの仕様であれば信号名やタイミングなど明確になっているべきですが、今回はここから始めることにします。
現実の仕事でも曖昧な仕様が渡されて、詳細は自分で定義しなければならないことは多いと思うので。。。

まずはどういう状態があるか考えましょう。
次の4つが妥当なところでしょうか?

1.ドアが完全に閉まった状態
2.ドアが完全に開いた状態
3.ドアが開いている最中の状態
4.ドアが閉まっている最中の状態

ちょっとシナリオを書いてみると、

まずドアが閉まっている。
"開"ボタンを押すとドアが開き始める。
ドアが完全に開くとその状態でドアは停止。
"閉"ボタンを押すとドアが閉まり始める。
ドアが完全に閉まるとその状態でドアは停止。

なんとなくよさそうです。
それでは早速状態遷移図を描いてみましょう。



まだ完全というわけではありませんが、なんとなくそれらしいものができていると思います。

次回はこの状態遷移図を仕様を満足させるところまで持っていって
さらにコーディングできる1歩手前までやってみたいと思います。

このシリーズは少し長くなりそう。

ところで、普段使っていたわけではないのですが、今回の状態遷移図はJUDE Communityというツールを使ってUMLのステートチャート図で描いてみました(UMLに慣れてないので変なところがあればご指摘ください)。

個人的にはハードウェアの設計にUMLを使うのはなかなか難しいところがあるなぁと考えているのですが、ステートチャート図についてはほぼそのまま使えると思います。

逆に言うと、ステートマシンでできることはソフトでできる処理とかなりオーバーラップがあります。

実際、今回のお題のようなものであれば恐らく1チップマイコン等を使うほうが多いのではないでしょうか?

最近はコンパクトなソフトマクロCPUもあるので、下手にステートマシンを設計するよりはそういうものを使ったほうが生産性・品質の両面でお得かもしれません。

水曜日, 8月 01, 2007

ステートマシン その1

さて、今回は現在のRTLデザインにおいては欠かせないステートマシン(FSM)について書いてみようと思います。

正式には"Finite State Machine"で日本語では「有限状態機械」などと訳すのでしょうが、現場のエンジニアには単に「ステートマシン」と呼んだほうがとおりが良いと思います。

ディジタル回路でステートマシンというと、

ムーア型だのミーリ型だの

はたまた

グレイ、ジョンソン、ワンホット

だのといったキーワードが出てくると思いますが、個人的にはそういったキーワードは教科書で一度読んでおけばいいかなぁ程度に思っています。

ムーアかミーリかと悩むよりは入力を全て単一のクロックに同期させたほうが良いし、出力のハザードを考慮してステートの遷移の際のハミング距離を1に抑える努力をするよりは出力にレジスタを付けて出したほうがずっと楽な場合が多いと思うからです。

正直、ステートの宣言などは列挙型で行なって合成ツールで勝手に最適化してくれる方が自分は好きです。

最も、最近の合成ツールは勝手にやってたりするので手動で苦労してステートをエンコードしても無駄になっているかもしれませんが。。。

まあ、どうしてもパフォーマンスが達成できない場合にはそのあたりをいろいろチューニングする破目になるのかもしれませんが、生産性・検証のことを考えるとできるだけ実装に近い部分を考慮しないですむほうが良いでしょう。

では次回、具体的に(簡単な)ステートマシンの設計をやってみたいと思います。

日曜日, 7月 29, 2007

アドレスデコーダ

ここでの"デコーダ"とは、アドレスをデコードしてチップセレクト信号を生成するようないわゆるアドレスデコーダです。

Verilogでの一般的な記述は次のようなものでしょうか?

case(address)
2'd0: chipSelect = 4'b0001;
2'd1: chipSelect = 4'b0010;
2'd2: chipSelect = 4'b0100;
2'd3: chipSelect = 4'b1000;
endcase

この場合、再利用性が少々乏しくなります。
次のような記述方法もあります。

parameter AD_WIDTH = 2;
parameter CS_WIDTH = 4;

input [AD_WIDTH-1:0] address;
output [CS_WIDTH-1:0] chipSelect;

assign chipSelect = 1 << address;

これならパラメータの変更のみで再利用可能です。

ちなみにCSR(コントロールステータスレジスタ)を記述するような場合、
私はアドレスデコーダを明確に記述することはしません。
だいたいこのような感じです。

always @(posedge ICLK or posedge IRST) begin
if (IRST) begin
regControl <= 0;
end else begin
if ((WE)&&(address==ADR_CONTROL))
regControl <= writeData;
end
end

これをデコーダを書いて、セレクト信号を生成して・・・とやると
デコーダ分の記述が増えるだけでなく
次のような記述を見て

always @(posedge ICLK or posedge IRST) begin
if (IRST) begin
regControl <= 0;
end else begin
if ((WE)&&(sel[4]))
regControl <= writeData;
end
end

はたして、セレクト信号のbit4はこのレジスタのものだっただろうか?
とデコーダの記述を見に行く必要もなくなります。

これも抽象化の一例ですね。



しかし、このブログはコードが書きづらい。
preタグと"<<"を一緒に使うと崩れてしまう。
いい方法無いのかなぁ。

火曜日, 7月 24, 2007

組み合わせ回路

verilogで組み合わせ回路を記述する場合、alwaysかfunctionを使うことになると思います。

alwaysを使うとこんな感じでしょうか。


always @* begin: ReadDataMux
case(address)
ADDR_REG_A: readData = regA;
ADDR_REG_B: readData = regB;
ADDR_REG_C: readData = regC;
ADDR_REG_D: readData = regD;
default : readData = 0;
endcase
end


functionを使うならばこんな感じ。


function [7:0] BarrelShift (
input [7:0] dataIn,
input [2:0] shift
);
reg [15:0] rtData;
begin
rtData = {dataIn, dataIn} << shift;
BarrelShif = rtData[15:8];
end
endfunction

ともにVerilog2001を対象に書いています。

alwaysは"@*"が使えるので入力の種類が多いときなどに便利です。
短所は出力をregで宣伝しなければならないこと。

レジスタにならないものをregで宣言しなければならないことは
初心者を十分混乱させてくれます。

また、当初は簡単な組み合わせ回路だからとおもって

assign control = (signal==RED) ? STOP : GO;

と書いていたら、やっぱり安全第一ということで


always @* begin: DriveControl
case(signal)
RED : control = STOP;
YELLOW : control = ATTENTION; // STOP is better.
BLUE : control = GO;
default: control = STOP;
endcase
end


このように変更した場合に、
わざわざcontrolの宣言をwireからregに変えなければならないというのも面倒です。

functionの場合は、function内のみのスコープをもつ変数を使えるところが利点です。
Cでプログラムを書く人などはこちらのスタイルの方が好みかもしれません。

注意点は、ポートリストに入っていなくても同一モジュール内の信号を参照できてしまうことです。
この場合、シミュレーション時にラッチを生成しているような動作をしてしまい、検証の際に非常に痛い目に会うかもしれません。

例えば次のような場合、


function [7:0] FuncOut (input a, input b);
begin
FuncOut = a & b & c; // cはfunction外で宣言
end
endfunction


シミュレーションでは、
入力a,bに変化があった場合は出力も変化しますが
cが変化した時点では出力は変化しません。

両方使い分けれるようになれば、verilog初心者は卒業かな?
それだけで判断できるようことでもないですが。

しかし、verilogはいまだに中途半端な仕様です。

土曜日, 7月 21, 2007

バレルシフト その2

前回の続き

さて、バレルシフタをverilogでどう記述するかというとこんな感じでしょうか?


parameter DATA_WIDTH = 8;
parameter SHIFT_WIDTH = 3;

input [DATA_WIDTH-1:0] iDATA_IN;
input [SHIFT_WIDTH-1:0] iSHIFT;

output [DATA_WIDTH-1:0] oDATA_OUT;

wire [(DATA_WIDTH*2)-1:0] shiftedData;

assign shiftedData = {iDATA_IN,iDATA_IN} << iSHIFT;
assign oDATA_OUT = shiftedData[(DATA_WIDTH*2)-1:DATA_WIDTH];

つまり入力がabcdefghと与えられた場合、まずそれを2つ並べて
{abcdefgh,abcdefgh}

それをシフト。たとえば3つシフトするなら

{defghabcdefgh,xxx}

最後に上位半分だけとって

defghabc

でバレルシフト完成。

ただ、これってどのような回路になっているのか簡単にはわからないですよね。
恐らく、この記述の合成結果は次のようになっていると思います。

wire [DATA_WIDTH-1:0] shift1stDATA;
wire [DATA_WIDTH-1:0] shift2ndDATA;

assign shift1stDATA = (iSHIFT[0]) ?
{iDATA_IN[DATA_WIDTH-2:0],iDATA_IN[DATA_WIDTH-1]} :
iDATA_IN;

assign shift2ndDATA = (iSHIFT[1]) ?
{shift1stDATA[DATA_WIDTH-3:0],
shift1stDATA[DATA_WIDTH-1:DATA_WIDTH-2]} :
shift1stDATA;

assign oDATA_OUT = (iSHIFT[2]) ?
{shift2ndDATA[DATA_WIDTH-5:0],
shift2ndDATA[DATA_WIDTH-1:DATA_WIDTH-4]} :
shift2ndDATA;

つまり、

シフトのビット0で1回シフトするかどうかを判断、

シフトのビット1で2回シフトするかどうかを判断、

シフトのビット2で4回シフトするかどうかを判断、

以上をカスケードに接続してバレルシフトが完了という感じです。

しかし、このように合成してくれるかどうかはツール次第なので
心配だったら後者の記述を直接書いてもいいと思います。

再利用性を考えると前者の方が楽ですね。

火曜日, 7月 17, 2007

バレルシフト その1

食わず嫌いはいけないなと思って、最近はソフトウェア関係の書籍も意識的に読むように心がけています。

その中で"配列の要素の回転"というものがあって、例えば次のような配列があった場合

abcdefgh

これを3要素回転させると結果は

defghabc

となります。

ソフトの場合、エレガントなアルゴリズムがあって
i要素分回転させたい場合、まず配列をはじめのi個と残りのn-i個にわけます。

abc, defgh

次に分割したそれぞれにおいて、要素の並びを逆転します。

cba, hgfed

分割した配列を再び1つにまとめて、

cbahgfed

最後にこの配列全部の並びを逆転させます。

defghabc

すると、見事回転が完成しているというもの。


私のような凡人にとってはこれでちゃんとできているという事実だけでもスゴイと思ってしまうのですが
実行時間やメモリの消費量及びコードのシンプルさという観点からもこのアルゴリズムは優れているとの事です。

で、これをハードウェアにそのまま応用できるか?
というとそううまく行かないのが悲しいところです。

このような操作は、ハードでは"バレルシフタ"と呼ばれるものに相当します。

次回はHDLによるバレルシフタの記述と実装について書いてみたいと思います。

金曜日, 7月 13, 2007

サクッと書いてサクッと検証?

「サクッと書いてサクッと検証」,富士通九州が米Cadenceの形式検証を評価

Tech-On!の記事より。

現場の人が本当にそう思っているかどうかはちょっと疑問ですが。

この自動チェック機能は設計者に評判がよく,リピータが出たほどと由利氏は述べた。
一方で,プロパティを書くことには,大半の設計者が難色を示していると同氏は述べている。

実際のところこのあたりがネックになってくるんだろう。

設計者をどのように教育していくか?

最終的には自分を助けることにもつながるので、プロパティ記述は設計者も積極的に取り入れたほうが良いと思う。
取り入れることができる環境にあるならばの話だけど。

ただ、状態爆発を起こさないレベルの大きさのモジュール単位でフォーマル検証を使って確実に抑えておくという考え方は確かに正しい。

発見される問題は突き詰めてみると単一のモジュールで閉じてしまっているということがほとんどだからだ。

そこさえ押さえておけば、あとはインタフェースを標準化(規格でもいいし、社内独自のものでもいいだろう)することで生産性はかなり上がると思う。

フォーマル検証が使えなくても、数百行程度のモジュールレベルのRTLであればそれほど時間をかけずに徹底的に動的な検証することもできるだろう。

ただし、設計段階で各モジュールに的確な機能分けを行なって、モジュール間の依存関係をできるだけ小さくしておかないと上記の方法もあまり意味が無くなってしまう。

デザインによって、検証労力も雲泥の差が出てくる。

水曜日, 7月 11, 2007

Code Complete 第2版

Code Complete 第2版 上 ― 完全なプログラミングを目指して

Code Complete 第2版 下 ― 完全なプログラミングを目指して

@ITのプレビュー

ソフトウェアのコンストラクション(詳細設計からコーディング、開発者によるテスト・デバッグあたり)に焦点を当てた内容。

豊富な知識と経験に基づいた実践的な内容となっているので、明日使えるものばかりですね。

ソフトウェア技術者向けに書かれていますが、もちろんHDLを主体とするハードウェア技術者にもほとんどあてはまります。

上下巻でかなりのボリュームですが、文章は読みやすいので苦にはならないと思います。
それでもやはり、全て読むのには時間がかかりますが。

"言語の中へのプログラミング"という考え方はちょっと新鮮でした。

「この言語(環境)は不便だ」とあきらめるのではなく、自分の工夫によって状況を改善する。
確かにそれほど難しいわけでもなく、有益な方法だ。

"コンストラクション"に焦点を当てた書籍というのはあまり見かけないので、1度目を通してはいかがでしょうか?

しかし、なんで車の代表が「ポンティアック」なんだろう?

金曜日, 7月 06, 2007

フリーのコードカバレッジツール

Covered

フリー(GPL)のコードカバレッジツールです。
verilogのみ対応。

cygwinにインストールしてみたのでそのメモ。

必要なもの


  • gcc (Version 2.96 or higher)
  • flex (Version 2.5.4 or higher)
  • bison (Version 1.28 or higher)
  • GNU make (Version 3.27.1 or higher)
  • GNU gperf (Version 2.7.2 or higher)
  • tcl and tk (Versions 8.4 or higher) <-この場合は必要ないかも

"covered-0.5.tar.gz"をダウンロードしてきて、以下を実行。
$ gzip -dc covered-0.5.tar.gz | tar xvf -
・・・
$ cd covered-0.5
$ ./configure
・・・
$ make
・・・
$ make install
・・・

以上


サンプルを作って テスト。
適当な場所に展開して、展開後のディレクトリをカレントとしてください。
(VCDファイルはModelSimXEで作成)
$ covered score -t top -v top.v -v decimal_counter.v -vcd top.vcd

Covered covered-0.5 -- Verilog Code Coverage Utility
Written by Trevor Williams (trevorw@charter.net)
Freely distributable under the GPL license

Reading design...
Parsing file 'top.v'
Parsing file 'top.v'
Parsing file 'decimal_counter.v'

Checking for race conditions...

Scoring VCD dumpfile top.vcd...

*** Scoring completed successfully! ***

Dynamic memory allocated: 53710 bytes


$ covered report -d v -m ltcfram -o coverage.rpt cov.cdd

Covered covered-0.5 -- Verilog Code Coverage Utility
Written by Trevor Williams (trevorw@charter.net)
Freely distributable under the GPL license

以上
カレントディレクトリにできた"coverage.rpt"がレポートファイル。
一応、無事に動作している模様。

ただ、"COMBINATIONAL LOGIC COVERAGE RESULTS"で指摘されている部分がなぜ指摘されているか不明。

マニュアルはここ です。

VPIを使ってシミュレーションを実行しながらカバレッジ情報を見たり、GUIでインタラクティブに結果を閲覧したりといったこともできるようですが、上記のインストールでは多分できません。

詳しくはマニュアルをご覧ください。

木曜日, 7月 05, 2007

SystemCのインストール

これから少しずつSystemCの勉強もしてみようかと思い、cygwinにインストールしてみたのでそのメモ。

本当はLinux(OpenSUSE 10.2)に入れようかと思ったのだけれども、うまくいかなかったので。

gccのバージョンが悪かったのだろうか?

ちなみにcygwinのgccは3.4.4だった。

まず、OSCI からsystemc-2.1.v1.tgzをダウンロードする。

適当なディレクトリで以下のコマンドを実行。


$ tar xvzf systemc-2.1.v1.tgz

・・・

$ cd systemc-2.1.v1

$ mkdir objdir

$ cd objdir

$ mkdir /usr/local/systemc-2.1

$ export CXX=g++

$ ../configure --prefix=/usr/local/systemc-2.1

・・・

$ make pthreads

・・・

$ make install

・・・


以上。


実行するには以下のコマンド

$ export SYSTEMC=/usr/local/systemc-2.1
$ g++ -I. -I$SYSTEMC/include -L. -L$SYSTEMC/lib-cygwin -o sim hello.cpp -lsystemc -lm
$ ./sim

"Hello World."が表示されればOK。

サンプルのプログラムはこちらのサイトのものを使わせていただきました。

*$make の部分を $make pthreads に修正しました。
 なつたんさんのブログを参照

水曜日, 7月 04, 2007

リセットの論理を切り替える方法

会社によって、またはプロジェクトによってリセットの論理は正論理か負論理に分かれます。

モジュールの再利用性を考えると不便ですよね。

そこで次のような方法をとりましょう。

`define RESET_EDGE posedge
`define RESET_ON 1'b1

always @(posedge clk or `RESET_EDGE reset) begin
if (reset==`RESET_ON)
Q <= 1'b0;
else
Q <= D;
end

これが正論理の場合。

負論理に変更したい場合は、

`define RESET_EDGE negedge
`define RESET_ON 1'b0


とする。

もちろん、プロジェクト内でリセットの論理が統一されていることが前提です。

火曜日, 7月 03, 2007

Verilog Mode

エディタは何をお使いですか?

ソフトの言語に比べてHDLに対応しているエディタって少ないですよね。

私は普段Windows上で作業をしていますが、エディタはMeadowを使っています。

これは以前、VHDLをメインで使っていたときにEmacsだとデフォルトでvhdl-modeが付いていたのでそれがきっかけで使い始めました。

Verilogに対応するverilog-modeは標準では付いていませんが、こちらから入手できます。

インデントやカラーリングだけでも便利ですが、/*AUTOARG*/などで自動的にポートを挿入してくれる機能などは面倒な作業を削減してくれます。

インストール方法と使い方は以下のサイトが詳しいです。

Verilog modeのインストール

Verilog modeの機能

良い道具を選択するのもエンジニアの能力のひとつです。
楽できるところは積極的に楽をしましょう。

数年前にいた会社では、Windowsのメモ帳でAHDL(Altera Hardware Description Language)を書いていた人がいましたorz

木曜日, 6月 28, 2007

blocking代入とnonblocking代入

verilogのblocking代入とnonblocking代入は論理合成対象のRTL記述であれば
順序回路にはnonblocking、組み合わせ回路にはblockingと憶えておけば特に問題はありません。

しかし、シミュレーション記述の場合はその違いをちゃんと理解しておかないと思わぬところで痛い目にあうかもしれません。

ちなみになぜblocking,nonblockingというかご存知でしょうか?

blocking代入はその名のとおり、その代入文が完了するまでステートメントをブロックします。

対して、nonblocking代入の場合は代入のスケジューリングのみが行なわれて、遅延0で次の処理に移ります。


したがって、次のようなコードの場合(blk_nblk.v)、



a,b,cへの代入が行なわれるのはそれぞれ時刻20,50(=20+30),60(=20+30+10)となりますが
x,y,zへの代入が行なわれるのはそれぞれ時刻20,30,10となります。

この結果がどうなるのかというと、

# (a,b,c) = ( 5, 15, 10)
# (x,y,z) = ( 5, 10, 5)


どうですか?
予想と一致していたでしょうか?

特に注意するのはnonblockingの場合ですが、yとzへの代入はそれぞれ時刻30及び10に行なわれますが代入されるxの値は、式が評価された時刻(つまり時刻0)のものが使用されます。

ややこしいですね。

ちなみに波形はこんな感じになります。


水曜日, 6月 27, 2007

アサーションベース設計 原書2版

アサーションベース設計 原書2版

アサーションの有用性や適用方法などについて。
機能カバレッジについてもふれられています。

使用してあるのは、OVLやPSL,SystemVerilogなのでEDAツールに依存しない形で解説されています。

一見固そうですが意外と読みやすかったです。

はじめのほうにHPやIntelなど有名な企業での成功事例が載っているので、同僚や上司を説得するには良いかもしれません。

大規模化を続けるLSIの機能検証はもはやブラックボックスでは成り立ちません。

アサーションやカバレッジを利用して、設計担当者も設計・コーディングの段階から積極的に検証に協力していきましょう。

火曜日, 6月 26, 2007

[OVLチェッカー] ovl_never

ovl_neverは評価式が常に真ではないことを保証します。

ovl_never check_overflow (clock, reset, enable, (count>9), fire);

このように書くと、countの値が10以上になったときにassertionがfailとなり、メッセージが出力されます。

また、assertionがfailとなったサイクルでは、fire[0]が真(1)にセットされます。
これはその他のチェッカーも同様です。

デフォルトでは、評価式(test_expr)が0で無い場合(1,x,z)にassertionがfailとなりますが
`OVL_XCHECK_OFFがセットされていると、評価式が1のときのみfailとなります。

月曜日, 6月 25, 2007

v2html

v2html - verilog to html converter -

その名のとおり、verilogソースをHTMLに変換してくれるPerlスクリプトです。

キーワードを色分けしてくれるだけでなく、階層構造や信号を追っていけるので他人のコードを解析したり、レビューの時などに使えそうですね。

WindowsのActive Perlでも使えるようです。

自分はcygwin上でやってみましたが、特に問題なく使えてます。
一応、スクリプトの1行目のパスがPerlのある場所と一致しているかどうか確認してください。

こんな感じになります。

日曜日, 6月 24, 2007

OpenSPARC

今まで知らなかったのですが、SunがSPARCのRTLを公開しているんですね。

OpenSPARC


ちょっとビックリしました。

ソースはこちらで見れますが、Verilog HDLです。

広大すぎて、これをまともに見ようとするとそれなりの覚悟が必要。

しかしこれほどのものが公開されてるなんて。

こういった流れで、ハードウェアもオープンな方向に向かってくれるといいですね。

土曜日, 6月 23, 2007

OVLの導入方法

↓こちらにOVLの導入方法を簡単にまとめてみました。

OVL(Open Verification Library)

参考まで。

木曜日, 6月 21, 2007

アサーションとカバレッジ

OVL v2.0では、各チェッカーにassertion(assumption)機能だけでなくカバレッジ機能が追加されているものがあります。

しかし、カバレッジ機能についてはまだ十分ではないようです。

チェッカーのアサーション機能はその規定に違反したときに起動して、違反があったことを通知しますがその機能を利用して、シミュレーションがカバレッジポイントを通過したかどうかを確認することもできます。

例えばovl_neverを使って、カバレッジポイントを通過したときに真となる式をtest_expr入力に入れておけば、シミュレーション中にカバレッジポイントを通過した時点でチェッカーが起動して、通知してくれます。

このとき、severity_levelパラメータはOVL_INFOとしておき、msg入力にカバレッジポイントであるということを明記しておきましょう。

例えばこんな感じですね。
ovl_never
#(.severity_level(`OVL_INFO), .property_type(/*default*/),
.msg("Coverage point: Count Max."), .coverage_level(`OVL_COVER_NONE),
.clock_edge(/*default*/),.reset_polarity(`OVL_ACTIVE_HIGH),
.gating_type(/*default*/) )
cov_cnt_max_inst (.clock(ICLK), .reset(IRST), .enable(1'b1),
.test_expr((COUT==4'd9)), .fire(OFIRE));

水曜日, 6月 20, 2007

[OVL パラメータ] gating_type

OVLチェッカーのパラメータ、gating_type について。

gating_typeenable入力に対する振る舞いを指定します。

設定値は以下の3つ。

OVL_GATE_NONE
enable
入力は無視されます。

OVL_GATE_CLOCK
enable入力がFALSEの時、チェッカーは動作を停止します。
具体的には、チェッカーへのクロック供給が停止します。
したがって、内部の状態は保持されます。

OVL_GATE_RESET
enable入力がFALSEの時、チェッカーはリセットされます。

火曜日, 6月 19, 2007

assertionとassumption

assertionはその処理が正しく行なわれることをあらわす概念で、あるモジュールにassertionが設定されているとき、そのモジュール内での処理においてassertionの規定に違反しないことが期待される。

assumptionは仮定・想定の意味で、あるモジュールにassumptionが設定されているとき、そのモジュールに対する入力がassumptionの規定に違反しないことが期待される。

つまり、assertion/assumptionが設定されている場合、assumptionに違反しない入力に対してassertionに違反しない動作をする必要がある。

OVLではproperty_type`OVL_ASSERTを設定することでassertionを示し、`OVL_ASSUMEを設定することでassumptionを示す。

月曜日, 6月 18, 2007

OVL v2.0

OVLは2007年5月からv2.0になりました。

Mentor社発行の『Verification Horizons』によれば、

  • 合成可能なイネーブル入力とファイヤー出力付き ovl_[checker_name] モジュール
  • アービタ、FIFO用などの新規の18個のアサーション
  • クロックエッジ、リセット及びイネーブルゲートの極性をプログラム可能
  • グローバルデフォルト制御用の新規のマクロ
  • 主要なOVLのVHDLでの提供

などが新しい要素のようです。

また、チェッカーの名前が以前の'assert_[checker_name]'から
新しく、'ovl_[checker_name]'に変更されています。

旧来からある33のOVLアサーションについては'ovl_[checker_name]'と'assert_[checker_name]'(機能は旧来のまま)の両方が使えるらしいですが、新規のデザインには'ovl_[checker_name]'アサーションの使用を推奨とのことです。

アサーションモジュールにイネーブル入力とファイヤー出力が付いたので、それらをつなぎ合わせてより複雑な条件のアサーションを構成したり、また、合成可能なのでFPGAでのプロトタイピング時などにアサーションを組み込んだまま実装することで、エミュレーション時にアサーションをモニタすることも可能になるということのようですね。

日曜日, 6月 17, 2007

抽象化 おまけ

抽象化でコードはより人間の使う言葉に近づくことを説明した。
が、残念ながらその言語はどうしても"英語"になってしまうだろう。

プログラミング言語が高級になるにつれて
英語ができないものは不利になっていくことを最近特に感じる。

英語がわからないとコードを読めなくなる。

ただでさえ、情報量は英語の方が圧倒的に多いのに。

これは日本人の技術者にとって非常にやばい方向へ向かってるのかもしれない。
「エンジニアの必須スキルとして、まず英語」というのが冗談ではなくなりそうだ。

情報処理技術者試験の科目にも入れたほうがいいかもね。

土曜日, 6月 16, 2007

抽象化 その2

Verilogではparameterを使って、固定値をパラメータ化することできる。

パラメータ化による利点の一つは、再利用性を高めることができることだがもうひとつの大きな利点は数値を抽象化できることだ。

次のような仕様があったとする。

2ビットの入力signalについて、
2'b00を赤、2'b01を黄色、2'b10を青と定義する。
また、2ビットの出力ctrlについて、
2'b11を停止、2'b10を注意、2'b01を進行と定義する。
signalが赤の時、 ctrlは停止を出力、
signalが黄色の時、ctrlは注意を出力、
signalが青の時、 ctrlは進行を出力をすること。

この仕様に対して、次のようなコードを書いたとしよう。
case (signal)
2'b00: ctrl = 2'b11;
2'b01: ctrl = 2'b10;
2'b10: ctrl = 2'b01;
default: ctrl = 2'b11;
endcase

一応これでも仕様を十分満足できる。
が、一度仕様を読んでこのコードを見てもそれが正しいかどうか理解するのに少し苦労するだろう。

次の場合はどうだろうか。

parameter Red = 2'b00;

parameter Yellow = 2'b01;
parameter Blue = 2'b10;

parameter Stop = 2'b11;
parameter Caution = 2'b10;
parameter Go = 2'b01;

・・・

case
(signal)
Red: ctrl = Stop;
Yellow: ctrl = Caution;
Blue: ctrl = Go;
defautl: ctrl = Stop;
endcase

パラメータの定義の部分は少し注意が必要だがコードの本体の部分を理解するのはこちらの方がずいぶん楽だろう。
具体的な数値がすでになくなっているので抽象度が上がり人間の言葉に近くなっているからだ。

このように、同じ機能を実現するコードでも
抽象化することによって、ミスを減少したり、メンテナンス性向上させることができる。

ハードウェアではより低レベルでの効率化のため、各ビットに意味をもたせる場合が多くそのため、現在でもまだあまり抽象化されていないコードをよく見かけることがある。
例えば、先のsignalの定義で言えばbit1を見るだけでそれが青かどうか判断できるため、次のコードの方が良いと思う人も多いかもしれない。

if
(signal[1]) ctrl = 2'b01;
else begin
if (signal[0]) ctrl = 2'b10;
else ctrl = 2'b11;
end

しかし、EDAツールやチップの性能が向上してきている現在では、よりメンテナンス性の良い方法を選択した方が今後はよりしあわせになれるのではないだろうか?

抽象化 その1

コンピュータは全てのことを0と1だけで表現している。
いわゆる2進数というヤツ。

でも、いくらスーパーなエンジニアでも0と1だけで全てを把握するのは無理なので
16進数をつかったりして表現する。

0と1が8個並んでいるよりも、0~Fまでの値が2個並んでいる方がよほど楽だ。

最も、普通の人なら0~9までの数字が3個並んでいる方が理解しやすいが
人間の適応能力というのは大したもので、我々の業界では
32や64、256などの数字(16進数でそれぞれ0x20,0x40,0x100)を
「キリが良い」と感じてしまう重大な職業病が蔓延している。

16進数の方が2進数よりも扱いやすいのは、
まず第1に頭の中で処理をする数字の量が減ること
そしてもうひとつは値をある程度『記号』として意味をもたせることができるからだろう。

これも1つの抽象化だ。

抽象化は設計や検証のさまざまな場面で恩恵を与えてくれる。
なぜなら、抽象化されたものの方が人間が理解しやすいからである。

例えば次の2進数の数値をあなたは1週間後に憶えていられるだろうか?

1100101011111110.b

何の意味もない値を憶えておくことはかなり困難だ。
では、次の16進数の値ならどうだろう?

0xCAFE

これなら1週間後どころか1年、もしかすると一生憶えているかもしれない。
上の2つの数値は同じ値である。つまり、

1100101011111110.b = 0xCAFE

かなり極端な例だが、抽象化することで同じ値でもかなり扱いやすくなる。

ミスを減らしたり、理解を深めたり
この抽象化という概念はさまざまな場所であなたの味方になってくれる。

金曜日, 6月 15, 2007

ALDECのウェブセミナー

ALDECのサイトでOVLのウェブセミナーを公開しています。

ALDEC Verification Methodology Seminars (AVMS)

OVL以外にもいろいろとあります。

日本語版もあればうれしいのですが残念ながら英語のみです。

LSIの分野も設計に関する情報は少しづつ日本語でも手に入れられるようになってきましたが検証方面に関してはほとんどありませんね。

自分も英語は得意なほうじゃないので悲しいです。

日本にも有力なEDAベンダーが出てくればなぁ。

結局大元は向こうに握られてる感じですよね。