今日は大晦日なので、年越しそば。天ぷら(エビ、マイタケ、かき揚げ、かぼちゃ)と牡蠣のグラタン。美味しかったです。そばは、私の父親の手打ちです。(ラーメンどんぶりなのはご愛嬌)
これで今年のブログの更新は最後です。今日は画像関係のVHDLコードを書いて過ごします。
皆様、良いお年を。。。
2009年12月31日 20:05 |
日記
| トラックバック:0
| コメント:0
昨日は奥さんと娘2人とハンターマウンテン塩原スキー場に行ってきました。
今回は8時前に着いたので、スキー場の近くのファミリー用駐車場に止められたのでラッキーでした。でも、私は左足親指の爪を割っていてどのくらい滑れるかが不安でした。履きやすくするために助手席で温めておいたため、スキー靴を履くのが簡単でした。良かった。あまり痛くありませんでした。
まずはリフト券を買うのに並びました。でも、スキー場はかなりすいています。早くくるとこうなるのか。。。
スキー板を履いて滑りだします。私のスキー板はファンスキー、ショートスキーと言われるもので99cmです。このほうが持ち運びが便利ですし、スピードを出した直滑降以外は普通に滑れます。ただ、ビンディングがハズレないので、転んだときにより危険だと言われています。
さて、リフトを4本くらい滑りましたが、怪我は少し痛むものの、影響は少なそうで安心しました。それでもいつもよりもポジションを少し変えたので、足のヘタリがはやかったです。(運動不足?)
10時頃もう休憩となりました。その時は、かなり人が増えてきました。やはり、30日でみんな休みでしょうから。スキーに来るんでしょう。(写真を下に示します)
写真を見ると曇っていますが、午後から日もさしてきました。なかなか良いスキー日和。。。
午後からも滑りましたが、足も(運動不足?のため)終了となって2時頃、スキーを終了しました。
しかし、スノーボーダーは危ないですね。うまい人は良いんですが、まだうまくない人は、急に転びます。それも本当にたたきつけられるように転ぶので、見ていても痛そうです。後からスキーで行っても、急にこけるので危なくてしょうがありません。離れるようにしています。エッジが引っかかるんでしょうね?たぶん。
それに、あたりかまわずに座り込むのもやめて欲しいです。リフトを降りたあたりに大量にいます。
2009年12月31日 06:20 |
日記
| トラックバック:0
| コメント:0
すっかり年末モード突入です。28日は有給休暇をとって、大掃除していました。床のワックスがけ、窓拭きなどです。窓拭きは下の2人の子供らに時給500円で発注しました。喜んでやっていました。おかげで大掃除がはかどりました。だいたい2時間で終了したので、千円ずつアルバイト代を渡しました。
というわけで、12月26日から1月3日まで休暇です。明日はハンターマウンテン塩原に日帰りでスキーに行ってくる予定です。雪もありそうなので、滑れるでしょう。車のタイヤもスタッドレスに履き替えました。
FPGAの方はと言うと、この数日、お仕事のCMOSカメラから取り込んだ画像をMP Wavelet変換する回路のバグ取りをしていました。1フレームの最後の処のバグなので34msec くらいシミュレーションしないと問題の箇所が出来てきません。そのシミュレーションに10分以上かかります。それで、ながらデバックをしていました。例えば、本を読みながらシミュレーションが終わったらデバック。食器の洗い物をしながらデバックです。やっとバグも取れました。例外処理の部分だったのですが、例外処理として記述するのは、やはり大変です。通常の処理ができるように入力波形を偽装しました。この方法が一番良いようです。これからは、こうすることにします。あとこれをもう少し作りこまないといけないんですが、自分の趣味のFPGA回路も作りたいところです。
これは、せっかく作ったDDR2 SDRAMコントローラを使ってみたいということで、VGAコントローラを作ろかな?と思っています。前に、キャラクタ・ディスプレイ・コントローラは作ったのですが、今度はビットマップのVGAコントローラを作ろうと思っています。それにはなにか新たにプロセッサをということでOPENCORESで物色していますが、SH2が良いかな?大学のある研究室も使っていると言っていたし。。。
そうすると、DDR2 SDRAMコントローラをマルチポートにする必要が出てきて、帯域をVGA用とプロセッサ用にうまく使う必要が出てきます。なかなか面白そうなテーマではあると思っています。
来年の2月くらいから、あるFPGAボードを使えそうなので、DDR3 SDRAMやPCI Expressをやろうと思っています。楽しみです。
2009年12月29日 05:55 |
日記
| トラックバック:0
| コメント:0
PERIOD制約を入力クロックに対して書いておくと、派生したクロックもその倍率によって制約がかかるというのは知っていたのだが、それぞれのクロックを使ったFF同士のデータ間の制約については確認したことがなかった。今回、ISE11の制約ガイドで確かめてみた。
制約ガイドUG625(v11.4) 2009年12月2日 の58ページの”関連するDCM/PLL/MMCM ドメイン(自動)”に書いてある。
その概要を下に引用する。
最もよくあるクロック回路では、入力クロックがDCM/PLL/MMCM に使用され、出力がデバイスの同期パスのクロックに 使用されています。この場合、DCM/PLL/MMCM への入力クロックにPERIOD 制約を定義することをお勧めします。 この入力クロックにPERIOD 制約を付けると、ザイリンクスツールは各DCM/PLL/MMCM 出力クロックに対して新しい PERIOD 制約を自動的に作成し、出力クロックドメイン間のクロック関係を決定し、これらの同期ドメイン間のパスをす べて解析します。
図も引用する。この図を見ると一目瞭然。
CLK1Xで動作するFFからCLK2Xで動作するFFのデータパスも、CLKINのPERIOD制約を与えておけば、解析されるはず。良かった。
さてそれでは実際の回路で検証してみることにする。
CMOSカメラからディスプレイ出力回路で、SRAMのWEは48MHzクロックで出力している。24MHzクロックのFFの出力を使用して48MHzのクロック動作のFFで受けている。24MHzクロックにPRIOD制約が掛けてあって、DCMのCLK2Xで48MHzを出力している。下がそのパスのセットアップ時間の解析結果。
上のピンクの四角がソースクロックとディスティネーション・クロック。cam_pclkが24MHzでclk48が48MHzクロックだ。下のClock Path Skewを見ると、1.789 - 5.266 = -3.477ns となっている。他の静的タイミングを見るとcam_pclk の遅延が5.266nsだった。多分、clk48のクロック遅延が1.789ns だと思う。これで、セットアップ時間にクロックスキューが換算されている事がわかった。
2009年12月27日 13:50 |
UCFの書き方
| トラックバック:0
| コメント:0
ESP企画の旧パージョンボード(画像ベースボード、デジタルCMOSカメラ、208ピンSpartan3E XC3S500+2M高速SRAM基板)を使って、画像を出力していると、時々下の画像のようにちらちらしておかしくなる。(インプリメントの具合によって違うみたい。ちらつくインプリはずっとちらついているし、ちらつかないインプリはズートちらつかない)
拡大してみると、特に本の白い部分で黒いポチポチが見える。これはほんのちょっとVHDLソースを変えたりすると直ってしまう。詳しくは、”
CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!) ”参照。これはどうして起こるか確かめてみることにした。
いろいろ原因を考えてみたが、SDRAMのReadとWriteもぶつかっているようでも無い。やはりクロックが臭いのかな?ということで、CMOSカメラからのPCLKは下の図のようにDCMを通しているが、PCLKを直接クロックとして使用することにした。それでもXSTが自動的にBUFGは入れてくれていると思うけど。。。
つまり上図でDCM1/1を通さないで直接、回路のマスタクロックとして使用した。そうしたら、おかしい現象は解消された。下のラプラシアンフィルタの図もなんか緑っぽく、ノイジーだったのが、ノイズが減った。(下図はノイジーな状態)
下に変更点を示す。DCM_module_24MHzのmclk出力からmclkをとらないで、外部入力のcam_pclkから直接mclk へ接続した。mclk が回路全体のクロックである。
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, mclk_out => open, cam_clk_locked => cam_clk_locked, mclk_locked => mclk_locked ); reset <= not mclk_locked; mclk <= cam_pclk;
DACクロックもやはり反転して、DACデータの真ん中でクロックを立ち上げた方が良いようだ。
-- 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 => '0', D1 => '1', R => reset, S => '0' );
D0 => '0', D1 => '1' で反対になっている。
これで、安心して仕事の回路がデバックできる。
(追記)
このボードはclk入力もpclk入力もGCLKにアサインされていないので、ISE11だと、下のような制約を入れる必要がある。どうにかならないものかな?GCLKにアサインされていれば。。。
NET "cam_pclk" CLOCK_DEDICATED_ROUTE = FALSE; PIN "DCM_module_24MHz_inst/DCM_pclk.CLKIN" CLOCK_DEDICATED_ROUTE = FALSE;
(もう一度、追記)
新しいESP企画の画像ボードは、ちゃんとクロックがGCLK入力にアサインされていて、PCLKにDCMを使っても問題ないようです。
2009年12月26日 21:51 |
画像処理
| トラックバック:0
| コメント:0
まだ、2009年は終わっていないが今年1年で行ったことをまとめておこうと思う。
1月 ・EDKでPetalinuxを動かしてみようとしていた。しかしLinunxは1つも動かせていない。残念。。。
・秋月電子のAKI-H8/3069FフラッシュマイコンLANボードをいじってた。もう遠い昔のようだ。。。
・”AKI-H8/3069FフラッシュマイコンLANボードでRedBoot起動”でRedBootは起動したが、Ubuntuでtftpd を起動してもネットワーク経由でelf ファイルをダウンロードすることが出来なかった。
2月 ・ISE10.1iのXPower Analyzerを使ってみた。
・2/8にハンタマにスキーに行ったみたい。今シーズンは3回スキーに行ったわけだ。
・ナビを買いました。小さい3.5インチのナビ、ガーミン nuvi250 Plus です。
・2/28にFPGAの部屋のオフ会をした。参加された皆さん、ありがとうございました。また、このような会がもてればと思います。今度はFPGAカフェでどうですかね?
3月 ・Spartan3A Starter KitのDDR2 SDRAMコントローラを作り出した。今年のハイライト、まとめた原稿は来年4月頃公開予定。
・まずはSpartan3AのIOなどを調査
・蔵王に行った。ガリガリのアイスバーン。怖かった。
・Spartan3A Starter KitのDDR2 SDRAMコントローラでフロアプランを試したが、やはりうまくない。
・Spartan3A Starter KitのDDR2 SDRAMコントローラでRead入力用SLICEMの位置を固定した。
4月 ・Spartan3A Starter KitのDDR2 SDRAMコントローラのDQやDQSの配置を試行錯誤していた。
・筑波山にカタクリの花を見に行った。
・Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールでシミュレーション。
・非同期FIFOを自作した。(Advanced FPGA本を参考にした)
・イーエスピー企画が出している。画像ベースボード、デジタルCMOSカメラ、208ピンSpartan3E XC3S500+2M高速SRAM基板を使って、カメラで撮影した画像をアナログRGBディスプレイに表示することができた。(これはサンプルプロジェクトを改造している)
・Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールのインプリメントを行っている。
・ISE11.1iをインストール
5月 ・Spartan3A Starter KitのDDR2 SDRAMコントローラIOテストモジュールを公開した。
・ISE11.1iのチュートリアルを書いた。チュートリアルを書くのは疲れる。。。
・Graphvizでステートマシンの図を書いてみた
・日昇テクノロジーからFPGA/Cyclone II EP2C5Q208ボード とCPLD/FPGA用のインタフェース・ボードとCPLD/FPGA用ダウンロード・ケーブルを購入した。
6月 ・Spartan3A Starter KitのDDR2 SDRAMコントローラのシミュレーションをしていた。今度はIOだけではなくコントローラ全体を作った。
・数学ガールのsin(x)のテイラー展開をMaximaで検証したみた。
・Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのインプメント。DDR2-400は厳しいので、DDR2-300に目標変更。
・Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストのデバック。結局、SD_LOOP_OUTがIOBへマップされていないのが原因だった。
・Spartan3A Starter KitのDDR2 SDRAMコントローラのバーストテストは1時間連続運転してエラーなしだった。できた~。
・37インチの地デジテレビを購入。
・diceのVHDL版。書き方を間違ってしまった。。。
・Veritak3.69B以降とChipScopeによる協調検証をしてみた。シミュレーションと実機のリフレッシュの違いが観測できた。たっくさんありがとうございました。
・Quartus2でSignaltap2とVeritakの協調検証を始めた。
7月 ・ISE11.2iでのSpartan-3とSpartan-6の速度差を検証してみた。Virtex-6とSpartan-6のスライス構造とパスの比較もした。MCBも。
・ModelSimのVHDLシミュレーションとChipScopeの協調検証ができるようなった。ModelSimにVCDファイルを出力させて比べてみた。タックさんありがとうございました。
・Quartus2でSignaltap2を試すためにキャラクタ・ディプレイ・コントローラをAltera用に書き換えた。
・iPhone 3GSを買った。
・AlteraのTimeQuestなどをいろいろいじって勉強をした。
・AlteraのFPGAでキャラクタ・ディプレイ・コントローラを動作させることができた。
・次にSignaltap2を使ってみた。
・SignalTapⅡからVCDファイルを出力し、Veritakでシミュレーションの波形と比べてみることができた。たっくさんありがとうございました。
・小型カメラPENTAX Optio E75を購入。これは検索エンジンからのアクセスが多い。なぜ?
8月 ・AlteraのSOPC Builderを使ってみた。一部バグはあるが、使い易い。
・食品棚完成。
・スライド丸のこ購入。
・黒部ダムにも行ったな~。
・Nios2 9.0 IDEを使ってみた。くりさんやtakepon256さん、いろいろお世話になりました。
・超電磁Pさんの高性能デジタル回路設計の基礎と最新動向というセミナを受けてきた。
・FPGAカフェにも行ってきた。
・FPGA技術No.5の備州長船さんの第3章 THE AVALONM@STER(Avalon-MMスレーブペリフェラルの作成方法)を参考に、ダイナミック7セグメントLED用のAvalon-MMスレーブペリフェラルを作った。
・KiCADにオートルーターが付いた。ちょっと使ってみた。
9月 ・KiCADでSaprtan3ボードを試作してみた。いろいろ使い方がわかった。なんか基板を作ってみたいな。。。
・CMOSカメラから画像を入力してディスプレイへ出力する回路を作り出した。画像処理編スタート。
10月 ・手押しかんな盤を買っちゃいました。
・ModelSimでinit_signal_spyを使ってVHDLの他の階層のsignalをミラーした。長年の懸案の事項をやってみることができた。
・CMOSカメラから画像を入力してディスプレイへ出力する回路もメモリやCMOSカメラのモデルを作ってシミュレーションした。
・子ども会の旅行で親だけでディズニーシーに行ったっけ。
・CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!)。いろいろ紆余曲折はありましたが、やっと白黒画像をディスプレイに出力できました。。。
・画像のエッジ検出。2X2の差分でスレッショルド方式でのエッジ検出。
11月 ・まずは横方向のみのエッジ検出を試した。(スレッショルド方式)
・次に縦横斜めのエッジ検出。(スレッショルド方式)
・2X2の画素の演算で画像のエッジ検出。
・3X3のラプラシアンフィルタが完成。
・ソーベル・フィルタは飽和してしまった。まだデバックしていない。
・ウッドデッキ完成。
・YUV-RGB変換回路の作製を始める。長船さん、ありがとうございました。
・MTM04に行ってきた。楽しかった。
12月 ・DE0を使ってみた。
・YUV-RGB変換回路ができたと思ったら、エッジがおかしかった。
・シャープネスがおかしそうだったので、SCCBレジスタを設定する回路を作製。
・SCCBレジスタでオート・シャープネスを切れば、エッジはOKとなった。
1年を振り返ってみると、今年もいろんなことをやってきた。秋月のマイコン基板から、DDR2 SDRAMコントローラ、Kicad、画像処理までをやっていたとは思わなかった。1年は短いようでも、結構長いのかもしれない。それと木工、電動工具を買いまくった年でもある。また、インパクトドライバーを買おうとしているけど。。。
ブログを書いているので、一年を詳細に振り返って見られるのはとても良いことだと思う。
画像もブログでは、一段落してきたので、次は何をやろうか?(仕事ではこれからです)やはりDDR2 SDRAMコントローラを活かして、ビットマップのVGAコントローラを考えてみようかな?
あとPCI ExpressやDDR3 SDRAMなどもいじってみたい。今後の展開にご期待下さい?(期待出きないかもしれないけど。。。)
#Spartan3A Starter KitのDDR2 SDRAMコントローラは自分のところの技術発表会で、CMOSカメラから画像を入力してディスプレイへ出力する回路は高エネ研の技術研究会でいずれも3月に発表する予定。
2009年12月26日 05:55 |
日記
| トラックバック:0
| コメント:0
検索していたら
TopHatenar が見つかった。
TopHatenarの私のブログページ 。
TopHatenarとは? TopHatenarは、ブログの人気ランキングサイトです。 RSSフィード購読者数とソーシャルブックマーク獲得数という2つの指標をもとに、日本国内におけるブログの影響力を測定することができます。
だそうです。さらに面白いのは、ビジュアルブログ検索エンジンだ。
私のブログのビジュアルブログ検索エンジンの位置 。いろいろ見ているととても面白い。。。
2009年12月25日 05:35 |
日記
| トラックバック:0
| コメント:0
今度はOne_Transaction_SCCB.vhdを説明する。これは、SCCB_Reg_Controller.vhd から渡されたアドレス(SCCB_address)とデータ(SCCB_data)を使って、渡されたアドレスのSCCBレジスタにデータを書き込むモジュールだ。entityの記述を下に示す。
entity One_Transaction_SCCB is port( clk : in std_logic; -- クロック reset : in std_logic; -- リセット SCCB_address : in std_logic_vector(7 downto 0); -- SCCBレジスタのアドレス SCCB_data : in std_logic_vector(7 downto 0); -- SCCBレジスタのデータ op_enable : in std_logic; -- 動作イネーブル(200KHz, 5usec間隔) start_pulse : in std_logic; -- スタートパルス(1クロック幅) end_pulse : out std_logic; -- エンドパルス(1クロック幅) SCL : out std_logic; SDA : out std_logic ); end One_Transaction_SCCB;
start_pulseを入れて、end_pulseが出力されると渡されたアドレスのSCCBレジスタにデータを書き込む操作が終了となる。op_enableはfreqdiv.vhdから出力されたop_enaを接続する。SCLとSDAはCMOSカメラへ。
最初にメインのステートマシン。構造を下に示す。
VHDLコードを下に示す。
-- Main State Machine process(clk) begin if clk'event and clk='1' then if reset='1' then cs_main <= idle_main; else case cs_main is when idle_main => if start_pulse='1' then -- スタートパルスが来たらスタート cs_main <= start_state; end if; when start_state => if state_counter=17 and op_enable='1' then -- START ステートの最後で5us のイネーブルの時に遷移 cs_main <= ID_Address; end if; when ID_Address => if state_counter=17 and op_enable='1' then -- ID_Address ステートの最後で5us のイネーブルの時に遷移 cs_main <= SCCB_Reg_Addr; end if; when SCCB_Reg_Addr => if state_counter=17 and op_enable='1' then -- SCCB_Reg_Addr ステートの最後で5us のイネーブルの時に遷移 cs_main <= Write_Data; end if; when Write_Data => if state_counter=17 and op_enable='1' then -- Write_Data ステートの最後で5us のイネーブルの時に遷移 cs_main <= stop_state; end if; when stop_state => if state_counter=17 and op_enable='1' then -- stop_state ステートの最後で5us のイネーブルの時に遷移 cs_main <= idle_main; end if; end case; end if; end if; end process;
state_counterが17でop_enaが1のときに遷移する。state_counter は0~17までカウントするカウンタで、op_enaが1の時にカウントアップする。
次にデータパスのブロック図を再度示す。
SDAはSCLに比べて、必ず遅れるようにFFを2段入れた。SDAの最後のトラーステートバッファのイネーブルは必ずFFの出力とした方が良い。それは、イネーブルが組み合わせ回路だと、どの時点でひげが出て、思わぬ時にONしてしまうかわからないためだ。
下にconstant値と18ビット、9ビットのシフトレジスタのVHDLコードを示す。
constant START_PATTERN_SCL : std_logic_vector := "111111111111111111"; constant IDA_SCCBR_WD_PATTERN_SCL : std_logic_vector := "010101010101010101"; constant STOP_PATTERN_SCL : std_logic_vector := "011111111111111111"; constant START_PATTERN_SDA : std_logic_vector := "111111110"; constant ID_ADDRESS_PATTERN_SDA : std_logic_vector := "010000100"; constant STOP_PATTERN_SDA : std_logic_vector := "011111111"; -- SLC 用18ビット・シフトレジスタ process(clk) begin if clk'event and clk='1' then if reset='1' then SCL_shift_reg <= (others => '1'); else case cs_main is when idle_main => if start_pulse='1' then -- スタートパルスが来たらスタート SCL_shift_reg <= START_PATTERN_SCL; end if; when start_state => if op_enable='1' then if state_counter=17 then -- START ステートの最後で5us のイネーブルの時に遷移 SCL_shift_reg <= IDA_SCCBR_WD_PATTERN_SCL; else SCL_shift_reg <= SCL_shift_reg(16 downto 0) & '1'; end if; end if; when ID_Address => if op_enable='1' then if state_counter=17 then SCL_shift_reg <= IDA_SCCBR_WD_PATTERN_SCL; else SCL_shift_reg <= SCL_shift_reg(16 downto 0) & '1'; end if; end if; when SCCB_Reg_Addr => if op_enable='1' then if state_counter=17 then SCL_shift_reg <= IDA_SCCBR_WD_PATTERN_SCL; else SCL_shift_reg <= SCL_shift_reg(16 downto 0) & '1'; end if; end if; when Write_Data => if op_enable='1' then if state_counter=17 then SCL_shift_reg <= STOP_PATTERN_SCL; else SCL_shift_reg <= SCL_shift_reg(16 downto 0) & '1'; end if; end if; when stop_state => if op_enable='1' then SCL_shift_reg <= SCL_shift_reg(16 downto 0) & '1'; end if; end case; end if; end if; end process; -- SDA 用9ビット・シフトレジスタ process(clk) begin if clk'event and clk='1' then if reset='1' then SDA_shift_reg <= (others => '1'); else case cs_main is when idle_main => if start_pulse='1' then -- スタートパルスが来たらスタート SDA_shift_reg <= START_PATTERN_SDA; end if; when start_state => if op_enable='1' and state_counter(0)='1' then -- 2回に1回遷移 if state_counter=17 then -- START ステートの最後で5us のイネーブルの時に遷移 SDA_shift_reg <= ID_ADDRESS_PATTERN_SDA; else SDA_shift_reg <= SDA_shift_reg(7 downto 0) & '1'; end if; end if; when ID_Address => if op_enable='1' and state_counter(0)='1' then -- 2回に1回遷移 if state_counter=17 then SDA_shift_reg <= SCCB_address & '1'; else SDA_shift_reg <= SDA_shift_reg(7 downto 0) & '1'; end if; end if; when SCCB_Reg_Addr => if op_enable='1' and state_counter(0)='1' then -- 2回に1回遷移 if state_counter=17 then SDA_shift_reg <= SCCB_data & '1'; else SDA_shift_reg <= SDA_shift_reg(7 downto 0) & '1'; end if; end if; when Write_Data => if op_enable='1' and state_counter(0)='1' then -- 2回に1回遷移 if state_counter=17 then SDA_shift_reg <= STOP_PATTERN_SDA; else SDA_shift_reg <= SDA_shift_reg(7 downto 0) & '1'; end if; end if; when stop_state => if op_enable='1' and state_counter(0)='1' then -- 2回に1回遷移 SDA_shift_reg <= SDA_shift_reg(7 downto 0) & '1'; end if; end case; end if; end if; end process;
これで大体説明できたと思う。これらのファイルを合わせて、テストベンチを書くと下のようなシミュレーション波形が得られる。
2009年12月23日 21:27 |
画像処理
| トラックバック:0
| コメント:0
次にまずはfreqdiv.vhd から。freqdiv.vhd は25MHzから200KHzに分周する回路だ。ただ単に分周するのではなく、200KHzに相当する間隔、つまり5usec ごとに25MHzクロック1クロック分の幅 (40nsec) 分のイネーブル信号を出力する。それがop_ena だ。なんでこんなことをするのかと言うと、分周してクロック周波数を200KHz とすると、25MHz で動作する回路とのインターフェースが面倒だからだ。ツール、つまりISEでも自動では面倒を見てくれない。お互いの信号のやりとりは非同期としての扱いになってしまう。25MHzクロック1クロック分の幅 (40nsec) 分のイネーブル信号だったら、回路動作は25MHzクロックでの動作となるので、ツールが自動的(制約を掛けておけば)に良いようにしてくれる。ということで、このような構成になっている。下にVHDLコードを示す。
-- Frequncy Divider -- 200KHz clock -- マスタークロックを200KHzのop_enaに分周します。 library ieee; use ieee.std_logic_1164.all; use ieee.std_logic_unsigned.all; use ieee.std_logic_arith.all; entity FreqDiv is generic( divisor : integer := 125 ); port( clk, reset : in std_logic; op_ena : out std_logic ); end FreqDiv; architecture RTL of FreqDiv is signal lcnt : std_logic_vector(15 downto 0); begin process(clk) begin -- Enable frequency is 200KHz if clk'event and clk='1' then if reset='1' then lcnt <= (others => '0'); elsif lcnt = conv_std_logic_vector(divisor, 16)-1 then lcnt <= (others => '0'); else lcnt <= lcnt + 1; end if; end if; end process; process(clk) begin if clk'event and clk='1' then if lcnt = conv_std_logic_vector(divisor, 16)-1 then op_ena <= '1'; else op_ena <= '0'; end if; end if; end process; end RTL;
次は、SCCB_reg_values_ROM.vhd だが、これは、”
VHDLでのブロックRAMや分散RAMの初期化(16進数で書かれた外部データファイル) ”で説明した大体そのままなのだが、RAMではなくROMになっている。下にVHDLコードを示す。
-- SCCB_reg_values_ROM.vhd -- SCCBプロトコル・コントローラを実装してSCCBレジスタに書き込む値をセーブしてある ROM。書き込みデータは SCCB_reg_values.data にセーブしておく。 -- SCCB_reg_values.data のフォーマット"1280" 最初の2キャラクタが16進形式のアドレス、次の2キャラクタが16進形式のデータ。例は12番地に80を書く -- SCCB_reg_values_ROM.data には必ず256行のデータを用意しておく。アドレスがFFの場合はレジスタ・アクセスはそこで終了する。 library IEEE, STD; use IEEE.std_logic_1164.all; use STD.textio.all; use IEEE.std_logic_textio.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; -- pragma translate_off library UNISIM; use UNISIM.VCOMPONENTS.ALL; -- pragma translate_on entity SCCB_reg_values_ROM is port( clk : in std_logic; -- Clock address : in std_logic_vector(7 downto 0); dout : out std_logic_vector(15 downto 0) ); end SCCB_reg_values_ROM; architecture RTL of SCCB_reg_values_ROM is type RamType is array(0 to 255) of std_logic_vector(15 downto 0); impure function InitRamFromFile (RamFileName : in string) return RamType is FILE RamFile : text is in RamFileName; variable RamFileLine : line; variable RAM : RamType; begin for I in RamType'range loop readline (RamFile, RamFileLine); hread (RamFileLine, RAM(I)); end loop; return RAM; end function; signal RAM : RamType := InitRamFromFile("SCCB_reg_values.data"); begin process(clk) begin if clk'event and clk='1' then dout <= RAM(conv_integer(address)); end if; end process; end RTL;
SCCB_reg_values.dataの一部を下に示す。
ACDF FF00 0000
2009年12月23日 19:50 |
画像処理
| トラックバック:0
| コメント:0
SCCBインターフェース回路が完成した。VHDLソースを全部公開するか、説明を書きながら一部分公開するかで迷ったが、説明を書きながら一部分公開しようと思う。
最上位のトップ階層はSCCB_Reg_Controller.vhd である。このファイルのentity を下に示す。
-- SCCB_Reg_Controller.vhd -- SCCBレジスタのコントローラ -- SCCB_reg_values_ROM.data には必ず256行のデータを用意しておく。アドレスがFFの場合はレジスタ・アクセスはそこで終了する。 -- 1行のデータは16ビット幅となっていて、上位8ビットがアドレス、下位8ビットがデータとなる。 -- One_Transaction_SCCBにアドレスとデータを渡して、1クロック分のstart_pules をアサートしSCCBレジスタに書き込む -- One_Transaction_SCCBが書き込みを終了したら、end_pulseをアサートされるので、終了を検出できる。 -- SCCB_reg_values_ROM.dataのアドレスにFFが書いてあるエントリまで、上記の動作を実行する。 library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; -- pragma translate_off library UNISIM; use UNISIM.VCOMPONENTS.ALL; -- pragma translate_on entity SCCB_Reg_Controller is port( clk : in std_logic; -- クロック reset : in std_logic; -- リセット SCL : out std_logic; -- SCCBのクロック SDA : out std_logic -- SCCBのデータ ); end SCCB_Reg_Controller;
clkとresetを受け取って、SCL(SCCBクロック)とSDA(SCCBデータ)を出力する。
この下に、freqdiv.vhd、One_Transaction_SCCB.vhd、SCCB_reg_values_ROM.vhd の各モジュールがある。
SCCB_Reg_Controller.vhd には、SCCB_reg_values_ROM.vhd から読み込んだデータをSCCBレジスタを設定するモジュール(One_Transaction_SCCB.vhd) に渡すステートマシンがある。これはアドレス値0xFFを読むと停止する。下にそのステートマシンのVHDLコードを示す。
-- SCCBのレジスタをセットするためのステートマシン process(clk) begin if clk'event and clk='1' then if reset='1' then cs_reg_set <= idle; start_pulse <= '0'; else case cs_reg_set is when idle => if ROM_data(15 downto 8) = x"FF" then -- レジスタセット終了 cs_reg_set <= end_state; start_pulse <= '0'; else -- アドレスがFFでないので、セットするレジスタがある cs_reg_set <= start_pulse_state; start_pulse <= '1'; end if; when start_pulse_state => cs_reg_set <= wait_one_trans_SCCB; start_pulse <= '0'; when wait_one_trans_SCCB => if end_pulse='1' then -- SCCBレジスタへの書き込みが終了 cs_reg_set <= next_address; start_pulse <= '0'; end if; when next_address => if ROM_address=x"FF" then -- 終了 cs_reg_set <= end_state; start_pulse <= '0'; else cs_reg_set <= idle; start_pulse <= '0'; end if; when end_state => cs_reg_set <= end_state; start_pulse <= '0'; end case; end if; end if; end process;
このステートマシンでは、One_Transaction_SCCB.vhd にstart_pulse を出して1つのSCCBレジスタへのWriteを実行させる。One_Transaction_SCCB.vhd のSCCBレジスタへのWrite終了後に受け取るend_pulse を受けるとSCCB_reg_values_ROM.vhd のアドレスを1つ進める。そして、idleステートに戻り、アドレスに0xFFが出てきたらend_state に行ったきりになって終了となる。
2009年12月23日 08:28 |
画像処理
| トラックバック:0
| コメント:0
”
SCCBインタフェース回路の実装3(シミュレーション) ”でシミュレーションが大丈夫そうだったので、インプリメントして試してみた。
設定したSCCBレジスタのアドレスは0xAC、書き込んだデータは0xDF。アドレスACのbit5にSharpness (edge enhancement) auto strength control というビットがあるので、これを解除した。結果として、”
YUV-RGB変換7(なんか不具合が。。。) ”で問題だった輝度の変化の激しい場所での輝度データの飽和は無くなった。SCCBレジスタにうまく書き込めたようだ。やった~!!!
下にディスプレイの写真を示す。
だいぶピントが合っていないような気がするが、これをシャープネスでシャープにしていたのだろうか?
ともかく直ったみたいだ。いろいろSCCBレジスタをいじってみる必要がありそうだ。外部データファイルを書き換えてインプリメントすると簡単に設定の変更ができるので、手軽にトライしてみることができるようになった。
2009年12月22日 19:37 |
画像処理
| トラックバック:0
| コメント:2
”
SCCBインタフェース回路の実装2(ブロック図の作成) ”で書いたブロック図を元にVHDLでコーディングをした。
下のconstant値ががSCL用18ビットシフトレジスタにロードする値と9ビットのSDA用シフトレジスタにロードする値だ。
constant START_PATTERN_SCL : std_logic_vector := "111111111111111111"; constant IDA_SCCBR_WD_PATTERN_SCL : std_logic_vector := "010101010101010101"; constant STOP_PATTERN_SCL : std_logic_vector := "011111111111111111"; constant START_PATTERN_SDA : std_logic_vector := "111111110"; constant ID_ADDRESS_PATTERN_SDA : std_logic_vector := "010000100"; constant STOP_PATTERN_SDA : std_logic_vector := "011111111";
VHDLの階層はSCCB_Reg_Controller.vhdがトップで、その下に、freqdiv.vhd、One_Transaction_SCCB.vhd、SCCB_reg_values_ROM.vhd の各モジュールがある。
freqdiv.vhd は25MHzを200KHz, 5usec のイネーブルを生成する。One_Transaction_SCCB.vhd はSCCBレジスタのアドレスとデータを与えられて、SCCBレジスタに1つ書き込む回路である。SCCB_reg_values_ROM.vhd はSCCB_reg_values.data の内容をROMに読み込んだROM。VHDLソースは長いので省略。
シミュレーション波形を下に示す。
上の図でscl がクロック、sda がデータだ。scl は10usec周期、100KHzとなっている。下のcs_main が現在のステートを表している。start_state がスタートだけれども、slc は18ビットのシフトレジスタに値をロードしているので、最後の200KHzで2クロック分のみを使用している。最初はダミーなので、効率が悪いが最初に設定するだけなので、スピードは必要ない。よって、わかりやすさを優先して、このような実装となった。
id_address は8ビットの42を出力して、最後にドントケアビットがある(ハイ・インピーダンス)。
sccb_reg_addr はSCCBレジスタのアドレスを示していて、この場合はAC番地を表している。やはり、最後にドントケアビットがある。
write_data はsccb_reg_addr に書き込みデータを示している。ここではDF を書き込む。やはり、最後にドントケアビットがある。
最後に、stop_state はstop_state 同様に効率が悪い。最初の200KHzで2クロック分のみを使用している。
さて、うまく行ったようなので、今度はインプリメントして確かめてみることにする。うまく行ったら、このソースを公開するかも?
2009年12月21日 22:07 |
画像処理
| トラックバック:0
| コメント:0
昨日は久しぶりに木工をやらない休日でした。そのかわりに、お買い物日です。
久しぶりに、お昼に
一麺の塩ラーメン を食べました。寒い日に、ここの塩ラーメンは美味しい。。。ファンです。
その後、イーアスのユニクロへ。軽量ダウンジャケットを買おうとしましたが、着てみたら、ものすごい静電気。。。人間静電試験器になる気はなかったので、買うのをやめました。これでFPGA基板を持ったら確実にFPGAを静電破壊しそう。。。結局、ユニクロではアンダーシャツ2枚とヒートテックのタイツを購入。
次は、息子を塾に送ってから、下妻のジャスコに。2万円以内の16インチ地デジ液晶テレビを買いに行きました。古いテレビも処分のために持って行きました。16インチ地デジ液晶テレビは
ピクセラのPRD-LA103-16B です。これでエコポイント
6,000 7,000ポイントと家電引取りの3,000ポイント付くので、古家電処理料を入れても、実質
13,000円 12,000円くらいでした。
次に、ホームセンターで
私が持っているパナソニックのインパクトドライバー と同じものが14,800円で売っているということなので、買いに行きました。EZ7206PRK-Hと型番にPが余計についていますが、バッテリーが同じなら問題ありません。パッテリーは定価で1万5千円、買値で1万円くらいしますので、同じ充電池を使うインパクトドライバーがあったら良いと思っています。残念ながら、モノが売り切れで予約してきました。
それから、私は家具作りサークルの会長にされていますが、つくば市に土日に来られる方で家具作りをやりたい方、一緒に家具作りをやりませんか?先生が道具を貸してくれて、丁寧に教えてくれます。ただし、車でないと来るのが大変です。年会費、2,000円です。他に材料費がかかります。興味のある方は、
Profile に書いてあるメールアドレスにメール下さい。
2009年12月20日 08:03 |
日記
| トラックバック:0
| コメント:0
”
VHDLでのブロックRAMや分散RAMの初期化(外部データファイル) ”の続き
”VHDLでのブロックRAMや分散RAMの初期化(外部データファイル)”では、外部データファイルを16進で書くことができなかったが、どうも2進数で書くとわかりづらいので16進数で書く方法を模索することにした。やってみたら書くことができたので、ブログに書いておくことにする。
さて、hreadを使えば16進数で読めるようになるのだが、前回はhreadを書いてもエラーになってしまった。hreadが定義されているのはstd_logic_textio.vhdなので、これを見ると、out の属性はstd_logic_vecter になっている。そうか、前回はbit_vector で記述されていたからエラーだったんだ。。。早速、定義のところをstd_logic_vectorに変更したところ、論理合成が通った。嬉しい。。。
そのソースを下に示す。
library IEEE, STD; use IEEE.std_logic_1164.all; use STD.textio.all; use IEEE.std_logic_textio.all; use IEEE.std_logic_unsigned.all; use IEEE.std_logic_arith.all; -- pragma translate_off library UNISIM; use UNISIM.VCOMPONENTS.ALL; -- pragma translate_on entity idram is port( clk, reset : in std_logic; wr : in std_logic; iad, dad : in std_logic_vector(7 downto 0); ini : in std_logic_vector(15 downto 0); iout, dout : out std_logic_vector(15 downto 0)); end idram; architecture RTL of idram is type RamType is array(0 to 255) of std_logic_vector(15 downto 0); impure function InitRamFromFile (RamFileName : in string) return RamType is FILE RamFile : text is in RamFileName; variable RamFileLine : line; variable RAM : RamType; begin for I in RamType'range loop readline (RamFile, RamFileLine); hread (RamFileLine, RAM(I)); end loop; return RAM; end function; signal RAM : RamType := InitRamFromFile("idram.data"); begin -- データ用RAM process (clk) begin if clk'event and clk = '1' then if wr = '1' then RAM(conv_integer(dad)) <= ini; end if; dout <= RAM(conv_integer(dad)); end if; end process; end RTL;
下の記述もすっきりした。
さて外部データファイルの一部を下に示す。
0101 1234 3456 FF00 0000 0000 0000
これでインプリメントするとBRAMにマップされる。それをFPGA Editor で見てみたのが下の図。
ピンクの四角で囲んだ部分に外部データファイルのデータが入っているのが分かる。
これで、16進数の外部データファイルで見やすく書くことができる。
2009年12月19日 05:30 |
VHDLの書き方
| トラックバック:0
| コメント:0
Notepad++でHDLファイルをいじっていると、このプロジェクト(プロジェクトA)を編集しているのだけど、ちょっとこっちのプロジェクト(プロジェクトB)を編集したいというときがある。その場合に、数多くのプロジェクトAのファイルの中にプロジェクトBのファイルがちょこっと混じっていると、どうも見にくいし、ミスる可能性が増える。
そのような場合にはNotepad++ のセッション機能を使うと良いと思う。
さて、それじゃ使ってみよう。2つのVHDLファイルが開いている状態で、ファイルメニューから”セッションを保存”を選択。
保存ダイアログが開くので、idram.sessoin と名前をつけてセッションを保存する。
これでセッションが保存できた。
例えば、他のプロジェクトを編集しいて、今、保存したセッションを読み込むには、
1. ファイルメニューから”すべて閉じる”を選択して、全部ファイルを閉じる。
2. ファイルメニューから”セッションを読み込む”を選択する。
3. ダイアログからidram.session を選択して開くボタンを押すと、さっきのファイル構成が再現される。
色々なセッションを作れば、そのプロジェクトのファイルだけを手軽に編集することができるだろう。
2009年12月19日 00:01 |
EDAツールについて
| トラックバック:0
| コメント:0
”
SCCBインタフェース回路の実装1(タイミングチャート) ”でタイミングチャートを作成した。今度は回路構成を考えてブロック図を書いてみることにした。
最初に、SCLを100KHz、10usec 周期にすることにした。SCCBインタフェース回路が動作する周波数(イネーブルを入れるタイミング)はその倍の200KHz とする。これはクロックをシフトレジスタで生成する都合からそうなった。
まずは制御部のメインのステートマシンを下に示す。
メインステートマシンは、ごくごく当たり前の構成になっている。
次に、シリアルデータの出力方法だが、ブロック図を下に示す。
メインステートマシンでの各ステートのデータのパターンとクロックのパターンを、18ビット長のシフトレジスタに最初にロードして200KHz (5usec) ごとに送出することにより、シリアルデータを出力する。SDAの方は確実にSCLより遅れるようにFF2段を通過されることにする(ここのFFのクロックは25MHz)。その後、ドントケアビットのためにトライステート・バッファをつけてある。そのトライステート・バッファは、シフトレジスタを駆動するクロックで動くCounter(9ビット目)とID_Address、SCCB_Reg_Addr、Write_Data の各ステートのANDをとった信号でハイ・インピーダンスになるようにする(ドントケアビット)。
クロックの方も出たり出なかったりするので、このような構成にすることにした。これでSCCBレジスタに値を書き込むI2C似のプロトコルの方のブロック図は完成した。
次に、もう1つ上のレベルでに設計だが、BRAMを1つ使って、値を変更するSCCBレジスタはBRAMにアドレスと値を書いていくことにする。それを見て上に書いたブロック図の回路がSCCBプロトコルでSCCBレジスタに値を書いていく。最後にアドレスがFFのエントリを検出したら終了とする。
アドレスと値の設定方法だが、”
VHDLでのブロックRAMや分散RAMの初期化(外部データファイル) ”を使用して外部のファイルにアドレスと値を1列に書いて、BRAMへデータをイニシャライズすることにする。このブログ記事の例では1列に1つのデータだが、2つのデータに拡張できるはずである。よってBRAMのデータ幅は16ビットとする。
これでやっとVHDLで書くことができるようになったので、次は、VHDLで書いていくことにする。
(2009/12/21:追記)
シリアルデータの出力回路のブロック図を変更したので、下に書いておく。やはり、SDAは18ビットは必要ないと考えた。SLCの2回シフトに付き1回シフトする。それから、SLCとSDAをIOBのFFに入るようにする。SDAのトライステートバッファのイネーブルを正しい形に変更した。トライステートバッファのイネーブルは必ずFFからの出力とする。ここを組み合わせ回路にしてしまうと、特にFPGAではどこにひげがでるか分からないので、必ずFFからの出力とする。
2009年12月16日 06:04 |
画像処理
| トラックバック:0
| コメント:0
SCCB (Serial Camera Control Bus) のインターフェース回路を実装することにした。
第1段階は、SCCBプロトコルを調べることだ。SCCBプロトコルはI2Cバスに似ている。I2Cバスについては、”
やまねこのマイコン実験室、I2Cバスを使ってみよう ”や”
I2C通信の使い方 ”に詳しく書かれている。
それによるとI2Cは、SCL, SDAともにオープンドレインで、スレーブ側からのビジー通知はスレーブがSCLをローにドライブすることによってマスタに通知するそうだ。SCCBはその使い方はできないので、SCCBはI2Cのサブセットということができると思う。
SCCBプロトコル仕様はここにある 。この仕様はほとんど3線式SCCBについて書かれているが、2線式はI2Cバスの仕様に沿う形で良いようだ。どうもいつもマニュアルが不完全だ。。。
仕様をタイミングチャートにしてみた。下図に示す。
FPGAのSCCBインターフェース回路がマスタで、CMOSカメラ側がスレーブになる。上の例はSCCBレジスタ12番地に80、つまりレジスタのオールリセットを行うコマンドだ。
最初にスタートビットがある。それは、I2Cと一緒でSCLが1の時にSDAを0にドライブする。その時のタイミング制約がtSU:STAとtHD:STA。次に”01000010"と出力する。この場合、必ず、SDAはSCLが0の時に変化させる。SCLが1の時にSDAのデータが確定される。ちなみに最後の0は0がWrite、1がReadを表す。つまり16進で書くと、42がWrite、43がReadとなる。そのデータは
OV7640のマニュアル の10ページの最初の数行に書いてある。このID Address をアクセスすれば、OV7640、OV7725にアクセス出来るようだ。その時のタイミング制約がtSU:DAT、tDH:DATになる。
次に、マスタはSDAのドライブをOFFする。これはACKのはずなんだが、CMOSカメラ側がドライブするようだ。その次は、Sub-address でここにSCCBレジスタのアドレスを入れて、CMOSカメラに送る。このアドレスは”00010010”で16進で書くと12だ。次にWriteするデータ、”10000000”、16進で書くと80をマスタは出力する。
最後にストップのシーケンスがある。これはSCLが1の時にSDAを0から1に変化させる事によって、ストップとなる。その時のタイミング制約がtSU:STOとなる。次のSCCBのデータ転送が始まるまでの制約がtBUFになる。
だいたい、タイミングが分かったので、次はどのように実装するかを考える事にする。
2009年12月15日 06:02 |
画像処理
| トラックバック:0
| コメント:0
昨日、シナランバーコア合板で机を作った。今までの2X4材で作った机は、少しでこぼこしていたので、家具を組み立てるときに微妙に合わないことがあった。それで、水平がでる机が欲しかったので、シナランバーコア合板を天板として、足を2X4材で作った。
机の上に載っているのが、今度、購入したブロアとベルトサンダー。ブロアはのこぎりのクズを吹き飛ばすのに使用する。とても便利。ベルトサンダーは、ウッドデッキ用のテーブルの上の研磨に使用する。ベルトサンダーが一番研磨力が強いサンダーだ。ウッドデッキ用のテーブルの上を研磨してみたが、ベルトサンダーは言ってみれば、紙やすりのキャタピラがついた戦車で、しかも強力なモーターがついている。よって、研磨するにはベルトサンダーが進まないように押さえて置く必要がある。考えてなかった。。。結構大変。。。
ウッドデッキ用テーブルと椅子が今日、完成。後は塗装するだけだが、今のところ、以前のウッドデッキと同じタンネン・グリーンに塗装する予定だそうだ。
これで購入した2X4X10F は1本を残して使い切った。後は、短いのが10本くらい残っているだけだ。無料で8F から10F にアップグレードできてラッキーだった。テーブルと椅子の分の木材を買わなくて済んだ。
2009年12月13日 20:14 |
木工
| トラックバック:0
| コメント:0
twitter のNafitafuさんのつぶやきでISE11.4が出たことを知ったので、早速、ISE11.3を立ち上げてXilinx Updataをした。
その時の画面を下に示す。
ISE Design Suite 11.4 Software Updates は35MB だから大した違いはないのかも?IP Updata が大きい。
EDK11.4 は
なひたふさんによるとEARLY ACCESS ながらSpartan-6に対応 したようだ。
1時間以上ダウンロードしているが、今のところ、ダウンロードは74%。
午前6時58分にインストール終了。リブートを要求されたので、リブート。
ISEが立ち上がったが、ISE11.4と表示されるほかは外見的には変わったところはない。
新機能を見るとSpartan-6の新しいスピードグレードのサポートくらいみたい。あまり大きくは変わっていないようだ。
パーシャル・リコンフィギュレーションが標準で可能な来春のISE12.1が楽しみ。。。
2009年12月12日 05:54 |
Xilinx ISEについて
| トラックバック:0
| コメント:0
”
YUV-RGB変換6(やったー、うまく行きました) ”でできたと思ったYUV-RGB変換。早速、先生に見せたら欠点を指摘されてしまった。でも確かにそう。。。
それは、輝度が急激に変わるところが飽和しているように見えるということだ。下の写真はCMOSカメラからディスプレイに表示した画面をデジカメで取ったものの一部を拡大している。それはどの部分かと言うと、パソコンの液晶ディスプレイの枠とその表示画面の間が問題となった。黒い枠と広く光る画面の境にピンクの矢印で示す白い線が入っているのがわかる。なぜこの白い線が出るのかが問題だ。
この線は輝度が極端に変わる部分に現れる。例えば黒いコードと白っぽい風景とか。下の写真はダウンロードケーブルのコードの周りにできた白い線だ。なんか飽和しているように見える。もしくはエッジ検出しているみたい。
どうしてこうなるのか?YUV-RGB変換がいけないのか?それとも元からなのか?
原因究明のため、Y信号だけを表示してみた。それが下の写真。カラーの時と同じ場所を写した写真だが、特に黒いケーブルの周りが白くなっているのがわかるとおもう。(下の写真をクリックして拡大してみると、良く見えます)
本当に輝度信号からおかしいのか、ChipScopeを入れてデータを見てみることにした。使用したのは、下の写真のような画像だ。どこがポイントかと言うと、VGA信号の最初に輝度がおかしい処を持ってくるようにした。そうすると、ChipScopeのトリガは最初の水平描画信号のスタートでかければ良いことになるからである。つまりディスプレイの枠と液晶表示画面のふちの境界の白く飽和している部分が左上端にある画像ということになる。
これをChipScopeでみたのが下の図になる。
cam_ydata_2d がCMOSカメラから来たデータとなる。r_w が0の時がYUVのうちのY(輝度信号)が出力されている。その部分をピンクの四角で囲んである。それは、VSYNCが来てから最初のHREFが1になった時の最初のデータから35個目のデータだ。そのなかで輝度データを見ると、86, FF, FF, 00, 00, 35, 35 となっていて、FFから00に飛んでいる部分がある。やはり、この部分が問題だと思う。CMOSカメラに原因があるようだ。
これは、SCCBバスのコントローラをやはり、早急に開発してCMOSカメラの設定をいじってみる必要がありそうだ。
#そういえば、デバックの過程でRGBの飽和演算を外してみた。その時は、蛍光灯やその辺の輝度が高いところが黄色になった。黄色は赤と緑の混合色なので、青が飽和しているようだ。つまり青は飽和しやすいと思う。それは計算式を見ても言えるのではないだろうか?
(追記)
”
CMOSカメラから画像を入力してディスプレイへ出力15(できた!!!) ”の下の画像は、輝度の変化が大きいところでも正常に表示されている。(でも、うっすらと見えるのかな?少なくとも、はっきりは分からない)
これは、基板も違うが、CMOSカメラもKBCR-M03VG (OV7760)だった。ここで使っているCMOSカメラは、KBCR-M04VG (OV7725)。
もし何か情報があれば、ぜひ教えて下さい。よろしくお願いします。
2009年12月11日 04:51 |
画像処理
| トラックバック:0
| コメント:15
”
YUV-RGB変換5(インプリメントして基板にコンフィグ )”の続き。
25MHzのクロックを半分にして、12.5MHzをCMOSカメラに供給するために、DCM_module_25MHz.vhd のDCM1/2の分周比を2から4に変更した。つまり50MHzの2分周を4分周の12.5MHzに変更した。このクロックをコネクタに出力して、オシロで見てみた。
12.5MHzが出力されている。これでHSYNC, VSYNCとも正常に戻ったはず。とりあえず、ディスプレイにつないでみた。
その結果、画像は出たが、あれ~、なんか色がおかしい。なんか青が無い。。。
上の写真で青いうちわを写したら、ディスプレイでは黒くなってしまった。どこかがおかしい。早速、VHDLコードを点検。そうすると、下の図のピンクで囲った部分を見てみると、blue に sat_conv_r を代入している。
これはバグなので、blure <= sat_conv_b; に変更して、インプリメントし、ボードにダウンロードした。
そうしたところ、正常に色が出て、YUV-RGB変換が完成した。うれしい~。
非常に綺麗に色が出ている。思ったより画質が良いみたいだ。
ご助言いただいたみなさん。ありがとうございました。
2009年12月09日 21:11 |
画像処理
| トラックバック:0
| コメント:2
”
YUV-RGB変換4(シミュレーション) ”の続き。
前回、シミュレーションが終了したので、インプリメントするためにUCFに2つ目のSRAMのIOパッドを加えてインプリメントした。何回かやって成功した。
次は基板にコンフィグして動作するかどうか確かめる。うまく行けばYUV-RGB変換したあとのカラーの画像が見れるはず。。。
これから基板にダウンロードする。下が基板の写真。
ダウンロードケーブルを接続して、iMPACTからダウンロードした。液晶ディスプレイを見ると、同期範囲外で同期が外れている。いかにもおかしい、ということでオシロで同期信号を見てみることにした。
まずは HSYNCから。HSYNCの出力波形を下に示す。
VGAの信号フォーマットを下に示すが、32usec のはずが出力されているのは16usec で、半分の周期、倍の周波数だった。これじゃ、同期範囲外ですね。
#私もオシロを使っているので、HDLコード屋からハード屋さんに昇格かな?
念のために VSYNCも波形を見てみた。
やはり、8.32msec で半分の周期。これは同期が取れない。
次にどこで2倍の周波数になっているのかを検証してみることにした。
クロック関係のブロック図を下に示す。
次にクロック関係のVHDLコードを下に示す。
DCM_module_25MHz_inst : DCM_module_25MHz port map( clk50MHz_in => clk, clk50_out => clk50, 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; -- 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' );
上の図のDCM1/2 の24MHzクロック出力が cam_clk_nodeだ。これはODDR2_for_cam_clk のODDR2で クロッキングされてcam_clk としてCMOSカメラに供給されている。CMOSカメラからはPCLKが出力され、それが DCM_module_25MHz_instのpclk_in (図で言うとDCM1/1)に入って、mclk_out から mclkとして出力され、すべてのモジュールに供給されている。
まずは、mclkをコネクタに出力して、オシロで見てみることにした。その波形を下に示す。
ひえ~、50MHzでした。これじゃ当たり前。予定の2倍の周波数です。念のために、cam_clk_nodeをコネクタに出力して見てみた。(下図参照)
これは正常。するとCMOSカメラでクロックが2倍になっているんだな?
そこで、もう一度、OV7725のデータシートを確認。なんだ、デフォルト値が書いてあるんじゃないですか。。。見落としていました。申し訳ない。。。
気を取り直して、デフォルト値でどこか悪いというか、そういう設定になっているかを検証。
そうすると、アドレス11の CLKRCのデフォルト値が 80だった。bit6が外部クロックをダイレクトに使用するというビットでこれは立っていない。bit5 - 0 が内部クロック・プリスケーラで、内部クロック = 入力クロック/(bit5-0 + 1)/2 だそうだ。/2 がどこにかかるか分からないが、入力クロック/((bit5-0 + 1)/2) だとしたら、現在の現象と合っている。
解決策としては、今まで入れていた25MHzのクロックを半分にして、12.5MHzをCMOSカメラに供給することにした。
しかし、やはりSCCBレジスタを設定するI2Cのモジュールを作成することにしたい。YUV-RGB変換が終了したら作ろうと思う。それでもわからないフォーマットがあるんだけど。。。
2009年12月09日 05:44 |
画像処理
| トラックバック:0
| コメント:6
DE0で、自作ソフトからAvalonバス上のJTAG-UARTとやり取りできないかと思っている。それの覚書。
ネットで検索していたら、
niosforum.comの記事がヒット 。
それによると、nios2-terminalのstdin/stdoutを自作ソフトにリダイレクトするようだ。リダイレクトするソフトウェアは、
Redirecting an arbitrary Console's Input/Output にあるそうだ。
まだ、確かめていない。そのうちに試してみよう。
まずは、nios2-terminalはeclipseからしか起動したことが無いので、これを起動するところから始めないと。。。
2009年12月08日 05:47 |
AlteraのFPGA
| トラックバック:0
| コメント:0
2010年1月29日(金)に東京コンファレンスセンター・品川 5 Fで開かれる
無償テクニカル・セミナー X-fest 2010 に申し込んで受講票が届きました。
コース選択は下の通りです。
10:00 ~ 10:50 基調講演: 近年の半導体市場の動向に呼応する代理店商社の役割について 11:00 ~ 11:50 Xilinx FPGA検証を効率的に行うActive-HDLのご紹介(アルデック・ジャパン株式会社)、アサーション・ベースのシミュレーション活用(メンター・グラフィックス・ジャパン株式会社) 13:00 ~ 13:50 Spartan-6 Hard Memory Controller を使用した外付けメモリーのインターフェースの設計 14:00 ~ 14:50 Spartan-6 ギガビットトランシーバとPCI Expressエンドポイントブロックの設計 15:10 ~ 16:00 最新FPGA用オンボードDC-DC電源モジュールの提案と最適設計のポイント 16:10 ~ 17:00 ザイリンクス社製VIRTEX®-6対応PCI Express®用iDMAC®ソリューション
お昼がでる他に、なんか、ニケ・ボードという、配布用評価基板を配布予定だそうです。
べにいた掲示板 という評価基板のブログもあるようです。
安価に配布なんでしょうか?もしかして無料ですか?そう考えるのは図々しいですよね? 無償だそうです。凄い、太っ腹ですね。。。
主な仕様は下のとおりだそうです。(
ここより転載 )
■ 500Ksps、16ビット、A/Dコンバータ ■ 高精度16ビット、D/Aコンバータ ■ 32ビット Coldfire ® マイコン ■ 128Mビット PCM(相変化メモリ) ■ 3軸センサ ■ 温度センサ ■ リセット付き電源監視回路IC ■ 電源IC(負電源を含む) ■ 各種高精度オペアンプ ■ 2.8W、D級モノラルオーディオ・アンプ ■ USB経由による簡易なソフトウェア・アップデート ■ 無償開発ソフトウェア環境によるコード開発 ■ 2x20ヘッダ経由による、アヴネット製Spartan ® -6 LX16 FPGA評価キットとのダイレクト接続
盛り沢山です。セミナーでもこのボードのセミナーがありました。とりあえず、他のセミナーが聞きたいので、聞く予定は無いんですが。。。
”Spartan-6 Hard Memory Controller を使用した外付けメモリーのインターフェースの設計”と”Spartan-6 ギガビットトランシーバとPCI Expressエンドポイントブロックの設計”が楽しみです。
2009年12月08日 05:37 |
その他のFPGAの話題
| トラックバック:0
| コメント:6
”
YUV-RGB変換3(画像ボードやタイミングの再検討) ”の続き。
YUV-RGB回路のコーディングが終了したのでシミュレーションをしてみた。
まずはストラテジーを説明すると、下のタイミングチャートを見るとわかる通りに、SRAMの帯域はYに対してUVは1/2を割り当ててある。つまりSRAMにWriteする部分ではYUV422をそのままWriteする。
よって、モジュールの機能は少し違うが下のブロック図でいうと、VGA_Display_Controller にYUV-RGB変換回路を実装してある。
VGA_Display_Controller がYとUVデータを読み込み、1クロック分保存する。それは、上のたタイミングチャートを見るとわかるが、SRAMにWrite、Readアクセスを交互に行っているからだ。Readは1クロックおきとなるので、16ビット長のReadされたYデータは現在のクロックで上位8ビット、次のクロックで下位8ビットと使用する。UVデータはReadされた16ビット長の上位8ビットにUデータが、下位8ビットにVデータが割り当てられている。UVデータは8ビットだけなので2クロック間同じデータを使用する。
YUV-RGB変換のVHDLコードを下に示す。後で作成する画像処理回路のために掛け算器はできるだけ温存しておくつもりなので、掛け算器を使わずにあえて足し算で記述することにした。
-- YUV-RGB変換 U=pixel_uv_data(15 downto 8), V=pixel_uv_data(7 downto 0) -- R = (Y<<8 + "1_0110_0100"*V - X"B380")>>8 -- G = (Y<<8 - "1011_0111"*V - "0101_1000"*U + X"8780")>>8 -- B = (Y<<8 + "1_1100_0110"*U - X"E300")>>8 y <= pixel_y_data(15 downto 8) when data_enable='1' else pixel_ydata_1d(7 downto 0); u <= pixel_uv_data(15 downto 8) when data_enable='1' else pixel_uvdata_1d(15 downto 8); v <= pixel_uv_data(7 downto 0) when data_enable='1' else pixel_uvdata_1d(7 downto 0); conv_r <= ("000" & y & "00000000") -- Y<<8 + ("000" & v & "00000000") -- "1_0000_000"*V + ("00000" & v & "000000") -- "100_0000"*V + ("000000" & v & "00000") -- "10_0000"*V + ("000000000" & v & "00") -- "100"*V - ("000" & X"B380"); -- R = (Y<<8 + "1_0110_0100"*V - X"B380") conv_g <= ("000" & y & "00000000") -- Y<<8 - ("0000" & v & "0000000") -- "1000_0000"*V - ("000000" & v & "00000") -- "10_0000"*V - ("0000000" & v & "0000") -- "1_0000"*V - ("000000000" & v & "00") -- "100"*V - ("0000000000" & v & "0") -- "10"*V - ("00000000000" & v) -- V - ("00000" & u & "000000") -- "100_0000"*U - ("0000000" & u & "0000") -- "1_0000"*U - ("00000000" & u & "000") -- "1000"*U + ("000" & X"8780"); -- G = (Y<<8 - "1011_0111"*V - "0101_1000"*U + X"8780") conv_b <= ("000" & y & "00000000") -- Y<<8 + ("000" & u & "00000000") -- "1_0000_0000"*U + ("0000" & u & "0000000") -- " 1000_0000"*U + ("00000" & u & "000000") -- " 100_0000"*U + ("000000000" & u & "00") -- " 100"*U + ("0000000000" & u & "0") -- " 10"*U - ("000" & X"E300"); -- B = (Y<<8 + "1_1100_0110"*U - X"E300") -- 飽和演算と丸め+右8ビットシフト process(conv_r) begin if conv_r(18)='1' then -- 値がマイナスの場合 sat_conv_r <= (others => '0'); elsif conv_r(17)='1' or conv_r(16)='1' then -- 飽和 sat_conv_r <= (others => '1'); else -- 右8ビットシフト sat_conv_r <= conv_r(15 downto 8); end if; end process; process(conv_g) begin if conv_g(18)='1' then -- 値がマイナスの場合 sat_conv_g <= (others => '0'); elsif conv_g(17)='1' or conv_g(16)='1' then -- 飽和 sat_conv_g <= (others => '1'); else -- 右8ビットシフト sat_conv_g <= conv_g(15 downto 8); end if; end process; process(conv_b) begin if conv_b(18)='1' then -- 値がマイナスの場合 sat_conv_b <= (others => '0'); elsif conv_b(17)='1' or conv_b(16)='1' then -- 飽和 sat_conv_b <= (others => '1'); else -- 右8ビットシフト sat_conv_b <= conv_b(15 downto 8); end if; end process;
19ビットで演算をして、最上位ビットが立っている場合は、マイナスなので0に丸めた。絶対値の方が良いのかどうか分からないが、とりあえず0としてみた。16ビット目と17ビット目が立っている場合はオーバーフローなのでX"FF"に設定した。それ以外の場合は8ビット右シフトを行った。
シミュレーションのwaveウインドウのYUV-RGB変換結果の部分を下に示す。
これは0ラインの最初の部分だが、ピンクの四角で過去った部分はYが55、Uが55、VがAAとなっている。それを右8ビットシフトする前のYUV-RGB演算値がconv_r, conv_b, conv_g である。その値をもとに飽和演算した値が、sat_conv_r, sat_conv_b, sat_conv_g となる。conv_r だけ手計算してみたが値は合っていた。結構面倒で、あまり手計算したくなくなったけど。。。
というわけで、だいたいできたので、今度はインプリメントして確かめてみるが、その前に1つSRAMを増やしたので、UCFを作り直す必要がある。
テーマ:ハードウェア - ジャンル:コンピュータ
2009年12月07日 05:26 |
画像処理
| トラックバック:0
| コメント:0
今日は背もたれなしの椅子を2つ作った。ウッドデッキの余りの木切れで作ったので、長さは約65cmになった。高さは38cm、幅は37cm。
2つ同じ高さに作ったので、2つ並べると長椅子とおなじになる。あと2つ作る予定。
最初、9mm のドリルで裏に穴を掘って、そこからコーススレッドで止めようとしたのだが、やはり十分な下穴をあけても天板が浮いてしまう。それに9mm のドリルのクズがすごくて足と天板の間に入ってしまう。スゴク難しい。結局、天板の上からコーススレッドで止めるのが一番楽だった。この辺の試行錯誤で1台目はすごく時間がかかってしまった。。。
次回、正確に水平がでる机をランバーコアで作る予定だが、その時はやはり、天板からではなく、足の台から止める必要がある。その場合は9mm のドリルで裏に穴を掘って、一旦、足を外してお掃除して、もう一度載せて、3mm のロングドリルで下穴あけして、クランプで止めながらコーススレッドを打っていこうと思っている。
2009年12月06日 18:00 |
木工
| トラックバック:0
| コメント:0
このところ家でも職場でもVHDLばかりで、そろそろVerilogが恋しくなってきました。(職場の下地を家で書いているのでしょうがない面はあるんですが。。。)
Verilog2001で書いてきましたが、そろそろ世の中はSystemVerilogですかね?そういうわけで本は買ってあるんですが、まだ読んでいないです。AlteraのQuartus2は対応しているみたい(一部書けないのもあるとか?)ですし、Xilinxはそのうち対応するという期待があります。今のうちに勉強しておいてシミュレーションだけでもSystemVerilog (SV)にできたらいいな?ということで勉強するつもりになりました。
SVと言えば、
Veritak もSV対応のシミュレーターを開発していたはずということで、Webサイトを見てみました。
すると
Veritak F.A.Q. の710によると”2010 4Q : Support Basic feature of SV. 2011 : OVM/VMM support w/o assertions/coverage.”だそうです。さらに712を見ると
SystemVerilog Tutorial がありました。SVの実装面からの新機能が事例付きで解説してあって、読んでいると勉強になります。暇なときに心がけて勉強したいと思います。
2009年12月05日 06:08 |
SystemVerilog
| トラックバック:0
| コメント:2
DE0を使ってみる機会ができたので、使ってみた。
おもむろに電源ONすると、7セグLEDが1.1.1.1~F,F.F.Fまで順番に表示して、LEDが順番に点灯し続けた。
ディスプレイをつなぐと画面が出力された。
Sim's blogさんで話題のDVDに入っているDE0_ControlPanelを動作させてみた。USBケーブルを差して、DE0_ControlPanel.exeを起動すると、スイッチの設定を見たり、LEDを制御できたり、いろんなことができる。
最初のタブはチェックしたLEDを点灯させることができる。
7セグLEDの状況も設定できる。
上の設定をしたDE0がこれ、LEDが2個、7セグLEDは1234を表示している。
次のタブはスイッチ、スライドスイッチを操作したり、押しボタンスイッチを押したりすると画面に反映される。
SDRAMへの書き込み、読み出しテスト、多分FLASHへの読み書きもできる。
PS2のキーボードのテスト。キーボードをつなぐと文字が表示される。
最後にVGAテスト、表示させるパターンを選ぶとVGA信号をつないだディスプレイに表示される。
これは、DE0_ControlPanelでDE0_ControlPanel.sofという回路をDE0にコンフィグしているようだ。DE0のユーザーズマニュアルを見ると下の図が載っている。(転載します)
Nios2が入っていて、JTAGでパソコンと通信している。この辺はSimさんのブログの”
Altera DE0のJTAG通信? ”に詳しく書かれているが、私もちょっと調べてみたい。とおるすがりさんご紹介の
FPGA BBSのスレッド に詳しく書かれているようだ。
DLLやアプリを解析するソフトのDependency Walkerで解析してみた。(
Dependency Walkerの本家はここ 、
日本語パッチはここ から入手した。
使い方はこの辺 。)
DE0_ControlPanelをDependency Walkerで開いてみる。
これだけでは、TERASIC_JTAG.dllとかが出てこないが、プロファイリングを行うと、ツリーに出てくる。余り書くとリバースエンジニアリングになってしまうので、書かないが、TERASIC_JTAG.dllからTERASIC_JTAG_DRIVE.dllが呼ばれている感じ。コンフィグすると実際には、もう2つくらいアプリが起動する。でも、コンフィグはタイムアウトで成功しなかった。
メーカーが仕様を公開してくれないとやはりまずいので、この辺でリバースエンジニアリングはやめることにした。
でも、パソコンから簡単にUSB-JTAG経由でやり取りできると実験のプロセッサ用ボードとして非常に都合がよい。アバロンバスにNios2をつながないで、JTGA UARTと独自プロセッサをつないで、パソコンの独自アプリとJTGA UART間で通信して、そのデータをアバロンバス経由で独自プロセッサに渡せれば良いんだけど。。。その可能性を探ってみようと思う。
2009年12月04日 05:54 |
Altera DE0ボード
| トラックバック:0
| コメント:2
11月のキーワードベスト30を発表します。
やはり1, 2番は”FPGAの部屋”のようだ。3番目は”tortoisesvnの使い方”。案外、このようなツールの使い方が入っている。8番の”notepad 使い方”もそうだ。”jude シーケンス図 書き方”、”qucs”、”Kicad 使い方”。
”psoc”も上位に来ている。
おもしろいところでは、デジタルカメラ、”optio e75”が4位になっている。結構、このデジカメは検索が多い。安いカメラとして出回っているのかな?私は便利に使っている。不満も私の用途では特にない。
”同期リセット 非同期リセット”や”非同期FIFO”もランクインしている。
おもしろい?のは、”FPGAカフェ”が30位にランクインしている。注目されているようですよ。すすたわりさん!
さて、2009年の1月から11月までのアクセス数を下に示す。
でこぼこはあるが増える傾向だと思う。皆さん、見ていただいてありがとうございます。
1月から11月までで441,719アクセスだった。FPGAも注目されてきているのかな?
2009年12月02日 20:26 |
日記
| トラックバック:0
| コメント:0