FC2カウンター FPGAの部屋 OV9655

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

FPGAの部屋

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

OV9655でSXGAを表示3(表示できた)

色々とビット幅がミスっていたが、(しかし、Verilogはビット幅が間違っていてもエラーがでないものか?)やっとまともにSXGAの画像を表示することができた。ヤッター!
OV9655_9_110128.jpg
(SXGAです。PCLK 48MHz、15fps)

OV9655は現在の設定では?、暗さに弱いようだ。上の画像は照明が暗いので、明るいところではもっと良い画像になった。
OV9655_10_110128.jpg

OV7670のS/N Rate は46dB、Dynamic Range は52dBに対して、
OV9655のS/N Rate は42dB、Dynamic Range は50dB なので、OV9655は画素が多い分、大きさが小さいのだろうか?

ともかく、目的は達成した。やはり、SXGAの方が綺麗だ。後は、RGB各4ビットではビット数が少ないので、買ってあるChrontel のCH7301Cを使って、RGB各8ビットのDVI-Iで出力したい。そのためには、Spartan-3A Starter Kit の拡張ポートの基板を設計して、どこかに作ってもらう必要がある。4層基板で作りたいな?と思っている。

  1. 2011年01月28日 19:02 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:4

OV9655でSXGAを表示2(FIFO容量の変更、SXAGへのタイミング変更)

OV9655でSXGAを表示1(FIFO容量の再検討)”でFIFO容量の検討をした。その検討結果を元にCoreGenのIPを変更する。更に、SXGAの解像度にタイミングを変更する。

Camera_Controller 用のFIFOのcam_cont_afifoを開いた。下図参照。
OV9655_6_110126.png

Write Widthは16ビットでWrite Depthは64(8ビット換算では128深度)なので、すでに十分な容量がある。これはこのままとする。

次に、VGA_Display_Controller 用のcam_data_afifoを開いた。下図参照。
OV9655_7_110126.png

このFIFOは半分の容量だったので、Write Width 32、Write Depth 256, Read Width 16, Read Depth 512 に変更した。

VESA Signal 1280 x 1024 @ 60 Hz timing”を参考にdisp_timing_parameters.vhを変更した。

// 表示タイミングの定義 (1280 x 1024)

parameter H_ACTIVE_VIDEO= 1280;
parameter H_FRONT_PORCH = 48;
parameter H_SYNC_PULSE = 112;
parameter H_BACK_PORCH = 248;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

parameter V_ACTIVE_VIDEO = 1024;
parameter V_FRONT_PORCH = 1;
parameter V_SYNC_PULSE = 3;
parameter V_BACK_PORCH = 38;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

parameter H_DISPLAY_SIZE = H_ACTIVE_VIDEO/8; // 横160桁
parameter V_DISPLAY_SIZE = V_ACTIVE_VIDEO/8; // 縦128行

parameter RED_DOT_POS = 9; // 9ビット目がRED
parameter GREEN_DOT_POS = 8; // 8ビット目がGREEN
parameter BLUE_DOT_POS = 7; // 7ビット目がBLUE


後は、カウンタのビット長などを変更している。思ったより、手間がかかりそう。ピクセルクロックは108MHz、フレームレートは60Hzと書いてあったが、62Hz程度だった。


次回は、OV9655の設定を決めて、SXGA画像の表示を試みる。
  1. 2011年01月26日 05:26 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:0

OV9655でSXGAを表示1(FIFO容量の再検討)

OV9655を使ってみる4(VGAの表示)”でOV9655でVGAを表示できたので、今度はSXGAを表示してみたい。

前回、”OV9655を使ってみる3(回路の書き換え)”で、Camera_Controller の動作クロックとVGA_Display_Controller のクロックを分離した。SXGAでは、Camera_Controller の動作クロック、つまり、OV9655のPCLKは48MHzで15fps、VGA_Display_Controller のクロックは108MHzとなる(VESA Signal 1280 x 1024 @ 60 Hz timingを参考にした)。
VGA_Display_Controller の動作クロックがVGAの25MHzから4倍にあがったので、DDR2 SDRAMコントローラの帯域がきつくなることが考えられる。それと、相対的なレイテンシも増加するので、VGA_Display_Controller やCamera_Controller のFIFO容量の考察が必要となる。

Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路2(レイテンシの測定)”を参考に、現在のDDR2 SDRAMの動作クロック125MHzにおけるレイテンシを計算してみた。このレイテンシは、CMOSカメラのデータをSXGAに表示するだけではなく、この表示回路にCPUなどの付加回路を付けたときにでも、ディスプレイの表示が破綻しないことを目指す。
まずは、DDR2 SDRAMの動作クロックが125MHzの時の、DDR2 SDRAMコントローラにコマンドが入っていない状態(初期状態)でのWriteアクセスのレイテンシは、

87nsec * 150MHz / 125MHz = 104 nsec


となる。初期状態でのReadアクセスのレイテンシは、

147nsec * 150MHz / 125MHz = 176 nsec


となる。

リフレッシュによるレイテンシについて検証する。次のバーストのためにプリチャージしてACTコマンドを入れたときにリフレッシュが起きて、また同じACTコマンドを入れ直している場合は、150MHzの時に、180nsec のレイテンシが増加しているので、125MHzでは、

180nsec * 150MHz / 125MHz = 216nsec


となる。以前の150MHzの例を下図に示す。
BitMaped_VGA_Controller_6_090109.gif

ROWアドレスやバンクが異なる(つまりプリチャージ、ACTコマンドを入れなければならない)Write, ReadコマンドがFIFOに詰まっている場合のレイテンシについて検討してみる。下図に150MHzの場合を示す。
BitMaped_VGA_Controller_7_090110.gif

上図は、DDR2 SDRAMコントローラへのWrite, Read要求用のFIFOがFULLになったところのRead要求を入力してから、Readされた値がoutput_data に出てくるまでの時間を測定している。測定した時間は1340nsec だった。これを125MHzに変換すると、

1340nsec * 150MHz / 125MHz = 1608nsec


となる。以前は考慮しなかったが、最悪の場合として、リフレッシュによる増加分216nsec を加えると、1824nsec となる。これをVGA_Display_Controller の動作周波数108MHzの周期9.26nsec で割ると、197クロックになる。
非同期FIFOが半分の容量になったときに、VGA_Display_Controller はArbiterに表示データの要求を出すので、非同期FIFOの容量は197の倍の394深度となる。ということは、データ幅が16ビットのVGA_Display_Controller側(RGB444)では、512深度のFIFOを実装することにする。DDR2 SDRAMコントローラのデータ幅は32ビットなので、256深度だ。

次に、Camera_Controller のFIFOの容量を計算する。Camera_Controller は優先順位が最低なので、VGA_Display_Controller のバースト転送もレイテンシとして計算する。
Readアクセスのレイテンシ+128Readバーストの時間を計算する。VGA_Display_Controller のFIFOは半分の容量になったときに、半分の容量分のReadリクエストをDDR2 SDRAMコントローラに出す。それは、256バイトのRead要求なので、16ビット幅のDDR2 SDRAMでは、128ワードのReadアクセスとなるからである。128Readバースト時間は、

128 * 1/(250MHz) = 512 nsec


なので、これにリフレッシュによる増加分を加えて、728nsec となる。これに、DRR2 SDRAMコントローラのFIFOが最悪の条件でFULLになっている時のレイテンシ1608nsec を加えると、2336nsec となる。2336nsec をCamera_Controller の動作周波数48MHzの周期20.8nsecで割ると、112クロックとなる。よって、Camera_Controller のFIFOは8ビットデータ幅で128深度のFIFOとする。

DDR2 SDRAMのメモリ帯域をどのくらい占有するか計算してみると、DDR2-250なので、250MHz * 2バイト = 500MB/sec、VGA_Display_Controller では、108MHz * 1バイト = 108MB/sec、Camera_Controller では、48MHz * 1バイト = 48MB/sec なので、

((108MB/sec + 48MB/sec) / 500MB/sec) * 100 = 31.2%


の帯域を使用している。後の70%は、まだ帯域が残っている。VGA_Display_Controller もCamera_Controller もブランク期間があるので、もう少し帯域は抑えられるはずなので、まだCPUなどを付加する余裕があると思われる。
  1. 2011年01月25日 05:47 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:2

OV9655を使ってみる4(VGAの表示)

OV9655を使用してVGAを表示させてみた。SCCBレジスタの設定値は”Surveyor SRV-1 Blackfin Camera”ページの”Google Code zip archive of the SRV-1/SVS firmware builds”からお借りした。
これを元にRGB555に変更した。このSCCB設定レジスタの設定値は0x11のプリスケーラに0x01が入っているようなので、PLLでX4にしておくと、CMOSカメラのXCLK1に入れたクロック周波数がそのままPCLKに出てくる。
この設定値を使ってディスプレイに出た画像が下だ。
OV9655_5_110113.jpg

ちょっと緑が強い気がする。OV7670とそう変わらないか?それともOV7670の方が少し良い感じがする。

Pudn.com > Downloads > SourceCode/Document > Embeded-SCM Develop > Embeded Linux > OV9655のif defined(CONFIG_OV9655_OUT_VGA)の設定値を使ってみたところ、横に流れてしまって画像が見えなかった。

本当にCMOSカメラを設定するのは難しいということが改めてわかった。Preliminary Datasheetに書いていないことが多すぎる。。。

今度はCMOSカメラ回路を変更して、SXGAを表示させてみたいと思っているが、その前にNSLの続きをやってみようと思う。
  1. 2011年01月13日 05:21 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:0

OV9655を使ってみる3(回路の書き換え)

OV9655はSXGA (ピクセルクロックは108MHz) とVGA (ピクセルクロックは25MHz) で使う予定なので、CMOSカメラのドットクロックとVGA Display Controller のドットクロックが合わなくなる。今までは、CMOSカメラに25MHzを入力して帰ってきたPCLKでCamera ControllerとVGA Display Controller を動作させていた。
CamDispCntrler_DDR2_2_100709.png
CamDispCntrler_DDR2_3_100709.png

これらのクロックは、Spartan-3A Starter Kit の50MHzのクロックをDCMで1/2にしてCMOSカメラに入力していたが、ここも独立させてDCMを1個使用することにした。VGA Display Controller のクロックもCMOSカメラのPCLKから取るのやめて、独立にDCMを追加した。
下にdcm_CAM_DDR2_clk.vのVerilog ソースを示す。

// DCM module (dcm_CAM_DDR2_clk.v)
// 50MHzを入力して、DDR2_SDRAM用のclkを生成する。
// 125MHzクロック出力に変更。CMOSカメラ用の25MHzも生成する
// 2011/01/11 : VGA Display Controller のクロックとCAMのクロックを独自のDCMで生成する

`default_nettype none
`timescale 1ns / 1ps

(* KEEP_HIERARCHY = "TRUE" *)module dcm_CAM_DDR2_clk (sysclk, reset, clk_ddr2, clk_cam, clk_vga, dcm_ddr2_locked, dcm_cam_locked, dcm_vga_locked);
    `include "ddr2_cont_parameters.vh"
    input    wire    sysclk;
    input    wire    reset;
    output    wire    clk_ddr2;
    output    wire    clk_cam;
    output    wire    clk_vga;
    output    wire    dcm_ddr2_locked;
    output    wire    dcm_cam_locked;
    output    wire    dcm_vga_locked;
    
    wire clk_bufg, clk_node, dcm1_locked;
    wire clk_ddr2_node, clk_ddr2_bufg;
    wire clk_cam_node, clk_cam_bufg;
    wire clkc_bufg, clkc_node, dcmc_locked;
    wire clkv_bufg, clkv_node, dcmv_locked;
    wire clk_vgadc_node, clk_vgadc_bufg;
    wire reset_vc_dcm;
    
    // DDR2 SDRAM用クロック
    DCM dcm_DDR2_clk_dcm (
        .CLKIN(sysclk),
        .CLKFB(clk_bufg),
        .DSSEN(1'b0),
        .PSINCDEC(1'b0),
        .PSEN(1'b0),
        .PSCLK(1'b0),
        .RST(reset),     // 前段のDCMがロックするまでリセット
        .CLK0(clk_node),
        .CLK90(),
        .CLK180(),
        .CLK270(),
        .CLK2X(),
        .CLK2X180(),
        .CLKDV(),
        .CLKFX(clk_ddr2_node),
        .CLKFX180(),
        .LOCKED(dcm1_locked),
        .PSDONE(),
        .STATUS()
    );
    defparam dcm_DDR2_clk_dcm.CLKIN_PERIOD = 20.0;
    defparam dcm_DDR2_clk_dcm.DLL_FREQUENCY_MODE = "LOW";
    defparam dcm_DDR2_clk_dcm.DUTY_CYCLE_CORRECTION = "TRUE";
    defparam dcm_DDR2_clk_dcm.CLKDV_DIVIDE = 2.0;
    defparam dcm_DDR2_clk_dcm.PHASE_SHIFT = 0;
    defparam dcm_DDR2_clk_dcm.CLKOUT_PHASE_SHIFT = "NONE";
    defparam dcm_DDR2_clk_dcm.STARTUP_WAIT = "FALSE";
    defparam dcm_DDR2_clk_dcm.CLKFX_DIVIDE = 2;
    defparam dcm_DDR2_clk_dcm.CLKFX_MULTIPLY = 5;
    // defparam dcm_DDR2_clk_dcm.FACTORY_JF = 16'hFFFF;
    
    BUFG CLK_BUFG_INST (
        .I(clk_node),
        .O(clk_bufg)
    );
    
    BUFG CLK200_BUFG_INST (
        .I(clk_ddr2_node),
        .O(clk_ddr2_bufg)
    );
    assign reset_vc_dcm = ~dcm1_locked;

    // CMOSカメラ用クロック(24MHz)
    DCM dcm_cam (
        .CLKIN(clk_bufg),
        .CLKFB(clkc_bufg),
        .DSSEN(1'b0),
        .PSINCDEC(1'b0),
        .PSEN(1'b0),
        .PSCLK(1'b0),
        .RST(reset_vc_dcm),     // 前段のDCMがロックするまでリセット
        .CLK0(clkc_node),
        .CLK90(),
        .CLK180(),
        .CLK270(),
        .CLK2X(),
        .CLK2X180(),
        .CLKDV(),
        .CLKFX(clk_cam_node),
        .CLKFX180(),
        .LOCKED(dcmc_locked),
        .PSDONE(),
        .STATUS()
    );
    defparam dcm_cam.CLKIN_PERIOD = 20.0;
    defparam dcm_cam.DLL_FREQUENCY_MODE = "LOW";
    defparam dcm_cam.DUTY_CYCLE_CORRECTION = "TRUE";
    defparam dcm_cam.CLKDV_DIVIDE = 2.0;
    defparam dcm_cam.PHASE_SHIFT = 0;
    defparam dcm_cam.CLKOUT_PHASE_SHIFT = "NONE";
    defparam dcm_cam.STARTUP_WAIT = "FALSE";
    defparam dcm_cam.CLKFX_DIVIDE = 25;
    defparam dcm_cam.CLKFX_MULTIPLY = 12;
    // defparam dcm_cam.FACTORY_JF = 16'hFFFF;
    
    BUFG CLKC_BUFG_INST (
        .I(clkc_node),
        .O(clkc_bufg)
    );
    
    BUFG CLK_CAM_BUFG_INST (
        .I(clk_cam_node),
        .O(clk_cam_bufg)
    );

    // VGA Display Controller 用クロック(25MHz)
    DCM dcm_vgadc (
        .CLKIN(clk_bufg),
        .CLKFB(clkv_bufg),
        .DSSEN(1'b0),
        .PSINCDEC(1'b0),
        .PSEN(1'b0),
        .PSCLK(1'b0),
        .RST(reset_vc_dcm),     // 前段のDCMがロックするまでリセット
        .CLK0(clkv_node),
        .CLK90(),
        .CLK180(),
        .CLK270(),
        .CLK2X(),
        .CLK2X180(),
        .CLKDV(),
        .CLKFX(clk_vgadc_node),
        .CLKFX180(),
        .LOCKED(dcmv_locked),
        .PSDONE(),
        .STATUS()
    );
    defparam dcm_vgadc.CLKIN_PERIOD = 20.0;
    defparam dcm_vgadc.DLL_FREQUENCY_MODE = "LOW";
    defparam dcm_vgadc.DUTY_CYCLE_CORRECTION = "TRUE";
    defparam dcm_vgadc.CLKDV_DIVIDE = 2.0;
    defparam dcm_vgadc.PHASE_SHIFT = 0;
    defparam dcm_vgadc.CLKOUT_PHASE_SHIFT = "NONE";
    defparam dcm_vgadc.STARTUP_WAIT = "FALSE";
    defparam dcm_vgadc.CLKFX_DIVIDE = 4;
    defparam dcm_vgadc.CLKFX_MULTIPLY = 2;
    // defparam dcm_vgadc.FACTORY_JF = 16'hFFFF;
    
    BUFG CLKV_BUFG_INST (
        .I(clkv_node),
        .O(clkv_bufg)
    );
    
    BUFG CLK_VGADC_BUFG_INST (
        .I(clk_vgadc_node),
        .O(clk_vgadc_bufg)
    );

    assign clk_ddr2 = clk_ddr2_bufg;    
    assign dcm_ddr2_locked = dcm1_locked;
    assign dcm_cam_locked = dcmc_locked;
    assign dcm_vga_locked = dcmv_locked;
    assign clk_cam = clk_cam_bufg;
    assign clk_vga = clk_vgadc_bufg;
endmodule


この構成で、OV7670カメラ回路を動作させたら問題なく動作した。
次に、OV9655に取り替えて、VGAに設定したつもりで、SCCB設定レジスタに以下の項目を設定した。最初の2文字がレジスタのアドレスで、後の2文字が設定データ。FF00は終了の合図。

6B0A
1267
40F0
FF00


aitendoのOV9655モジュールではDVDDの1.8Vは内蔵のレギュレータを使用しているので、設定レジスタ6Bのビット4は0にしておく必要があると思う。設定レジスタ12で30fps VGAとRGBモードに、設定レジスタ40でデータのレンジを00からFFまでにとRGB555に設定したつもりだ。CMOSカメラに入れるクロックは24MHzだ。
これで確かめてみたところ、PCLKには12MHzが出力され、入力したクロックの半分になっていた。VSYNCは3.5Hz程度、HREFは4KHz程度だった。どうもSXGAモードになっているみたいだった。
OV9655のマニュアルを良く読んだら、SCCBインターフェースでアクセスすべきアドレスが違っていた。OV7670のWriteでは42番地だったが、OV9655のWriteでは60番地だそうだ。これでは設定できない。。。
早速、One_Transaction_SCCB.vhdの

constant ID_ADDRESS_PATTERN_SDA : std_logic_vector := "010000100";



constant ID_ADDRESS_PATTERN_SDA : std_logic_vector := "011000000";


に変更した。
これでSCCB設定レジスタに設定できるようになったようだが、今度はHREFが30Hz、VSYNCが30Hzになってしまった。おかしい。。。
SXGAモードでは、CMOSカメラの入力周波数を24MHzにして、6BレジスタでPLLをBypassモードからX4モードに設定すると、PCLKは48MHz、VSYNCが15Hz程度、HREFが15KHz程度になって、これでいい感じなのではないか?と思う。
VGAモードを探っていきたいが、サンプルをWebから入手したので、これを設定してVGAモードになるかどうか?を確かめてみたい。
  1. 2011年01月12日 05:37 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:0

OV9655を使ってみる2(変換基板製作)

今日はOV9655とSpartan-3A Starter Kit をつなぐ変換基板をFPGA-CAFEで作らせてもらった。すすたわりさんの席で作らせてもらって、ありがたかった。ありがとうございました。
さて、変換基板は、OV7670の変換基板と同じに作ろうと思ったのだが、反対面に作ってしまった。基板がOV7670とはミラーになってしまった。結果として、ヘッダに少しかかってしまったが、ヘッダには取り敢えず使わないので、そのまま行くことにした。失敗。。。
更に家に帰ってきて、テスターチェックしたら、最後の2本を間違えていたので、修正した。
下にOV7670とOV9655の変換基板に実装した状態での写真を示す。左がOV7670、右がOV9655だ。
OV9655_2_110109.jpg

次の写真は裏だ。
OV9655_3_110109.jpg

OV9655は18ピンなのだが、16ピンのコネクタしか無かった。それで、D1, D0は浮かせている。この下位ビットはRAWモードでしか使用しないので、無視することにした。Spartan-3A Starter Kit のJ2にもピンの余裕は無いので、仕方がない。(ピンクの四角で囲ってあるところが、浮いているD1, D0ピン)
OV9655_4_110109.jpg

次はSCCBの初期化データを作成して、取り敢えずVGAで動作させてみよう。
  1. 2011年01月09日 20:32 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:0

OV9655を使ってみる1(購入、変換基板設計)

aitendoのカメラモジュール(OV9655)[CAMERA130W-OV9655]を購入した。
OV9655_1_110103.jpg

OV9655は、SXGA(1280X1024) 15fps, VGA 30fpsのカメラだ。SXGAで使用してみたいが、最初はVGA 30fpsで使ってみようと思う。そうすれば、いままでの回路がそのまま使用できるはずだ。
取り敢えず、Spartan-3A Starter Kitにカメラモジュールを接続するための変換基板を作る必要がある。OV7670と同じピン配置だったら、同じ変換基板が使えるんだけど、ピン配置は違っているし、それに18ピンなので、20ピンのピンソケットを買う必要があるかと思った、しかし、D0, D1はRAW RGBでのみ使用して、YUVやRGBモードでは、D9~D2のみ使用するということだった。よく見ると、D1, D0が端にあるので、この部分は浮かせた状態で使用して、16ピンソケットに入れようと思っている。
そうして使った場合の配線表を下に示す。
OV9655_2_110103.png

これで、OV7670の時とSpartan-3Aに対する配線は同じになる。つまり、今までの回路がそのまま使えるはず。ただし、初期化データは変更する必要がある。配線はFPGA-CAFEが始まったらハンダ付けをさせてもらうことにする。

今のところ、出力用のDACが4ビットの抵抗分割なので、これを8ビットのDVI出力にしたいと思っている。そうなると、Spartan-3A Starter Kitの拡張コネクタに刺さる基板を設計する必要があるな。。。
  1. 2011年01月04日 03:57 |
  2. OV9655
  3. | トラックバック:0
  4. | コメント:0