FC2カウンター FPGAの部屋 2009年10月
fc2ブログ

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

HDLのソースの行数

前々から、自分で書いたHDLソースの行数を知りたいと思っていました。
ネットで検索してみたところコロ助というソフトで各ソースファイルの行数を簡単に取得できることがわかりました。
言語の種類ごとにカウントできるので、起動してから他の言語のチェックはすべてはずして、VHDLとVerilogは最初から用意されていなかったので、自分で追加しました。
korosuke_1_091031.png

VHDLの設定は
korosuke_2_091031.png

Verilogの設定は
korosuke_3_091031.png

これで、このブログでダウンロード出来るソースを試してみます。
CMOSカメラから白黒ディスプレイ表示回路 (CamDispCntrl_SRAMp_091023.zip) は、全部で1419行でした。有効行は1169行です
korosuke_4_091031.png

Spartan3A Starter Kit のDDR2 SRAMコントローラのバーストテスト (Spa3A_STKit_ddr2_burst_test_090821.ZIP) は3388行、有効行が2820行。やはりcontroller.v が一番多くて995行。
SuzakuV_DDR2_test (SuzakuV_DDR2_test_080823.ZIP) は、3884行。有効行は2952行。
Spartan3E Starter Kit のDDR SDRAMバーストテスト (DDR_burst_test_verilog_080404.ZIP) は、2192行、有効行は1861行でした。

ちなみにお仕事の大きな基板のVHDLソース行数は3万7千行程度。PCIの基板の方は3万5千行程度でした。
今作りかけのPCI-X基板のVHDLソースは半分くらいの出来で2万5千行程度です。

  1. 2009年10月31日 04:58 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

今日届いたもの

システムクランプバー 92cm。丸のこで真っすぐ切れるように購入。92cmあると、コンパネやベニヤを縦に切れる。

覇権の標的。元半導体技術者の方が書いているサスペンス小説。mixiで知っておもしろそうだと思ったので購入。古本です。

先週届いた本。数学ガール、ゲーデルの不完全性定理。まだ少ししか読んでいない。
  1. 2009年10月28日 21:07 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

画像のエッジ検出2(方式の検討)

CMOSカメラからの画像データからエッジを検出してみようということになったので、方式を考えている。
8bits X 2KWORDのBRAMを使って、CMOSカメラからのY(輝度)データを保存する。保存しながら2エントリのシフトレジスタに入力しながら、横方向に比較する。1水平ライン分BRAMにたまったら、今度はCMOSカメラからのY(輝度)データを前のデータと比較し、さらにBRAMから出力した1水平ライン前の2つのデータと比較する(下図参照)。比較して、1つでもスレッショルド値を超えていたら、ある値をSRAMに書き込み、そうでなければオール0を書き込む。スレッショルド値を超えた時の値はオール1ではコントラストが強すぎるかな?とりあえず半分の0x80 を書いておくことにしよう。

edge_detect_1_091028.png

最初のビットは比較できないし、比較できるときにはデータとは他にValidビットを用意して、Validビットが双方立っていないとその方向の比較は無視するようにする。
後はどのモジュールで比較を担当するかだが、CAMERA_CONTROLLERモジュールにcompareサブモジュールを作る感じで行こうと思う。

BRAMのWRITE_MODEはREAD_FIRSTモードにしておいた方が良いとSpartan3のユーザーズマニュアルに書いてあった。今回は前の水平ラインのデータを読み出しながら今の水平ラインのデータを書くので、WriteモードとReadモードにアドレスのコンフリクトが生じる可能性がありそうだ。BRAMは2Kバイトあるので、1Kバイトずつ使って、ダブルバッファリングしようかな?それならば、アドレスのコンフリクトは生じない。

ユーザーズマニュアルを読んでいるといろいろ発見があって面白い。Spartan3AのBRAMでは、 RAMB16BWERプリミティブがあって、それを使うとバイトイネーブルが付いているそうだ。512X36bits 構成ではWE0~3まであって、9ビットごとに書き込むレーンを決められる。これだと、今まで、バイトイネーブルが欲しいために、2KX9bits のBRAMを4個並べていた構成で、メモリ容量がいらなければ512X36bits 構成にすることができる。

”1つのブロックRAMを使用した256x72シングルポー トRAM”の例があった。”メモリアレイ を半分に分割 し、一方に下位 36ビッ ト 、も う 一方に上位 36 ビット を保存することによ り 、 72 ビット幅のメ モ リを作成します。”そうか、これは気がつかなかった。覚えておくことにする。
  1. 2009年10月28日 20:14 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

画像のエッジ検出1

さて、”CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!)”でCMOSカメラからの映像をディスプレイに映すことができたので、今度はそのデータを使って、ハードウェアでエッジの検出をしてみようと思う。
YUVを受け取ってRGBに変換してみると言うのも面白いし、考えてみれば、Spartan3Eの掛け算器を一度も使ったことがなかった。エッジ検出の後で一度使ってみたい。
さて、画像のエッジ検出となると、2X2ピクセルを切り取って、縦横斜めを引き算して、一定のスレッショルド値を決めてそれを超えていたらそのドットを明るくする。それ以外のドットは暗くする。このようなアルゴリズムで大丈夫かな?
まず、最初は1ライン分のY(輝度)データを取りながら、横方向の演算をする。2回目以降は横方向の演算もしながら、縦方向、斜め方向の演算も一緒にする。複数の方向からそのビットがエッジだという演算結果が出ても、同様にそのドットを明るくする。つまりORということ。
1ライン分のYデータはBRAMを1ライン分用意して、そこに格納することにする。
この、ボードには切り替えようのスイッチがないので、3秒ごとに正常の白黒画像、エッジ検出画像を切り替えることにする。
  1. 2009年10月27日 05:26 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:2

引き出し製作1

今日はテレビ台用の引き出しを途中まで作った。
1X8材をスライド丸のこで切って、片方を手動カンナ盤でかんながけ。その後、トリマーに4mm のストレートビットを付けて、引き出しの底板(4mm のシナべニア)を付ける溝を掘った。だけども、4mm のストレートビットということで買ってきたのだが、ノギスで測ってみるとビットの直径は3.3mm で実際に掘った溝は3.5mm だった。もう一度0.6mm 程度、ずらして掘ったのだが、この加減が難しかった。溝の幅が5mm程度になって、がばがばになってしまった。あるのだったら5mm のストレートビットを買うべきだったのかな?
ちなみに溝の深さは5mm。溝を彫り終わったら、引き出しの高さに合わせるために、丸のこにT字型のアダプタを付けて、真っすぐにひき割った。
その後、手動カンナ盤で板の幅を調整。
底板を丸のこで切断して、木工用ボンドを付けて、箱になるように接着した。はたがねがないので、密着するように隠し釘を打って固定。隠し釘は打った後で頭を払うと頭が取れて、目立たなくなる釘だ。これで、明日まで固定すればOKのはず?今のところうまくいっていると思うが微妙(0.5mm程度)にくるっている感じ。大きさは447X354X164mm。
hikidashi_1_091025.jpg

hikidashi_2_091025.jpg

hikidashi_3_091025.jpg
  1. 2009年10月25日 18:02 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:0

パイクとぶつかりそうになりました

今日、イーアスに行った帰り、ちょうど沼崎の部落の中を走っているときに、突然反対車線のバイクが正面から向かってきました。このままでは正面衝突。大いにあせりました。瞬間でしたが少し右にハンドルを切ってフルブレーキ。あまり右に逃げてもバイクが自分の車線に戻って避けようとしたときに、ぶつかってしまうかもしれません。バイクは制御不能の状態のようでした。一瞬でしたが、なんとか私の車の左ぎりぎりをかすめて、後ろでこけました。本当に危ないところで、近くにはコンクリートの電柱もありました。運よく、畑に自爆した様子。
車が止まったので、降りて見に行きました。大丈夫か?と声をかけると、あせった様子で立ち上がりました。どこかけががないかと聞いたところ、大丈夫とのこと。。。ライダースーツに身を包んでいましたし、突っ込んだところが畑なので、大丈夫そうでした。怪我もなさそうです。こちらにしきりに謝っていましたが、原因を聞くと、直進していたのだが、脇から急に車が出てきて、その車を避けるのにコントロール不能になったそうです。その車は私は気がつきませんでしたが、バイクがハイサイド気味になったのでしょうか?結構コントロール不能の状態のようでした。
バイクの方は謝ってくれましたし、怪我もしていないようでした。また、車にも被害がないことから、そのまま別れました。
本当に良かったです。正面からバイクが衝突したら、バイクの人はたぶん大怪我か即死。こちらもただでは済まないところでした。本当に良かった~。皆様もお気を付けください。
  1. 2009年10月24日 20:55 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:6

CMOSカメラから画像を入力してディスプレイへ出力16(VHDLソースを公開)

CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!)”でCMOSカメラ・ディスプレイ回路が出来たので、ソースを公開します。いつものように、保証はありません。商用不可、転載はご相談くださいということでお願いします。
イーエスピー企画が出している。画像ベースボード、デジタルCMOSカメラ、208ピンSpartan3E XC3S500+2M高速SRAM基板を使って、カメラで撮影した画像をアナログRGBディスプレイに白黒で表示する回路です。なぜ白黒かというとそれが依頼者の仕様だからです。詳しくは”画像処理”を参照ください。
VHDLソースをここに置いておきますので、興味のある方はダウンロードしてください。何かバグを見つけたら、お知らせください。よろしくお願いします。

これからは秘密の部分を作るので公開できないが、ブランチして、ブログの方ではDWMでやっていたYUVからRGBへの変換をやってみようかと思う。つまり白黒からカラーにする。しばらくVerilogを書いていないし、Verilogに書き直してからにしようかな?SDカードインターフェースも良いな。

音声の方も再挑戦したいので、ΔΣ変調も勉強しようと思っています。勉強に良いWebサイトや本があったら教えてください。
  1. 2009年10月23日 05:17 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:2

Spartan-6 FPGA SP605 Evaluation Kit

今日、たまたまXilinx社のSpartan-6の開発ボードのページを見ていたら、Spartan-6 FPGA SP605 Evaluation Kit が載っていました。ここに写真があります
DDR3 Component Memory 1Gb、光モジュール用のコネクタ、DVIコネクタ(VGAも出るようです)、PCI Express x1 Edge Connector、10/100/1000 Tri-Speed Ethernetがついています。
16x2 LCD character display も付いていると書いてあるけど、ついてるようには見えませんが、コネクタのところにつくのかな?
$495だそうです。
  1. 2009年10月22日 18:02 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:6

ISE11.3でのプロジェクトの絶対パス問題?

CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!)”をやっているときに、ChipScope Analyzer でコンフィグして動作した.bit ファイルをiMPACT でコンフィグすると動作しないという問題に遭遇した。ISEのバージョンは11.3。
非常に悩んだが、どうやらプロジェクトのパスが違っていて、違ったHDDに結果が書き込まれていることが分かった。家でやっていたプロジェクトを職場に持っていたのだが、家ではHドライブに作ってあったが、職場ではCドライブにコピーした。CamDispCntrl_SRAMフォルダの下にSource、Simulation、Synth113の各フォルダがあって、Synth113フォルダがISEのプロジェクトが置いてあるフォルダだ。当然、職場のCドライブのSynth113フォルダの下のISEのプロジェクトを起動してインプリメントしていた。
Camera_Disp_31_091021.png

当然、iMPACTでは、CドライブのCamDispCntrl_SRAMフォルダの下のSynth113フォルダの中にあるcamdispcntrl_sram.bit を選んでコンフィグしていたのだが、どうも動作しない。ChipScope のコンフィグはISE11からProject Navigator から起動するとコンフィグ時に自動的にビットファイルを選んでくれる。そのビットファイルのパスを良く見ると、HドライブのCamDispCntrl_SRAMフォルダの下のSynth113フォルダにパスが通っていた。え~、もしかして、iMPACTでコンフィグできないのはこれが原因?Hドライブを見るとCamDispCntrl_SRAMフォルダの下のSynth113フォルダだけが生成されていた。
Camera_Disp_32_091021.png

この、Hドライブの下のCamDispCntrl_SRAMフォルダの下のSynth113フォルダのビットファイルをiMPACTでコンフィグすると問題なく動作した。ということは、ISE11.3では、プロジェクトのパスは絶対パスで持っているのだろうか?Project Navigator でフルパスにはしていないのだけど。。。これは注意する必要がある。フォルダごとプロジェクトをコピーして、確実に動くプロジェクトを残しながら、違う試みを試してみることは良くやっているからだ。コピー元のプロジェクトフォルダに変更が反映されては困ったことになる。

皆さんのところでも同じような現象が起きたことがありますか?
  1. 2009年10月22日 04:30 |
  2. Xilinx ISEについて
  3. | トラックバック:0
  4. | コメント:2

CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!)

CMOSカメラから画像を入力してディスプレイへ出力14(CMOSカメラの出力が出た!)”で最後に書いた修正を施したがやはり、表示はあまり変わらなかった。
ChipScopeで見たら、シミュレーションと同様に、master_sync が出た1クロック後に、n_mem_rd は0になったので、この部分のバグは修正されている。
Camera_Disp_30_091021.png

その後、VGAのアドレスカウンタのバグを発見。これを修正後、画像が見えたが、なんかノイジーだ。
Camera_Disp_33_091022.jpg

どこかおかしいのかと思って、ChipScopeで各種信号を見たり(一番上の図)をしていたのだが、上のChipScopeを仕掛けたときにノイジーなのが直ってしまった。(その後、ChipScopeを抜いても大丈夫になりました。制約とかは追加したのですが、それで直ったとも思えないのですが?)
Camera_Disp_34_091022.jpg

ちょっと割り切れないところがあるが、一応完成!!!(初めから画像は白黒の予定です)
しかし、今のところCMOSカメラにクロックを供給するDCMをX0Y0の位置に固定しておかないとクロックが消えてしまうようだ。これも謎?Spartan3Eが不良なのだろうか?
それに、”ISE11.3でのプロジェクトの絶対パス問題?”の現象にも悩まされた。この現象があるし、それにボードを持っていないと思うし、後でシミュレーション用にソースファイルを公開しようと思う。
  1. 2009年10月22日 04:02 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:2

CMOSカメラから画像を入力してディスプレイへ出力14(CMOSカメラの出力が出た!)

CMOSカメラから画像を入力してディスプレイへ出力13(もしかしたらRESETはアクティブハイ?)”でCMOSカメラのRESETはアクティブハイのようなので、CMOSカメラのRESETを0固定にしてみた。

 n_cam_reset <= '0'; -- OV7640のRESETはアクティブハイ

としたら、CMOSカメラから出力が出てきた。うれしかった!
Camera_Disp_25_091020.png

HREFやデータが出ている。正常に動いているようだ。単にリセットしなければ良かったのか?
VSYNCの後の最初にHREFが1になって、master_sync が1の時を拡大したの下の図。
Camera_Disp_26_091020.png

それらしくデータが出ている。cam_ydata_2d の3B, 3D, 3D, 3F... のデータがYデータのようだ。これでもしかしてうまくいっているかな?と思ってVGAディスプレイをつないでみたが、かなりおかしい画像だった。それでもCMOSカメラの画像という雰囲気はある。
Camera_Disp_28_091020.jpg

同期信号はOKだがデータがおかしいような表示だ。まだどこかがおかしい。
ChipScopeにメモリ関係の信号を入れて取りなおしてみた。(下の図)
Camera_Disp_27_091020.png

なかなか良さそうだ。シミュレーションと比べてみると、下にシミュレーションの図を示す。
Camera_Disp_29_091021.png

ピンクの楕円で囲ったmaster_sync が出た1クロック後に、黄色の楕円で囲ったn_mem_rd は0になっている。しかし、1つ前のChipScopeの図ではmaster_sync が出た後のn_mem_rd_OBUF(下から2番目の信号)の値は1である。ここがおかしい。このChipScopeでの結果ではSRAMのデータとFPGAからの書き込みデータがぶつかってしまう。なぜに、シミュレーションと実機の動作が違うのか?
ここでChisScopeで作ったVCDファイルを持ってきておけば、”Veritak3.69C以降におけるModelSimのVHDLシミュレーションとChipScopeの協調検証”でやったようにVeritakを使用して比較できたのだが。。。
VHDLソースを見てみることにした。n_mem_rdがおかしいので、そのコードを見てみる。CamDispCntrl_SRAM.vhdで、下のように書いてある。

 n_mem_rd <= not r_w;


r_w 信号は、synchronizer.vhd が出力している。下にソースを示す。

    -- その他のモジュールの動作は1クロック遅れるので、最初はwrite_stateとなる
    process(cs_rw, cs_sync, cam_href_1d) begin
        case cs_rw is
            when idle_rw =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= write_state;
                else
                    ns_rw <= idle_rw;
                end if;
            when read_state =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= read_state;
                else
                    ns_rw <= write_state;
                end if;
            when write_state =>
                r_w_node <= '0';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= read_state;
                else
                    ns_rw <= read_state;
                end if;
        end case;
    end process;
    r_w <= r_w_node;


上のソースで、”if cs_sync=vsync_deassert and cam_href_1d='1' then”はmaster_sync が1になる条件だ。idle_rw ステートに初期化時にいるから、最初にmaster_sync が出るとwrite_state に遷移する。その後はwrite_state, read_state を交互に遷移する。その後、master_sync が出たらread_state に遷移してしまう。これじゃおかしい。
シミュレーションは初期状態を示していて、ChipScopeはそれより後の状態を示している。シミュレーションでそれを確認するためには35ms 程度シミュレーションする必要があるので大変だ。このようにクロック周期と実際の動作のタイムスケールが相当異なる回路ではシミュレーションによる確認が難しい場合がある。
上のソースを下のように修正した。

    -- その他のモジュールの動作は1クロック遅れるので、最初はwrite_stateとなる
    process(cs_rw, cs_sync, cam_href_1d) begin
        case cs_rw is
            when idle_rw =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= write_state;
                else
                    ns_rw <= idle_rw;
                end if;
            when read_state =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= write_state;
                else
                    ns_rw <= write_state;
                end if;
            when write_state =>
                r_w_node <= '0';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= write_state;
                else
                    ns_rw <= read_state;
                end if;
        end case;
    end process;
    r_w <= r_w_node;


これでやってみる。たぶん直っていると思う。
  1. 2009年10月21日 04:32 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

CMOSカメラから画像を入力してディスプレイへ出力13(もしかしたらRESETはアクティブハイ?)

CMOSカメラ・ディスプレイ回路は、仕事の合間にやってい見ているが、なかなかうまくいかない。でもどうやらCMOSカメラのRESETを100ms 以上入れるとCamDispCntrl_SRAM.vhd のr_w 信号がトグルすることが分かった(ソースコードはここ参照)。これはCMOSカメラからのPCLKがきちんと来ていてステートマシンが正常に動作していることを表している。しかし、HREF、VSYNCが来ていない。
試しに、”DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示”にチップスコープを入れると正常にHREF、VSYNCが来ている。
これは"DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示"の回路をシミュレーションしてみる必要がある。とりあえず、メモリモデルやCMOSカメラモデルを付けていない状態のシミュレーションモデルがあったので、これでシミュレーションしてみることにする。(CMOSカメラのRESETの状態が見えれば良い)
Camera_Disp_21_091020.png

上の図はModelSimのwaveウインドウだが、ハイライトされているrstb がCMOSカメラのRESET入力に入っている。ということはRESETはアクティブハイ?今までアクティブローだと思っていた(Webで拾ってきたマニュアルにはその辺が書かれていない)。確かにVHDLコード見ても、H2プロセッサから書かれることになっているが、初期値では0にイニシャライズされている。私の”DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示”のプロジェクトではH2プロセッサを取って、CMOSカメラのコントロール用のI2Cインターフェースへのコマンドはステートマシンモジュールを付けくわえていた。そのモジュールはCMOSカメラのRESET関係は設定しないので、当然と言えば当然か。
今まで、CMOSカメラのRESETの論理を反転したこともあったが、その時はDCMのLOCKEDの反転を入れていたので、リセット時間が足りなくて正常動作しなかったということも考えられるかな?
とにかくCMOSカメラのRESETは0固定で試してみることにする。それでも正常にCMOSカメラからHREF、VSYNCが出てこなければ、I2Cインターフェースを付けて、CMOSカメラのSCCBレジスタの12番地に0x80 を書いて、SCCBレジスタをリセットする必要があるかもしれない。

#やはり、どこがどうして悪いかわからないときに、曲がりなりにも動作する回路があるということが、本当にありがたい。少なくとも基板やCMOSカメラが決定的に壊れているということはないのだから。。。
  1. 2009年10月20日 05:35 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新 (2009/10/18)

FPGAの部屋のまとめサイトを更新しました。

”Constraints Editor、SOPC Builder、Nios2 EDS、画像処理、CADツールについて”の項目を追加しました。
”Spartan3A Starter Kit、Xilinx ISEについて、VHDLの書き方、シミュレーション”の項目を更新しました。
  1. 2009年10月18日 17:57 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

トイレの棚

今日はトイレの棚を作った。昨日買ってきた木のL字アングルがなかなか良い!
tana_091018.jpg

満足の行く出来なのだが、奥さんの要望は棚を天井から23cmの位置に取り付けることだったのだが、板厚の換算を忘れて、板厚分(19mm) 天井に近くなってしまったのは内緒である。

今日はウッドデッキ用の防腐剤塗布2X4材8Fの値段を見てきた。石下のホームジョイ本田は1本650円だったが、グランステージは520円だった。普通の2X4材6Fもホームジョイ本田は320円だが、グランステージは238円で安い。
  1. 2009年10月18日 17:43 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:6

棚の製作、雑記

今日は1X8材12Fを使って、机の上に置く棚を作った。900X885X183mm。
tana_091017.jpg

グランステージでトイレに棚を作るために、1X6材6Fと木のLアングル3個を買ってきた。明日、トイレに棚を作るつもり。
庭にウッドデッキを作るために木材を見てきたが、良さそうな土台があった。写真を撮ってくるのを忘れたが、これを使うと簡単そう。ウッドデッキの材料は防腐剤処理済みの2X4材12Fの予定。

CMOSカメラ・ディスプレイ表示は、実機でのデバックなので職場でやる必要がある。他の仕事が忙しいので、なかなかやる暇がない。以前動作したもののシミュレーションをしてみようと思ったが、プロジェクトは職場なので出来ない。残念。次に家でこのブログを書きながらやるのは何にしようか?思案中。

そういえば、Spartan3A Starter Kit のDDR2 SDRAMコントローラのことを技術論文としてまとめておこうと思う。3月くらいに発表する。CMOSカメラ・ディスプレイ表示もうまく行ったら3月くらいに発表しようと思う。

#FPGAのことを書いてあるブログが少ないのはなぜ? やはり、皆さん、お仕事で外に漏らせないからですかね?
  1. 2009年10月17日 18:05 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:4

Embedded Technology 2009

今日、Embedded Technology 2009に登録しました。
FPGAカンファレンス2009東京には急な仕事が入ったため行けなかったので、11/19(木)に行こうと思っています。
FPGAのカンファレンス無料セッションにも、興味のありそうな項目があります。特に、”16:00-16:45 FP-6 FPGAの部分再構成の活用開発事例”は聞いてみたいと思っています。
そういえば、ETフェスタが開催されるのですね。どこかにお邪魔して、お話を聞いてみたいですね。
急な仕事や病気がなければ、ぜひ行って見たいと思っています。
  1. 2009年10月16日 13:18 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

CMOSカメラから画像を入力してディスプレイへ出力12(実機でテスト、うまくいかない)

前回でシミュレーションが大体終わったので、ISE11.3でインプリメントして、ボードにコンフィグして確かめてみた。そうしら、みごとにCMOSカメラの映像信号が出ない。
Chipscopeを入れて確かめてみたのだが、HREFがずっと0、cam_clk_resetが0ということは、DCMがロックされているので、図2のCMOSカメラに入っているCLKは出ている。もっともそのクロックでChipscope が動いているのだが。。。mclk_locked は0でmclk が来ていないようだ。mclk はCMOSカメラのPCLKをDCMに入れて、出てきたクロックで、回路全体で使用するものだ。
Camera_Disp_22_091015.png
     図1 最初のChipscope波形

Camera_Disp_6_090921.png
           図2 クロック系統図

CMOSカメラ (OV7640) のマニュアルを読んでみると、ts:RESET (Setting time after software/hardware reset) が1ms となっている。RESETの期間が1ms というわけではないような気もするが、今まではDCMのロックまでに期間でリセットを出力していたので、今度はカウンタでカウントして1.37ms のリセットを出力することにした。

 -- CMOSカメラ用のリセットを出力する(1.37ms)
    -- CMOSカメラのRESETを出力するために32,768カウントする。(41.67ns * 32768 = 1.37ms)
    process(cam_clk_node) begin
        if cam_clk_node'event and cam_clk_node='1' then
            if cam_clk_locked='0' then
                cam_rst_cnt <= (others => '0');
            elsif cam_rst_cnt(15)='0' then -- 最上位が0の時はカウントして、1のなったらそこで停止
                cam_rst_cnt <= cam_rst_cnt + 1;
            end if;
        end if;
    end process;
    n_cam_reset <= cam_rst_cnt(15); -- CMOSカメラ用のリセットを出力する(1.37ms)


そうすると、mclk_locked は1になって、PCLKが出力されてきたみたいだが、HREFは今度は1のままになっている。データ (cam_ydata_2d) も何か来ていたようだ。cam_mem_addr も回っているし、何か動いているのが分かるが、まだ、HREFが定期的に0から1、1から0になっていない。
Camera_Disp_23_091015.png

何かおかしい?以前のカラーデータを出力するビットファイルを入れると2回に1回は正常に表示されるので、システムは正常だ。(DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示
それでもおかしいので、もしかしたら、”DWM誌の2007年8月号と2007年10月号の基板でカメラの画像を表示2”と同様な原因も考えられる。
あるいは、CMOSカメラの仕様手順がおかしいということも考えられる。I2Cのクロックとデータを無視していたので、ポートを生かして下のように記述してみたが変化なし。

cam_sio_c <= '1';
cam_sio_d <= 'Z';


もう少し、DWM誌の2007年8月号を読んで勉強してみようと思う。
今のところ一番怪しいのはDCMの位置だろうか?それに、上のVHDLリストで n_cam_reset <= cam_rst_cnt(15); を n_cam_reset <= not cam_rst_cnt(15); としただけで関係ないはずのChipscope 用のクロックまで出なくなってしまうようなのだ。これはいかにもおかしいしあやしい?このクロックは48MHz水晶発振器のクロックを直接DCMを通して24MHzにしただけのクロックなので、変更しても止まるはずはないのだが。。。
DCMをはずしてみるというのも1つの手かもしれない。
  1. 2009年10月16日 05:31 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:2

CMOSカメラから画像を入力してディスプレイへ出力11(シミュレーション2)

今度は、CamDispCntrl_SRAM.vhd の内部タイミングを忘れないように書いておく。
まずは、前回、CamDispCntrl_SRAM から出力したcam_clk をCMOSカメラに出力して、CMOSカメラから入ってきたcam_pclk をDCMに入れて全体を如何させるクロックとする。
CMOSカメラからのcam_href, cam_vsync は一度IOBのFFを通して、cam_href_1d, cam_vsync_1d として、synchronizer.vhd に入力されてmaster_sync, r_wタイミングなどを生成する。
下に、synchronizer.vhd のソースを示す。

-- synchronizer
-- synchronizerが使用するのは、FPGAに入力されたcam_hrefやcam_vsyncからIOBのFFを通り1クロックディレイした信号。その他のモジュールは2クロック遅延した信号を用いる
-- cam_vsync_1d が1から0になった後の最初の cam_href_1d の立ち上がりで同期信号(master_sync)を出力する
-- 同時に出力するR_W信号を1(Read)にする

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;

entity synchronizer is
    port(
        clk : in std_logic;
        reset : in std_logic;
        cam_vsync_1d : in std_logic;
        cam_href_1d : in std_logic;
        master_sync : out std_logic;
        r_w : out std_logic
    );
end synchronizer;

architecture RTL of synchronizer is
type sync_state is (idle_sync, vsync_assert, vsync_deassert, sync_active);
signal cs_sync, ns_sync : sync_state;
type rw_state is (idle_rw, read_state, write_state);
signal cs_rw, ns_rw : rw_state;
signal msync : std_logic;
signal r_w_node : std_logic;

begin
    -- master_syncを出力するステートマシン
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_sync <= idle_sync;
            else
                cs_sync <= ns_sync;
            end if;
        end if;
    end process;
    
    process(cs_sync, cam_vsync_1d, cam_href_1d) begin
        msync <= '0';
        case cs_sync is
            when idle_sync =>
                if cam_vsync_1d='1' then
                    ns_sync <= vsync_assert;
                else
                    ns_sync <= idle_sync;
                end if;
            when vsync_assert =>
                if cam_vsync_1d='0' then
                    ns_sync <= vsync_deassert;
                else
                    ns_sync <= vsync_assert;
                end if;
            when vsync_deassert =>
                if cam_href_1d='1' then
                    ns_sync <= sync_active;
                else
                    ns_sync <= vsync_deassert;
                end if;
            when sync_active =>
                msync <= '1';
                ns_sync <= idle_sync;
        end case;
    end process;
    master_sync <= msync;
    
    -- r_wを出力するステートマシン
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_rw <= idle_rw;
            else
                cs_rw <= ns_rw;
            end if;
        end if;
    end process;
    
    -- その他のモジュールの動作は1クロック遅れるので、最初はwrite_stateとなる
    process(cs_rw, cs_sync, cam_href_1d) begin
        case cs_rw is
            when idle_rw =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= write_state;
                else
                    ns_rw <= idle_rw;
                end if;
            when read_state =>
                r_w_node <= '1';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= read_state;
                else
                    ns_rw <= write_state;
                end if;
            when write_state =>
                r_w_node <= '0';
                if cs_sync=vsync_deassert and cam_href_1d='1' then
                    ns_rw <= read_state;
                else
                    ns_rw <= read_state;
                end if;
        end case;
    end process;
    r_w <= r_w_node;
end RTL;


下に、前回と同様なタイミング(cam_vsync が1になった後、最初のcam_hrefが1の時)でのタイミングチャートを下に示す。
Camera_Disp_20_091014.png

synchronizer.vhd で生成されたタイミングで各種モジュールが動作する。よって、その他のモジュールが使用する信号は、CMOSカメラの出力から2クロック遅れた信号となる。(cam_href_2d... など)

下にCamDispCntrl_SRAM.vhd のソースを示す。

--CamDisplay Contoroller with SRAM(トップモジュール)-- トップモジュールから全部作ることにする。
-- CMOSカメラから出てくるビデオ出力はUYVYとする
-- VSYNCは正論理、HREFも正論理
-- clk(48MHz)はそのまま使用して、PCLKをDCMで受けて使用する。
-- IOBにマップされるロジックはこのトップモジュールにインスタンシエーションする。
-- synchronizerでは_1dのデータを使用し、その他のモジュールでは_2dのデータを使用する
-- 全体のタイミングは_2dを基準とする

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;

-- pragma translate_off
library UNISIM;
use UNISIM.VComponents.all;
-- pragma translate_on

entity CamDispCntrl_SRAM is
    port (
        clk    : in std_logic;            -- 水晶発振器からの48MHzクロック
        cam_vsync : in std_logic;    -- CMOSカメラからのVSYNC
        cam_href : in std_logic;    -- CMOSカメラからのHREF
        cam_pclk : in std_logic;        -- CMOSカメラからのpclk
        cam_ydata : in std_logic_vector(7 downto 0); -- CMOSカメラからのYデータ
        -- cam_sio_c : out std_logic;    -- CMOSカメラのI2Cクロック
        -- cam_sio_d : inout std_logic; -- CMOSカメラのI2Cデータ
        cam_clk    : out std_logic;     -- CMOSカメラのクロック
        n_cam_reset    : out std_logic;     -- CMOSカメラのリセット(Lでリセットの予定)
        dac_red    : out std_logic_vector(7 downto 0);    -- DACへのRED出力
        dac_green : out std_logic_vector(7 downto 0); -- DACへのGREEN出力
        dac_blue : out std_logic_vector(7 downto 0); -- DACへのBLUE出力
        n_dac_blank : out std_logic; -- DACへのアクティブローBLANK
        dac_clk : out std_logic; -- DACクロック(24MHz)
        vga_vsync : out std_logic; -- VGAのVSYNC
        vga_hsync : out std_logic; -- VGAのHSYNC
        mem_data : inout std_logic_vector(15 downto 0);    -- SRAMのmemory data
        n_mem_we : out std_logic; -- SRAMのmemory write enable
        n_mem_rd : out std_logic; -- SRAMのmemory read enable
        n_mem_cs0 : out std_logic; -- SRAMのchip select 0
        n_mem_cs1 : out std_logic; -- SRAMのchip select 1
        n_mem_cs2 : out std_logic; -- SRAMのchip select 2
        n_mem_cs3 : out std_logic; -- SRAMのchip select 3
        n_mem_lowerB : out std_logic; -- SRAMのmemory lower byte enable
        n_mem_upperB : out std_logic; -- SRAMのmemory upper byte enable
        mem_addr : out std_logic_vector(17 downto 0) -- SRAMのmemory address
    );
end CamDispCntrl_SRAM;

architecture RTL of CamDispCntrl_SRAM is
component DCM_module_24MHz
    port(
        clk48MHz_in : in std_logic;
        clk48_out : out std_logic;
        cam_clk_out : out std_logic;
        pclk_in : in std_logic;
        mclk_out : out std_logic;
        cam_clk_locked : out std_logic;
        mclk_locked : out std_logic
    );
end component;
component ODDR2
 generic(

      DDR_ALIGNMENT : string := "NONE";
      INIT          : bit    := '0';
      SRTYPE        : string := "SYNC"
      );

  port(
      Q           : out std_ulogic;

      C0          : in  std_ulogic;
      C1          : in  std_ulogic;
      CE          : in  std_ulogic := 'H';
      D0          : in  std_ulogic;
      D1          : in  std_ulogic;
      R           : in  std_ulogic := 'L';
      S           : in  std_ulogic := 'L'
    );
end component;
component VGA_Display_Controller
    port(
        clk : in std_logic;
        reset : in std_logic;
        master_sync : in std_logic; -- 表示タイミングの同期信号
        pixel_y_data : in std_logic_vector(15 downto 0); -- Yのデータ、下のdata_enableが1の時に有効
        data_enable : in std_logic;
        h_count_out : out unsigned(9 downto 0); -- 水平カウンタのカウント出力
        v_count_out : out unsigned(9 downto 0); -- 垂直カウンタのカウント出力
        red_out : out std_logic_vector(7 downto 0); -- VGA出力
        green_out : out std_logic_vector(7 downto 0); -- VGA出力
        blue_out : out std_logic_vector(7 downto 0); -- VGA出力
        blank_out : out std_logic; -- BLANK出力
        h_syncx_out : out std_logic; -- 水平同期出力
        v_syncx_out : out std_logic; -- 垂直同期出力
        mem_addr : out std_logic_vector(18 downto 0) -- SRAMのアドレス、バイト単位
    );
end component;
component synchronizer
    port(
        clk : in std_logic;
        reset : in std_logic;
        cam_vsync_1d : in std_logic;
        cam_href_1d : in std_logic;
        master_sync : out std_logic;
        r_w : out std_logic
    );
end component;
component SRAM_Controller
    port(
        clk : in std_logic;
        clk48 : in std_logic;
        reset : in std_logic;
        r_w : in std_logic; -- Read or Write
        cam_href_3d : in std_logic; -- cam_href の3クロック遅れ、各モジュールで2クロック遅れの信号を使っているので、それよりも1クロック遅れている信号をweのイネーブルとして使用する。これはUYVYとデータが来るので、サンプルするのに1クロック遅れるから。
        master_sync : in std_logic;
        cam_mem_addr : in std_logic_vector(17 downto 0); -- CMOSカメラの書き込み用のアドレス
        cam_ydata_in : in std_logic_vector(7 downto 0); -- CMOSカメラのデータ
        vga_mem_addr : in std_logic_vector(18 downto 1); -- VGAコントローラー用読み出し用アドレス
        
        mem_data_out : out std_logic_vector(15 downto 0); -- SRAMのデータ出力。CMOSカメラのデータを2つ集めたもの。
        mem_data_oe : out std_logic; -- SRAMのmemory data出力のOutput Enable
        
        n_mem_we : out std_logic; -- SRAMのWE
        n_mem_cs0 : out std_logic; -- SRAMのchip select 0
        n_mem_cs1 : out std_logic; -- SRAMのchip select 1
        n_mem_cs2 : out std_logic; -- SRAMのchip select 2
        n_mem_cs3 : out std_logic; -- SRAMのchip select 3
        n_mem_lowerB : out std_logic; -- SRAMのmemory lower byte enable
        n_mem_upperB : out std_logic; -- SRAMのmemory upper byte enable
        mem_addr : out std_logic_vector(17 downto 0) -- SRAMのmemory address
    );
end component;
component Camera_Controller
    port(
        clk : in std_logic;
        reset : in std_logic;        
        cam_href_2d : in std_logic;    -- CMOSカメラからのHREFのラッチ出力
        master_sync : in std_logic; -- 同期信号
        mem_addr : out std_logic_vector(17 downto 0) -- CMOSカメラのデータを書き込むSRAMのアドレス
    );
end component;
component IOBUF
    port(
        O : out std_logic;
        IO : inout std_logic;
        I : in std_logic;
        T : in std_logic
    );
end component;

signal mclk : std_logic;
signal reset : std_logic;
signal mclk_locked : std_logic;
signal master_sync : std_logic;
signal r_w : std_logic;
signal cam_href_1d, cam_vsync_1d : std_logic;
signal cam_href_3d : std_logic;
signal cam_href_2d, cam_vsync_2d : std_logic;
signal cam_ydata_1d, cam_ydata_2d : std_logic_vector(7 downto 0);
signal w_r : std_logic;
signal vga_blank : std_logic;
signal vga_mem_addr : std_logic_vector(17 downto 0);
signal vga_mem_addr_19 : std_logic_vector(18 downto 0);
signal cam_mem_addr : std_logic_vector(17 downto 0);
signal clk48 : std_logic;
signal mem_data_out : std_logic_vector(15 downto 0); -- SRAMのデータ出力。CMOSカメラのデータを2つ集めたもの。
signal mem_data_oe : std_logic; -- SRAMのmemory data出力のOutput Enable
signal n_mem_data_oe : std_logic;
signal vga_ydata : std_logic_vector(15 downto 0);
signal input_mem_data : std_logic_vector(15 downto 0);
signal cam_clk_node, cam_clk_locked : std_logic;
signal n_cam_clk_node, cam_clk_reset : std_logic;
signal n_mclk : std_logic;

begin
    
    DCM_module_24MHz_inst : DCM_module_24MHz port map(
        clk48MHz_in => clk,
        clk48_out => clk48,
        cam_clk_out => cam_clk_node,
        pclk_in => cam_pclk,
        mclk_out => mclk,
        cam_clk_locked => cam_clk_locked,
        mclk_locked => mclk_locked
    );
    reset <= not mclk_locked;
    n_cam_reset <= cam_clk_locked; -- CMOSカメラ用のリセットを出力する
    
    -- CMOSカメラ用クロックの生成
    n_cam_clk_node <= not cam_clk_node;
    cam_clk_reset <= not cam_clk_locked;
    ODDR2_for_cam_clk : ODDR2 generic map(
        SRTYPE => "ASYNC"
    ) port map(
        Q => cam_clk,
        C0 => cam_clk_node,
        C1 => n_cam_clk_node,
        CE => '1',
        D0 => '1',
        D1 => '0',
        R => cam_clk_reset,
        S => '0'
    );
    
    -- DAC用クロックの生成
    n_mclk <= not mclk;
    ODDR2_for_dac_clk : ODDR2 generic map(
        SRTYPE => "ASYNC"
    ) port map(
        Q => dac_clk,
        C0 => mclk,
        C1 => n_mclk,
        CE => '1',
        D0 => '1',
        D1 => '0',
        R => reset,
        S => '0'
    );
    
    -- CMOSカメラからの入力は一度IOBのFFを通す
    process(mclk) begin
        if mclk'event and mclk='1' then
            if reset='1' then
                cam_vsync_1d <= '0';
                cam_href_1d <= '0';
                cam_ydata_1d <= (others => '0');
                cam_vsync_2d <= '0';
                cam_href_2d <= '0';
                cam_ydata_2d <= (others => '0');
                cam_href_3d <= '0';
            else
                cam_vsync_1d <= cam_vsync;
                cam_href_1d <= cam_href;
                cam_ydata_1d <= cam_ydata;
                cam_vsync_2d <= cam_vsync_1d;
                cam_href_2d <= cam_href_1d;
                cam_ydata_2d <= cam_ydata_1d;
                cam_href_3d <= cam_href_2d;
            end if;
        end if;
    end process;
    
    -- CMOSカメラの書き込みアドレスの生成
    
    synchronizer_inst : synchronizer port map(
        clk => mclk,
        reset => reset,
        cam_vsync_1d => cam_vsync_1d,
        cam_href_1d => cam_href_1d,
        master_sync => master_sync,
        r_w => r_w
    );
    
    -- mem_dataの入力FF
    process(mclk) begin
        if mclk'event and mclk='1' then
            if reset='1' then
                vga_ydata <= (others => '0');
            else
                vga_ydata <= input_mem_data;
            end if;
        end if;
    end process;
    w_r <= not r_w;
    
    VGA_Display_Controller_inst : VGA_Display_Controller port map(
        clk => mclk,
        reset => reset,
        master_sync => master_sync,
        pixel_y_data => vga_ydata,
        data_enable => w_r,
        h_count_out => open,
        v_count_out => open,
        red_out => dac_red,
        green_out => dac_green,
        blue_out => dac_blue,
        blank_out => vga_blank,
        h_syncx_out => vga_hsync,
        v_syncx_out => vga_vsync,
        mem_addr => vga_mem_addr_19
    );
    n_dac_blank <= not vga_blank;
    
    Camera_Controller_inst : Camera_Controller port map(
        clk => mclk,
        reset => reset,
        cam_href_2d => cam_href_2d,
        master_sync => master_sync,
        mem_addr => cam_mem_addr
    );
    
    vga_mem_addr <= vga_mem_addr_19(18 downto 1);
    SRAM_Controller_inst : SRAM_Controller port map(
        clk => mclk,
        clk48 => clk48,
        reset => reset,
        r_w => r_w,
        cam_href_3d => cam_href_3d,
        master_sync => master_sync,
        cam_mem_addr => cam_mem_addr,
        cam_ydata_in => cam_ydata_2d,
        vga_mem_addr => vga_mem_addr,
        mem_data_out => mem_data_out,
        mem_data_oe => mem_data_oe,
        n_mem_we => n_mem_we,
        n_mem_cs0 => n_mem_cs0,
        n_mem_cs1 => n_mem_cs1,
        n_mem_cs2 => n_mem_cs2,
        n_mem_cs3 => n_mem_cs3,
        n_mem_lowerB => n_mem_lowerB,
        n_mem_upperB => n_mem_upperB,
        mem_addr => mem_addr
    );
    n_mem_data_oe <= not mem_data_oe;
    
    MEM_DATA_GEN : for i in 15 downto 0 generate
        IOBUF_inst : IOBUF port map(
            O => input_mem_data(i),
            IO => mem_data(i),
            I => mem_data_out(i),
            T => n_mem_data_oe
        );
    end generate MEM_DATA_GEN;
    n_mem_rd <= not r_w;
end RTL;


前回と同様なタイミング(cam_vsync が1になった後、最初のcam_hrefが1の時)でのタイミングチャートは、下のようになる。(前回と同じもの)
Camera_Disp_19_091013.png

35ms シミュレーションして全体を表示すると下のようになる。
Camera_Disp_21_091014.png

vga_vsyncが2回出力されるうちに、cam_vsyncは1回出力されている。大体動いてきたと思うが、もう少し、モデルの出すデータ値を変更して、確実に動くかどうかを検証したい。
  1. 2009年10月14日 05:23 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

テレビ台、人間ドック

今日は人間ドックに行ったのでお休みでした。いつも胃カメラをすると、お昼ご飯を食べられなかったのですが、今日はお昼を食べることができましたが、3時ころから頭が痛くて、今まで(午後9時頃)まで寝ていました。やっと、頭が痛いのが治りました。私は、いつも人間ドックに行くと調子が悪くなります。合わないんですね。

今週の月曜日に、オイルフィニッシュ、ミディアムウォルナットをテレビ台に塗装しました。良い色に仕上がったと思います。木目もはっきり浮き上がってきました。下がテレビ台です。
terebidai_1_091013.jpg

左右の棚は可動だななので、取り外して別に塗装しました。
terebidai_2_091013.jpg

木の種類はアガチスです。1週間ほど乾かすと完成です。
  1. 2009年10月13日 21:49 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:0

CMOSカメラから画像を入力してディスプレイへ出力10(シミュレーション1)

CMOSカメラから画像を入力してディスプレイへ出力9(モデルの説明)”でモデルのVHDLソースを掲載したが、シミュレーション波形を載せておくことにする。
まずは、トップモジュールのCamDispCntrl_SRAM.vhd のentityを載せておく。

entity CamDispCntrl_SRAM is
    port (
        clk    : in std_logic;            -- 水晶発振器からの48MHzクロック
        cam_vsync : in std_logic;    -- CMOSカメラからのVSYNC
        cam_href : in std_logic;    -- CMOSカメラからのHREF
        cam_pclk : in std_logic;        -- CMOSカメラからのpclk
        cam_ydata : in std_logic_vector(7 downto 0); -- CMOSカメラからのYデータ
        -- cam_sio_c : out std_logic;    -- CMOSカメラのI2Cクロック
        -- cam_sio_d : inout std_logic; -- CMOSカメラのI2Cデータ
        cam_clk    : out std_logic;     -- CMOSカメラのクロック
        n_cam_reset    : out std_logic;     -- CMOSカメラのリセット(Lでリセットの予定)
        dac_red    : out std_logic_vector(7 downto 0);    -- DACへのRED出力
        dac_green : out std_logic_vector(7 downto 0); -- DACへのGREEN出力
        dac_blue : out std_logic_vector(7 downto 0); -- DACへのBLUE出力
        n_dac_blank : out std_logic; -- DACへのアクティブローBLANK
        dac_clk : out std_logic; -- DACクロック(24MHz)
        vga_vsync : out std_logic; -- VGAのVSYNC
        vga_hsync : out std_logic; -- VGAのHSYNC
        mem_data : inout std_logic_vector(15 downto 0);    -- SRAMのmemory data
        n_mem_we : out std_logic; -- SRAMのmemory write enable
        n_mem_rd : out std_logic; -- SRAMのmemory read enable
        n_mem_cs0 : out std_logic; -- SRAMのchip select 0
        n_mem_cs1 : out std_logic; -- SRAMのchip select 1
        n_mem_cs2 : out std_logic; -- SRAMのchip select 2
        n_mem_cs3 : out std_logic; -- SRAMのchip select 3
        n_mem_lowerB : out std_logic; -- SRAMのmemory lower byte enable
        n_mem_upperB : out std_logic; -- SRAMのmemory upper byte enable
        mem_addr : out std_logic_vector(17 downto 0) -- SRAMのmemory address
    );
end CamDispCntrl_SRAM;


下にそのシミュレーション波形を示す。
Camera_Disp_19_091013.png

最初のカーソルの位置が、cam_vsync が1になってから、初めてcam_href が1になって、CMOSカメラのYデータのサンプルやVGAへの映像信号の出力が開始される時点だ。cam_ydata を見ると、FF, 00, FE, 01... というように出力されている。これはOV7640_Model.vhd が、U, Y, V, Y というように出力しているので、そのうちのYデータ、つまり、00, 01... というようにキャプチャすればよい。
次にmem_data を見ると、下のn_mem_we が0 の時がCMOSカメラのYデータの書き込みで、書き込みアドレスはmem_addr に出力されている。本当は00000 からなのだが、わかりやすいようにCMOSカメラのデータを書き込むアドレスはスタートを00100 からにしてある。最初の書き込みはまだデータが出力されていないので、ダミーの書き込みで、次からが本当の書き込みとなる。2番目のn_mem_we が0 の時(CMOSカメラデータのメモリへの書き込み)は、n_mem_upperb='0', n_mem_lowerb='1' となっていて、上位8ビットへの書き込みであることが分かる。3番目のn_mem_we が0 の時は、今度はn_mem_upperb='1', n_mem_lowerb='0' となっていて、下位8ビットへの書き込みであることが分かる。それぞれ、"00XX", "XX01" を書き込んでいる。
n_mem_rd が0 の時には、IS61LV25616_model.vhd が、55AA からスタートして、上位、下位8ビットごとに+1 したデータを出力している。mem_data を見ると、n_mem_rd が0 の時のデータが"55AA", "56AB"... と上位、下位8ビットごとに+1 されているのが分かる。このデータは、VGA_Display_Controller.vhd でサンプルされてdac_red, dac_green, dac_blue に同じ値が出力されている(2番目のカーソルの位置)。
  1. 2009年10月13日 06:07 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

ディズニーシーに行ってきた

昨日は地区の子供会でディズニーシーにバスで行ってきました。子供たちは誰も行かなかったけれど、幹事なので親だけで行ってきました。ディズニーシーはハロウィン一色でした。
desny_sea_1_091012.jpg

最初に、新アトラクションのタートルトークに行くことにして、行ったら120分待ちでした。このアトラクションはFast Pathがありません。仕方がないので、120分待ってみてきました。途中で腹が減ったので、奥さんを列に残して、ペッパースベアリブとメイプルチュロスを買いに行ってきました。ペッパースベアリブはちょっと辛くて味付けが濃いですが、油も程よく抜けておいしかったです。メイプルチュロスはメイプルらしく程よい甘さでした。
さて、タートルトークは亀のクラッシュとお話をするというアトラクションです。2時間くらい待ってやっと、コロンビア号の中に入りました。中ではタートルトークの掲示がありましたよ。
desny_sea_2_091012.jpg

これを見ながら、やっと入れました。タートルトークは、なかなか良くできていました。名前を聞いてきたりして、人が行ったことの反応を見ても、ソフトウェアによる自動応答ではないような気がします。人がやっているのかな?でも画面のスムーズな動きや反応が凄いですね。どうやってやっているのでしょうか?そんなことを考えさせるアトラクションでした。でも2時間並ぶ価値は?
その後はコロンビア号の
desny_sea_3_091012.jpg

展望デッキに上がりました。眺めが良いです。皆さんも一度行ってみると良いのでは?と思います。天気が良いと最高ですよ!
desny_sea_4_091012.jpg

その後は、ミスティックリズムというミュージカルみたいなのを見ました。これもアリエルみたいに人間空中つり下げや花火、水などを使ったミュージカルでした。あまり意味はわかりませんが、それなりに楽しめました。ただ、音が大きすぎます。私は鼓膜が破れそうなので、耳をふさいでいました。これでちょうどいいくらい。奥さんに聞いたら、音は大きいけれど大丈夫とのこと。。。
疲れたので、ユカタン・ベースキャンプ・グリルで、昼食と言っても2時ですし、先ほど、スペアリブも食べたので、ベーコンと野菜のクリームスープとスモークチキンサラダを食べました。
desny_sea_5_091012.jpg

サラダに載っているスモークチーズがおいしかったです。スモークチキンはもっとスモークが効いていた方が良かったと思いました。スープはそれなりでしょうか?肉ばかり食べているのでクラムチャウダーが食べたかったです!!!このお店にはありませんでした。残念。。。
その後は、島一周の舟に乗って、アトラクションは終わりです。これも、水路からいろいろな風景が見えて良かったですよ。
desny_sea_6_091012.jpg

後はお土産を買って帰りです。しかし、今まで行った中で一番混んでいました。3連休の中日なのでしょうがないですが、入場制限がかかっているときに行ったのは初めてです。
バスに乗り込んで、午後7時30分頃、家に帰ってきました。
  1. 2009年10月12日 05:53 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

CMOSカメラから画像を入力してディスプレイへ出力9(モデルの説明)

CMOSカメラ・ディスプレイ表示回路もだいぶシミュレーションが進んできた。今日は、モデルがどのように書いてあるかを書こうと思う。
最初にもう一度、全体のブロック図を下に示す。
Camera_Disp_4_090921.png

全体のブロック図のなかのCMOSカメラとSRAMのモデルを作成した。

まずはCMOSカメラのモデルから。CMOSカメラのモデルはモードが固定となっている。本当のCMOSカメラはI2Cでモードを設定することができるが、デフォルトの設定のまま使用するので、モデルもデフォルトの640x480ピクセル、30フレーム、UYVYデータ出力に固定されている。下のVHDLコードがCMOSカメラモデルだ。

-- OV7640_Model.vhd-- 現在のOV7640の仕様機能のみをモデル化する
-- Yデータは0から+1していく。UデータはFFから2つずつ減算(つまりずっと奇数)、VデータはFEから2つずつ減算(つまりずっと偶数)
-- clkに対してpclkは5ns程度遅延させる

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity OV7640_Model is
    port(
        clk : in std_logic; -- クロック入力
        n_reset : in std_logic; -- リセット入力
        vsync : out std_logic;
        href : out std_logic;
        pclk : out std_logic;
        ydata : out std_logic_vector(7 downto 0)
        -- sio_c : in std_logic;
        -- sio_d : inout std_logic
    );
end OV7640_Model;

architecture BEHAVIOR of OV7640_Model is
constant H_ACTIVE_VIDEO : integer := 640;
constant H_BLANK_SPACE : integer := 124;
constant H_SUM : integer := H_ACTIVE_VIDEO + H_BLANK_SPACE;

constant V_ACTIVE_VIDEO : integer := 480;
constant V_FRONT_PORCH : integer := 31;
constant V_SYNC_PULSE : integer := 3;
constant V_BACK_PORCH : integer := 11;
constant V_SUM : integer := V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

signal h_count : unsigned(10 downto 0); -- 水平カウンタ
signal v_count : unsigned(9 downto 0); -- 垂直カウンタ
signal u_data : unsigned(7 downto 0);
signal v_data : unsigned(7 downto 0);
signal y_data : unsigned(7 downto 0);
signal reset : std_logic;
signal vsync_node : std_logic;
signal ydata_node : std_logic_vector(7 downto 0);
signal pclock : std_logic;
signal href_node : std_logic;
begin
    reset <= not n_reset;
    pclock <= transport clk after 5 ns;
    pclk <= pclock;
    
    -- 水平タイミング生成
    process(reset, pclock) begin
        if reset='1' then
            h_count <= (others => '0');
        elsif pclock'event and pclock='1' then
            if h_count(10 downto 1) < H_SUM-1 then
                h_count <= h_count + 1;
            else -- CMOSカメラはUYなどと2クロックで1画素のため
                h_count <= (others => '0');
            end if;
        end if;
    end process;
    href_node <= '1' when h_count<H_ACTIVE_VIDEO and v_count<V_ACTIVE_VIDEO else '0';
    href <= href_node after 1 ns;
    
    -- 垂直タイミング
    process(reset, pclock) begin
        if reset='1' then
            v_count <= unsigned(CONV_STD_LOGIC_VECTOR((V_ACTIVE_VIDEO + V_FRONT_PORCH)-1,10));
        elsif pclock'event and pclock='1' then
            if h_count(10 downto 0)=H_SUM-1 then
                if v_count < V_SUM-1 then
                    v_count <= v_count + 1;
                else
                    v_count <= (others => '0');
                end if;
            end if;
        end if;
    end process;
    
    -- vsync の出力タイミング
    process(v_count) begin
        if v_count>=(V_ACTIVE_VIDEO + V_FRONT_PORCH)-1 then
            if v_count<V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE then
                vsync_node <= '1';
            else
                vsync_node <= '0';
            end if;
        else
            vsync_node <= '0';
        end if;
    end process;
    vsync <= vsync_node after 1 ns;
    
    -- ydata の出力
    process(reset, pclock) begin -- Yデータ
        if reset='1' then
            y_data <= (others => '0');
        elsif pclock'event and pclock='1' then
            if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(0)='1' then -- 水平の表示区間で2クロックに1回カウントアップ
                y_data <= y_data + 1;
            elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
                y_data <= (others => '0');
            end if;
        end if;
    end process;
    
    process(reset, pclock) begin -- Uデータ
        if reset='1' then
            u_data <= (others => '1');
        elsif pclock'event and pclock='1' then
            if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(1 downto 0)=0 then -- 水平の表示区間で4クロックに1回-2
                u_data <= u_data - 2;
            elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
                u_data <= (others => '1');
            end if;
        end if;
    end process;
    
    process(reset, pclock) begin -- Vデータ
        if reset='1' then
            v_data <= X"FE";
        elsif pclock'event and pclock='1' then
            if h_count(10 downto 1)<H_ACTIVE_VIDEO and h_count(1 downto 0)=2 then -- 水平の表示区間で4クロックに1回-2
                v_data <= v_data - 2;
            elsif h_count=0 and v_count=0 then -- 1フレーム描画の最初にリセット
                v_data <= X"FE";
            end if;
        end if;
    end process;

    process(h_count, y_data, u_data, v_data) begin
        if h_count(10 downto 1)<H_ACTIVE_VIDEO then -- 表示区間
            case h_count(1 downto 0) is
                when "00" =>
                    ydata_node <= std_logic_vector(u_data);
                when "01" =>
                    ydata_node <= std_logic_vector(y_data);
                when "10" =>
                    ydata_node <= std_logic_vector(v_data);
                when others => -- "11"
                    ydata_node <= std_logic_vector(y_data);
            end case;
        else
            ydata_node <= (others => '0');
        end if;
    end process;
    ydata <= ydata_node after 1 ns;
end BEHAVIOR;


当然ながら、h_countとv_countを持って、水平と垂直をカウントしている。それでVSYNCとHREFを出力する。シミュレーション用に最初の方にVSYNCが出て、その後にHREFが出るようにしている。そうでないとSYNCHRONIZERで同期するのに時間がかかりすぎてしまう。
Yデータは0からカウントアップ、UデータはUデータはFFから2つずつ減算(つまりずっと奇数)、VデータはFEから2つずつ減算(つまりずっと偶数)となる。これはシミュレーションの時にわかりやすくするため。つまり、Yではなく間違ってU, Vを受け取っていても、すぐにわかるようにしている。
clkに対してpclkは5ns程度遅延させている。

次に昨日も少し書いたが、SRAMのモデル。最初は256KX8を2つインスタンシエーションしていたが、メモリを食いすぎるので、64KX2を2つに変更した。わざわざbit_vector にしたのだが、やはりメモリを食うのか?下にVHDLソースを示す。

-- IS61LV25616_model.vhd
--
-- IS61LV25616のモデル。タイミング関係は全く考慮せずに動作だけをモデル化する
-- 256KB入れると厳しいので、1/4にした

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

library modelsim_lib;
use modelsim_lib.util.all;

entity IS61LV25616 is
    port(
        mem_data : inout std_logic_vector(15 downto 0);    -- SRAMのmemory data
        n_mem_we : in std_logic; -- SRAMのmemory write enable
        n_mem_rd : in std_logic; -- SRAMのmemory read enable
        n_mem_cs : in std_logic; -- SRAMのchip select 0
        n_mem_lowerB : in std_logic; -- SRAMのmemory lower byte enable
        n_mem_upperB : in std_logic; -- SRAMのmemory upper byte enable
        mem_addr : in std_logic_vector(17 downto 0) -- SRAMのmemory address
    );
end IS61LV25616;

architecture RTL of IS61LV25616 is
type SRAM256K is array (0 to 65535) of bit_vector(7 downto 0);
signal sram_upper : SRAM256K;
signal sram_lower : SRAM256K;
signal mem_addr_int : integer range 0 to 65535;
signal mem_data_node : std_logic_vector(15 downto 0);
signal mem_data_node2 : std_logic_vector(15 downto 0);
signal master_sync : std_logic;

begin
    mem_addr_int <= CONV_INTEGER(mem_addr(15 downto 0));
    
    -- Write Upper
    process(n_mem_we, n_mem_cs, n_mem_upperB, mem_data, mem_addr_int) begin
        if n_mem_we='0' and n_mem_cs='0' and n_mem_upperB='0' then
            sram_upper(mem_addr_int) <= To_bitvector(mem_data(15 downto 8));
        end if;
    end process;
    
    -- Write Lower
    process(n_mem_we, n_mem_cs, n_mem_lowerB, mem_data, mem_addr_int) begin
        if n_mem_we='0' and n_mem_cs='0' and n_mem_lowerB='0' then
            sram_lower(mem_addr_int) <= To_bitvector(mem_data(7 downto 0));
        end if;
    end process;
    
    -- -- Read Upper
    -- process(n_mem_cs, n_mem_rd, n_mem_upperB, mem_addr_int) begin
        -- if n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' then
            -- mem_data_node(15 downto 8) <= To_stdlogicvector(sram_upper(mem_addr_int));
        -- else
            -- mem_data_node(15 downto 8) <= (others => 'Z');
        -- end if;
    -- end process;
    
    -- -- Read Lower
    -- process(n_mem_cs, n_mem_rd, n_mem_lowerB, mem_addr_int) begin
        -- if n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' then
            -- mem_data_node(7 downto 0) <= To_stdlogicvector(sram_lower(mem_addr_int));
        -- else
            -- mem_data_node(7 downto 0) <= (others => 'Z');
        -- end if;
    -- end process;
    
    -- init_signal_spy でIS61LV25616_instの下にmaster_syncを持ってくる
    process begin
        init_signal_spy("../camdispcntrl_sram_inst/master_sync", "master_sync", 1, -1);
        wait;
    end process;
        
    -- データの流れを見やすいように上位のデータは55から+1, 下位のデータはAAから+1して、出力
    process(master_sync, n_mem_we) begin -- Read Upper
        if master_sync='1' then
            mem_data_node2(15 downto 8) <= x"55";
        elsif n_mem_we'event and n_mem_we='1' then
            if n_mem_cs='0' and n_mem_upperB='0' then
                mem_data_node2(15 downto 8) <= mem_data_node2(15 downto 8) + 1;
            end if;
        end if;
    end process;
    mem_data_node(15 downto 8) <= mem_data_node2(15 downto 8) when n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' else (others => 'Z');
        
    process(master_sync, n_mem_we) begin -- Read Lower
        if master_sync='1' then
            mem_data_node2(7 downto 0) <= x"AA";
        elsif n_mem_we'event and n_mem_we='1' then
            if n_mem_cs='0' and n_mem_lowerB='0' then
                mem_data_node2(7 downto 0) <= mem_data_node2(7 downto 0) + 1;
            end if;
        end if;
    end process;
    mem_data_node(7 downto 0) <= mem_data_node2(7 downto 0) when n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' else (others => 'Z');
        
    mem_data <= mem_data_node after 1 ns;
end RTL;


CMOSカメラの転送レートはディスプレイ表示回路の半分なので、RGB出力は最初の垂直フレームはずっと0のままになってしまう。そうすると40msくらいシミュレーションしないとだめということになる。それかクロックを驚異的に速めるという方法もあるな~。
そこでSRAMモデルの方でReadの時に、SRAMに書き込まれたデータではなく、自分で生成したデータを出して回路をデバックしようと思った。(昨日の引用)つまり、データの流れを見やすいように上位のデータは55から+1, 下位のデータはAAから+1して、出力することにした。

このようにモデルを書いた。次はシミュレーション波形の説明をしたい。

#今日は、子供会の旅行でディズニーシーに行きます。子供会の幹事なので行くのですが、家の子供は誰も行かないで夫婦だけです。(変ですよね)ウォーキングしてきます。。。

(2009/10/13:追記)
IS61LV25616_model.vhd が間違っていたので修正しました。
(2009/10/14:修正)
 OV7640_Model.vhd のv_countが2倍になっていたので修正。
  1. 2009年10月11日 05:21 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:5

ModelSimでinit_signal_spyを使ってVHDLの他の階層のsignalをミラーする

今、ModelSimでCMOSカメラ・ディスプレイ表示回路のシミュレーションをしている。SRAMモデルやCOMSカメラモジュールモデルを接続してテストしている。しかし、CMOSカメラの転送レートはディスプレイ表示回路の半分なので、RGB出力は最初の垂直フレームはずっと0のままになってしまう。そうすると40msくらいシミュレーションしないとだめということになる。それかクロックを驚異的に速めるという方法もあるな~。
そこでSRAMモデルの方でReadの時に、SRAMに書き込まれたデータではなく、自分で生成したデータを出して回路をデバックしようと思った。
つまり通常はこんな風に書いてあるReadの記述を、

    -- Read Upper
    process(n_mem_cs, n_mem_rd, n_mem_upperB, mem_addr_int) begin
        if n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' then
            mem_data_node(15 downto 8) <= To_stdlogicvector(sram_upper(mem_addr_int));
        else
            mem_data_node(15 downto 8) <= (others => 'Z');
        end if;
    end process;
    
    -- Read Lower
    process(n_mem_cs, n_mem_rd, n_mem_lowerB, mem_addr_int) begin
        if n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' then
            mem_data_node(7 downto 0) <= To_stdlogicvector(sram_lower(mem_addr_int));
        else
            mem_data_node(7 downto 0) <= (others => 'Z');
        end if;
    end process;


下のように、Upperが55から+1、LowerがAAから+1になるように書き直した。

    -- データの流れを見やすいように上位のデータは55から+1, 下位のデータはAAから+1して、出力    process(master_sync, n_mem_we) begin -- Read Upper
        if master_sync='1' then
            mem_data_node2(15 downto 8) <= x"55";
        elsif n_mem_we'event and n_mem_we='1' then
            if n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' then
                mem_data_node2(15 downto 8) <= mem_data_node2(15 downto 8) + 1;
            end if;
        end if;
    end process;
    mem_data_node(15 downto 8) <= mem_data_node2(15 downto 8) when n_mem_cs='0' and n_mem_rd='0' and n_mem_upperB='0' else (others => 'Z');
        
    process(master_sync, n_mem_we) begin -- Read Lower
        if master_sync='1' then
            mem_data_node2(7 downto 0) <= x"AA";
        elsif n_mem_we'event and n_mem_we='1' then
            if n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' then
                mem_data_node2(7 downto 0) <= mem_data_node2(7 downto 0) + 1;
            end if;
        end if;
    end process;
    mem_data_node(7 downto 0) <= mem_data_node2(7 downto 0) when n_mem_cs='0' and n_mem_rd='0' and n_mem_lowerB='0' else (others => 'Z');


ここで、master_sync はCMOSカメラのVSYNCが来た後で、最初のHREF が来たときに1になる信号だ。この信号は本来SRAMモジュールには来ていないが、最初のデータを決めるために、どうしても使いたい信号だ。以前、”VHDLの共有変数を使用したシミュレーション”をやってみたことがあったが、その時に教えていただいたinit_signal_spy を使ってみようと思った。
このページを見てやり方を学習したが、ModlSim XE3 6.4b Starter のUser's Manual を見るともう1つ引数が増えているようだ。最後の引数は、control_state でinit_signal_spy をenable, disable することができようになるようだ。int_signal_spy の記述をSRAM(IS61LV25616)のモデルに加えた。
まずは、modelsim_libライブラリをuse する。

library modelsim_lib;
use modelsim_lib.util.all;


その後、architecture のbegin の後に下のように記述した。(当然だが、すぐ後に書かなくてもOK)

    -- init_signal_spy でIS61LV25616_instの下にmaster_syncを持ってくる
    process begin
        init_signal_spy("../camdispcntrl_sram_inst/master_sync", "master_sync", 1, -1);
        wait;
    end process;


これで、上のモジュールの下のcamdispcntrl_sram_instモジュールのmaster_sync をSRAMモジュールのmaster_sync にミラーすることができた。なお、master_sync はsignal で定義しておく必要がある。
上は相対パスだが、下のように絶対パスでもOK。

    -- init_signal_spy でIS61LV25616_instの下にmaster_syncを持ってくる
    process begin
        init_signal_spy("/testbench/camdispcntrl_sram_inst/master_sync", "/testbench/is61lv25616_inst/master_sync", 1, -1);
        wait;
    end process;


実際のコード例は”CMOSカメラから画像を入力してディスプレイへ出力9(モデルの説明)”を参照。
  1. 2009年10月10日 17:49 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

COMODO Inernet Securityをアンインストール

今朝、パソコンを使っていたら、急に反応がのろくなって、マウスクリックに反応しなくなってしまいました。あせって、セーフモードで立ち上げて月曜日の復元ポイントに戻したのですが、やはり、極端に遅くなってどうしようもありません。タスクマネージャーを立ち上げると、それもだいぶかかってやっと見えた状態ですが、何とかcmdagent.exeというプロセスのCPU使用率が99%なのを見ることができました。調べてみると、Comodo Agent Serviceなんだそうですね
とにかく、セーフモードでCOMOD Internet Security をアンインストールしたら、正常に立ち上がりました。昨日か今日かのアップデートに何かがあったのでしょうか?
今度は、Microsoft 純正のMicrosoft Security Essentials を使うことにしました。
あ~、良かった!!!
MSE_091008.png

おかしくなったのはModelSimいじっているときだったんですが、今復旧してModelSimでコンパイルしようとしてもコンパイルできませんでした。他のプロジェクトにするとコンパイルできます。CMOSカメラ・ディスプレイのプロジェクトが壊れたのかな?ModelSimが一連の事態の引き金ということはないですよね???

(追加)
ModelSimのvsimk.exeとvish.exeで1.5GB 食っていました。メモリは全部で2.9GB使用していたので、やはりこの辺が原因でしょうか?やはりSRAMを全部入れたのがいけなかったのかも?1/4の容量にすることにします。
  1. 2009年10月08日 06:36 |
  2. パソコン関連
  3. | トラックバック:0
  4. | コメント:2

CMOSカメラから画像を入力してディスプレイへ出力8(シミュレーション途中)

CMOSカメラから画像を入力してディスプレイへ出力7”の続き。

ISE11.3のConstrants Editorの使い方1”、”ISE11.3のConstrants Editorの使い方2”、”ISE11.3のConstrants Editorの使い方3”でタイミング制約をかけて、その後インプリメントしてみたらとりあえず大丈夫そうだったので、シミュレーションをしてみることにした。シミュレーションをするには、CMOSカメラとSRAMの簡単なモデルを作る必要がある。そこで2つのモデルを適当に頑張りながら作った。そしてテストベンチも出来たので、昨日からModelSimでテストしている。
しかし、新しい版 (6.4b) のModelSimはwave画面が見づらくなってしまった感じがする。前は信号名の部分が右合わせで、階層が深い信号も階層が浅い信号も見やすかったのだけれど。左合わせになってしまっている。。。おまけに深い階層はスライダーを一番右にしても信号名が見えない。。。
Camera_Disp_16_091007.png

その代わり、信号名の下にshort name <-> full nameを切り替えられるアイコン(上の図でピンクで囲った部分)があった。これをクリックすると short name に切り替わる。
Camera_Disp_17_091007.png

もう一度クリックすると full name に切り替わるので、これで使ってみることにする。もし、右合わせにする方法を知っている方がいらっしゃったら教えてください。

さて、久しぶりのModelSimなので、unisim ライブラリを付けるのを忘れて、信号がUになってしまった。
プリミティブのIOBUFを入出力(inout)のところで使っている。

    MEM_DATA_GEN : for i in 15 downto 0 generate
        IOBUF_inst : IOBUF port map(
            O => input_mem_data(i),
            IO => mem_data(i),
            I => mem_data_out(i),
            T => n_mem_data_oe
        );
    end generate MEM_DATA_GEN;


どうも、このIOBUFの出力がUだな~と思っていたら、エラボレーション時にインスタンスが入っていなかった。が~ん!ということはunisimライブラリを use するのを忘れた。。。ということで、VHDLファイルの上の方に、下の記述を追加したら、IOBUFのインスタンスが入った。

-- pragma translate_off
library UNISIM;
use UNISIM.VComponents.all;
-- pragma translate_on


”-- pragma translate_off”と”-- pragma translate_on”で囲むのは、この間は、論理合成しないで下さいと論理合成ツールにお願いするpragmaだ(シミュレーションではpragmaは無視される)。今はなしでも良いのかもしれないけど、前は論理合成ツールに蹴られたこともあったので、必ず入れることにしている。これでIOBUFも正常になっ た。
インスタンスが入った様子を下の図に示す。
Camera_Disp_18_091007.png

ピンクで囲ったiobuf_instがインスタンスが出来たIOBUFだ。ModelSimのWorkspaceペインのInstanceに表示される。

まだいろいろバグがあるので修正中で、お見せできるのにはもう少しかかりそうだ。いろいろ出す必要がある信号が抜けている。

#今日は、娘の修学旅行で早い時間に送って行かなくちゃならないので、この辺で。。。シンガポールだそうだけど、向こうの大学で講義を聞いたり、プレゼンしたりで半分は勉強だそうだ。
  1. 2009年10月07日 05:44 |
  2. 画像処理
  3. | トラックバック:0
  4. | コメント:0

今日の日記 (2009/10/04)

前回、”板と板のはぎ”でつないだ板で、懸案のテレビ台を作った。まだ完成ではないが、だいぶ出来た。中央の棚は固定だが、左右の棚は移動棚にする予定。後は先生のところで移動棚の作り方を教えてもらいながら、作る予定。市販のものの移動棚よりもだいぶ構造的に強くするようだ。作り終わったら、ウォールナット色に塗装する。大きさは1250X360X440(mm)。
terebidai_091004.jpg

手前が天板と棚板。
その後にプッシュブロックを簡単な方法で作った。
pushblock_091004.jpg

その後、3時ころから、下の娘とサイクリングで石下のアピタへ行った。小貝川の土手を行ったが、とても気持ちが良かった。(以前も行きました)アピタに着いたら、レディーボーデンのアイス。私も北海道ミルクを食べたがおいしかった。ふと食品売り場を見ると、名物駅弁大会。。。しかも特価。。。
焼きサバずし、アジの押しずし、さいきょう寿司を買っちゃいました。今日の晩御飯の一部にします。
すぐに帰ったのですが、夕暮れの小貝川の土手は羽虫がいっぱいで、ほうほうの体で逃げ出しました。違う道を通って帰ったら5時でした。
ekiben_091004.jpg

(追加)駅弁の味の感想
焼きサバずし - いかにもサバが載っている感じで、おいしい。サバの油がオイリー。サバ好きにはたまらない一品。
アジの押しずし - 小アジが1匹丸ごと載っている。かなり酸っぱい。上の娘は美味しいとのこと。私には酸っぱすぎる。
さいきょう寿司 - 私はこれが一番好き。巻いてあるおぼろ昆布のだしと秋刀魚の味が絶妙。おいしかった。また食べたい。
  1. 2009年10月04日 18:03 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:0

VHDLの慣性遅延と伝搬遅延

たーぼ のハードウェア設計記録さんのブログ”慣性遅延と伝播遅延”にも記述されていたが、VHDLの慣性遅延と伝搬遅延について、私も覚書を書いておこうと思う。
Verilogの慣性遅延と伝搬遅延については、”Verilog2001版DDR SDRAMコントローラーのModelSimシミュレーション4への回答”を参照。

まずは、サンプルのVHDLコードを記述する。

-- 慣性遅延と伝搬遅延の比較

library IEEE;
use IEEE.std_logic_1164.all;
use ieee.numeric_std.all;

entity delay_test is
end delay_test;

architecture testbanch of delay_test is
signal clk : std_logic := '1';
signal delayed_clk : std_logic;
begin
    clk <= not clk after 10 ns;
    delayed_clk <= clk after 5 ns; -- 慣性遅延
end;


このVHDLコードをModelSimでコンパイルして、100ns シミュレーションすると、下のような波形になった。
delay_1_091004.png

普通に5ns遅延している。
次に、

delayed_clk <= clk after 5 ns; -- 慣性遅延

delayed_clk <= clk after 10 ns; -- 慣性遅延

に変更した時の波形を下に示す。
delay_2_091004.png

正常に遅延している。次に、

delayed_clk <= clk after 10.1 ns; -- 慣性遅延

に変更した時の波形を下に示す。
delay_3_091004.png

波形がなくなってしまう。これは、慣性遅延はパルスの長さ以上の遅延を設定すると、パルスが出力に現れなくなってしまうため。
さて、伝搬遅延にするために、

delayed_clk <= transport clk after 10.1 ns; -- 伝搬遅延

にVHDLソースを変更する。
delay_4_091004.png

そうすると、伝搬遅延では10nsを超える遅延を与えても、クロック波形が伝搬される。
ちなみに、

delayed_clk <= transport clk after 15 ns; -- 伝搬遅延

としても問題ない。
delay_5_091004.png

  1. 2009年10月04日 07:50 |
  2. VHDLの書き方
  3. | トラックバック:0
  4. | コメント:0

手押しカンナ盤を買ってしまいました

木工趣味が高じて、手押しカンナ盤を購入してしまいました。昨日届いたのですが、今日開けてやってみました。買ったのはこの機種ですが、ここでは買わずにオークションで15,500円でした。送料が1,800円、替刃を1組買ったので、それが2,500円で、19,800円でした。
いや~すごいです。2X4材があっという間につるつるになりました。ものすごい回転数でうるさいですが、木くずは99%は付属の袋に入るので周りが汚れません。
ただ、手を載せた板の下でカンナの歯が回っているのでスリルがあります。ちょっと怖い。そこでプッシュブロックを作ってみようと思っています。
teoshikannna_091003.jpg
  1. 2009年10月03日 21:44 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:5

ISE11.3のConstrants Editorの使い方3

ISE11.3のConstrants Editorの使い方2”の続き

今度はOutputのタイミング制約をしていこう。左のConstraint TypeからOutputsを選択する。そうすると、Unconstrained Input Ports に各入力ポートが出てくるので、とりあえず、その中からcam_clk をダブルクリックして、制約を追加しよう。cam_clk は、ODDR2で出力する予定のCMOSカメラ用のクロックなので、なるようにしかならないのだが、一応どのくらいのディレイで出ている見るために、RISING, FALLING両エッジで10ns 程度入れておくことにする。
Constraints_Editor_15_091002.png

Create Clock to Pad (OFFSET OUT) ダイアログが開く。左上のClock pad net and period をDDRのラジオボタンをクリックした(DDRレジスタで出力するため)。Output clock pad net: をclk に変更、Rising edge constraintsのExternal clock to pad (offset out): に10ns、Fa edge constraintsのExternal clock to pad (offset out): に10ns を設定した。
Constraints_Editor_16_091002.png

これでOKボタンをクリックする。DDRなので、RISINGとFALLINGの2つのエントリが、Constraints EditorのCreate Timing Constraints for Output (OFFSET OUT)に入った。
Constraints_Editor_17_091002.png

次に、dac_blue<0> のタイミング制約を作成する。同様にUnconstrained Output Portsからdac_blue<0>をダブルクリックすると、Create Clock to Pad (OFFSET OUT) ダイアログが開く。
DAC(ADV7125)のデータシートの5ページ目から、データのセットアップ時間が0.2ns、ホールド時間が1.5ns ということが分かった。よって、Rising edge constraintsのExternal clock to pad (offset out): に41.66 - 0.2 - 0.8(配線遅延分)= 40.66 nsとした。ホールド時間は指定できないが、そのくらいは大丈夫だと思う。
Constraints_Editor_18_091002.png

SRAM関係は非同期なので、クロックからの出力時間は関係ないが、そろっていないとまずいので、とりあえず、Rising edge constraintsのExternal clock to pad (offset out): を 10ns としておく。
Constraints_Editor_19_091002.png

あとは例によって、テキストエディタでバスの制約はコピーした。結局、出力のタイミング制約は下のようになった。

NET "cam_clk" OFFSET = OUT 10 ns AFTER "clk" RISING;
NET "cam_clk" OFFSET = OUT 10 ns AFTER "clk" FALLING;
NET "dac_blue<0>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<1>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<2>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<3>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<4>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<5>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<6>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_blue<7>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<0>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<1>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<2>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<3>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<4>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<5>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<6>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_green<7>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<0>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<1>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<2>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<3>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<4>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<5>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<6>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "dac_red<7>" OFFSET = OUT 40.66 ns AFTER "cam_pclk";
NET "mem_addr<0>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<1>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<2>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<3>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<4>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<5>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<6>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<7>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<8>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<9>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<10>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<11>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<12>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<13>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<14>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<15>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<16>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_addr<17>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<0>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<1>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<2>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<3>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<4>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<5>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<6>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<7>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<8>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<9>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<10>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<11>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<12>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<13>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<14>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "mem_data<15>" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "n_mem_lowerB" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "n_mem_upperB" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "n_mem_rd" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "n_mem_we" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "vga_hsync" OFFSET = OUT 10 ns AFTER "cam_pclk";
NET "vga_vsync" OFFSET = OUT 10 ns AFTER "cam_pclk";


  1. 2009年10月03日 05:11 |
  2. Constraints Editor
  3. | トラックバック:0
  4. | コメント:0

ISE11.3のConstrants Editorの使い方2

ISE11.3のConstrants Editorの使い方1”の続き。

IOのタイミング制約をやってみることにする。まずはInputを制約する。
左のConstraint TypeからInputsを選択する。そうすると、Unconstrained Input Ports に各入力ポートが出てくるので、とりあえず、その中からcam_href をダブルクリックして、制約を追加しよう。
Constraints_Editor_6_091001.png

そうすると、Create Setup_Time (OFFSETIN) ダイアログが開く。ここではInterface Tyte やData rate Clock edge などを選択するが、この場合はデフォルト値でOKなので、そのままNext > ボタンをクリックして次に進める。
Constraints_Editor_7_091001.png

CMOSイメージセンサOmniVision社のOV7640のマニュアルから、最悪値で行くと、HREFはPCLKの立下りから5nsで有効 (tpHH) になって、PCLKの立下りから0nsで無効 (tpHL) になることが分かる。つまり、クロックの立ち上がりでサンプルする時のセットアップ時間は41.66/2 -5 = 15.83 ns 、HREFが有効な時間は15.83 + 41.66/2 = 36.66 ns であるので、それぞれExternal setup time とData valid duration に値を設定する。
Constraints_Editor_8_091002.png

そして、Finishボタンをクリックすると、Constraints EditorのCreate Timing Constraints for Input (OFFSET IN) にcam_hrefの制約が入る。
Constraints_Editor_9_091002.png

次はcam_vsyncも同様の値を入力する。
次はcam_ydataのタイミング制約を入力する。まずはUnconstrained Input Ports の中のcam_ydata<0>をダブルクリックする。
Constraints_Editor_10_091002.png

そうすると、Create Setup_Time (OFFSETIN) ダイアログが開く。ここではInterface Tyte やData rate Clock edge などを選択するが、この場合はデフォルト値でOKなので、そのままNext > ボタンをクリックして次に進める。(キャプチャ図は省略)
Yデータのクロックの立ち上がりからのセットアップ時間は15 ns 、ホールド時間は8 ns なので、セットアップ時間はそのままだが、有効な時間は34.66 ns 23 nsとなる。
Constraints_Editor_11_091002.png

それで、Finishボタンをクリックする。
Constraints_Editor_12_091002.png

ここまで終了したら、いったんSaveアイコンをクリックして、セーブしてからConstraints Editorを終了する。
CamDispCntrl_SRAM.ucf ファイルを見てみよう。

NET "clk" TNM_NET = clk;
TIMESPEC TS_clk = PERIOD "clk" 20.83 ns HIGH 50%;
NET "cam_pclk" TNM_NET = cam_pclk;
TIMESPEC TS_cam_pclk = PERIOD "cam_pclk" 41.66 ns HIGH 50%;
NET "cam_href" OFFSET = IN 15.83 ns VALID 36.66 ns BEFORE "cam_pclk" RISING;
NET "cam_vsync" OFFSET = IN 15.83 ns VALID 36.66 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<0>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;


上のような制約が追加されている。他のcam_ydataはConstraints Editorから制約しても良いのだが、面倒なので、テキストエディタ(私はPeggyに自作のUCF用の定義ファイルを適用して使っています。”PeggyのUCFファイル用KWDファイル”参照)で制約を複製してしまうのが面倒がなくて良いと思っている(もちろんProject Navigaterから呼び出せる付属のテキストエディタで修正しても良い)。
Constraints_Editor_13_091002.png

もう一度、ProcessesペインのUser Constraints -> Create Timing Constrints をダブルクリックしてConstrinats Editor を起動する。そうすると、Constraints EditorのCreate Timing Constraints for Input (OFFSET IN) にcam_ydataがすべて入っている。
Constraints_Editor_14_091002.png

次は、mem_dataだ。やり方は前と同じなので省略する。SRAMのデータシートによると、アドレスやOE確定から10 ns なので、FPGAからのアドレス出力やOE出力のクロックからの出力時間を10 ns とする。さらにデータが有効になるのはアドレスやOE確定後から10 ns 後となる。と、セットアップ時間は41.66 - 10 - 10 = 21.66 ns となる。余裕がある。データが有効な時間は21.66 + データホールドの最小時間 0 nsなのだが、OEやアドレスの遅延時間の最小値を3 ns と見込んで = 24.66 nsとした。
同様にテキストエディタで複製し、修正したので、最終的なinputの制約は下のようになった。

NET "clk" TNM_NET = clk;
TIMESPEC TS_clk = PERIOD "clk" 20.83 ns HIGH 50%;
NET "cam_pclk" TNM_NET = cam_pclk;
TIMESPEC TS_cam_pclk = PERIOD "cam_pclk" 41.66 ns HIGH 50%;
NET "cam_href" OFFSET = IN 15.83 ns VALID 36.66 ns BEFORE "cam_pclk" RISING;
NET "cam_vsync" OFFSET = IN 15.83 ns VALID 36.66 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<0>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<1>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<2>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<3>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<4>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<5>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<6>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "cam_ydata<7>" OFFSET = IN 15 ns VALID 23 ns BEFORE "cam_pclk" RISING;
NET "mem_data<0>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<1>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<2>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<3>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<4>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<5>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<6>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<7>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<8>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<9>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<10>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<11>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<12>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<13>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<14>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;
NET "mem_data<15>" OFFSET = IN 21.66 ns VALID 24.66 ns BEFORE "cam_pclk" RISING;



(2009/10/07 修正)
cam_ydataのValid時間を34.66 nsから23 nsに修正しました。

  1. 2009年10月02日 05:45 |
  2. Constraints Editor
  3. | トラックバック:0
  4. | コメント:2
»