FC2カウンター FPGAの部屋 2011年01月

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

FPGAの部屋

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

RED(映画)を見てきました

今日は、昨日公開したREDを見てきました。
REDの略はRetired Extremely Dangerous の略で退役した凄腕のスパイが現役と殺り合って暴れる映画です。年寄りが暴れる映画なので、お年寄りの方が多かった気がします。痛快なアクション映画でした。こんな映画、好きです。

次は、”KG カラテガール”を見たいんだけど、東京と神奈川でしかやっていないみたい。残念。
  1. 2011年01月30日 20:47 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラをNSLで書こう1(メモリの生成テスト)

キャラクタ・ディスプレイ・コントローラをNSLで書きなおしてみようと思っている。キャラクタ・ディスプレイ・コントローラに関しては、”キャラクタ・ディスプレイ・コントローラの詳しい説明”と”キャラクタ・ディスプレイ・コントローラのまとめ”参照。使用したISEはISE12.4 。

最初にキャラクタ・ジェネレータROMやフレーム・バッファRAMをどうやって書こうか?を考えた。NSLでは、チュートリアルの”8.メモリ”にメモリの生成と初期化方法が書いてある。でも、こう書いた場合にBlockRAMを使ってくれるかどうか?という不安がある。それではということで、実際にやってみた。チュートリアルに載っていたサンプルを少し加工させていただいて下に引用する。

declare memtest {
   input in[8], adr[8] ;
   output f[8] ;

   func_in write ;
   func_in read ;
}
module memtest {
   mem m[256][8] ;

   function write m[adr] := in ;
   function read  f = m[adr] ;
}


これをNSL CoreでVerilogに落とす(Optimizeオプションをチェックしてある)。落としたVerilogファイルを下に示す。

/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sat Jan 29 05:42:47 2011
 Licensed to :LIMITED EVALUATION USER:
*/

module memtest ( p_reset , m_clock , in , adr , f , write , read );
  input p_reset, m_clock;
  input [7:0] in;
  input [7:0] adr;
  output [7:0] f;
  input write;
  input read;
  reg [7:0] m [0:255];

   assign  f = m[adr];
always @(posedge m_clock)
  begin
   if (write )
     m[adr] <= in;
end
endmodule
/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sat Jan 29 05:42:48 2011
 Licensed to :LIMITED EVALUATION USER:
*/


多分これだと、BlockRAMには割り当てられないで、SLICEMに割り当てられると思う。実際にSpartan-3A Starter Kit 用にインプリメントしてFPGA Editorで見てみた。やはりSLICEMが割り当てられている。
CDCont_NSL_1_110129.png

選択されたSLICEMをダブルクリックして中身を見てみると、やはりRAMとして使用されていた。
CDCont_NSL_2_110129.png

やはり、assign f = m[adr]; が always @(posedge m_clock) の中にはっていないとBlockRAMにアサインされない。
この場合は、やはり、Verilogのプリミティブ記述をInterface文で付けたほうが良さそうだ。

ということで一度諦めたんですが、もしかして、Readにregを設定して、それにメモリのデータを一度コピーして出力すればどうだろう?ということで、やってみました。それにフレーム・バッファRAMを想定すると、デュアルポートRAMになっているので、NSLファイルを書きなおしてみた。そのNSLソースを下に示す。

// BlockRAM
declare memtest {
   input in[8], adr_w[8], adr_r[8] ;
   output f[8] ;

   func_in write(adr_w) ;
   func_in read(adr_r) ;
}
module memtest {
   mem m[256][8] ;
   reg ReadData[8];

   func write{
    m[adr_w] := in ;
   }
   func read{
    ReadData := m[adr_r] ;
    f = ReadData;
   }    
}


これをNSL CoreでVerilogに落とす(Optimizeオプションをチェックしてある)。落としたVerilogファイルを下に示す。

/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sat Jan 29 19:12:22 2011
 Licensed to :LIMITED EVALUATION USER:
*/

module memtest ( p_reset , m_clock , in , adr_w , adr_r , f , write , read );
  input p_reset, m_clock;
  input [7:0] in;
  input [7:0] adr_w;
  input [7:0] adr_r;
  output [7:0] f;
  input write;
  input read;
  reg [7:0] m [0:255];
  reg [7:0] ReadData;

   assign  f = ReadData;
always @(posedge m_clock)
  begin
   if (write )
     m[adr_w] <= in;
end
always @(posedge m_clock)
  begin
if ((read)) 
      ReadData <= m[adr_r];
end
endmodule
/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sat Jan 29 19:12:22 2011
 Licensed to :LIMITED EVALUATION USER:
*/


インプリメントして、FPGA Editorで見てみた。BlockRAMが使用されていた。
CDCont_NSL_3_110129.png

これで、大丈夫かな?と思う。キャラクタ・ジェネレータROMも生成してみよう。

(2011/01/30:追加)
分散RAMのデュアルポートRAMのNSL記述について追加しておく。

// 分散RAM
declare memtest {
   input in[8], adr_w[8], adr_r[8] ;
   output f[8] ;

   func_in write(adr_w) ;
   func_in read(adr_r) ;
}
module memtest {
   mem m[256][8] ;

   func write{
    m[adr_w] := in ;
   }
   func read{
    f = m[adr_r] ;
    }    
}


これをNSL CoreでVerilogに落とす(Optimizeオプションをチェックしてある)。落としたVerilogファイルを下に示す。

/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sun Jan 30 04:40:30 2011
 Licensed to :LIMITED EVALUATION USER:
*/

module memtest ( p_reset , m_clock , in , adr_w , adr_r , f , write , read );
  input p_reset, m_clock;
  input [7:0] in;
  input [7:0] adr_w;
  input [7:0] adr_r;
  output [7:0] f;
  input write;
  input read;
  reg [7:0] m [0:255];

   assign  f = m[adr_r];
always @(posedge m_clock)
  begin
   if (write )
     m[adr_w] <= in;
end
endmodule
/*
 Produced by NSL Core(version=20110119), IP ARCH, Inc. Sun Jan 30 04:40:30 2011
 Licensed to :LIMITED EVALUATION USER:
*/


  1. 2011年01月29日 19:24 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

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

クロックネット同士のTIG制約

OV9655を使用したCMOSカメラ回路をインプリントしていると、タイミングエラーが出てしまった。
OV9655_8_110126.png

この内容を見てみる。下図参照。
UCF_Writing_8_110128.png

VGA_Display_Controller用のクロックとDDR2 SDRAMコントローラのクロックにタイミング違反がある。VGA_Display_Controller用のクロックの違反の中身を見てみる。
UCF_Writing_9_110128.png

Source はDDR2 SDRAMコントローラのinitialize_endで初期化が終わったという信号で、これは初期化が終了したらずーと1になる信号だ。Destination はreset_vga_node1でこの信号を生成するためにinitialize_endを使用している。このようなステーブルな信号では、タイミング違反があっても問題がないので、このパスはタイミングを無視するという制約を付加する。ほかのタイミングエラーも同様な箇所だった。
UCFの書き方3”クロック出力ピンをグループ化して、それ同士のタイミング解析を無視する制約をかけた。今回は、クロックネットをグループ化してタイミング解析を無視する制約をかける。それが下の制約だ。(UCFファイルの一部)

NET "clk_vga" TNM_NET = TMN_CLK_VGA;
NET "clk_ddr2" TNM_NET = TMN_CLK_DDR2;
TIMESPEC TS_CLK_DDR2_to_VGA = FROM "TMN_CLK_DDR2" TO "TMN_CLK_VGA" TIG;
TIMESPEC TS_CLK_VGA_to_DDR2 = FROM "TMN_CLK_VGA" TO "TMN_CLK_DDR2" TIG;


clk_vgaをTMN_CLK_VGAにグループ化、clk_ddr2をTMN_CLK_DDR2にグループ化してして、それぞれのグループ同士のタイミング解析を無視する(TIG制約)。

これでインプリントしてみた。タイミング違反は無くなった。
UCF_Writing_1_110128.png

最後に、先ほどの制約に相当するPCFファイルの一部を下に示す。

PATH TS_CLK_DDR2_to_VGA_path = FROM TIMEGRP "TMN_CLK_DDR2" TO TIMEGRP
"TMN_CLK_VGA";
PATH "TS_CLK_DDR2_to_VGA_path" TIG;
PATH TS_CLK_VGA_to_DDR2_path = FROM TIMEGRP "TMN_CLK_VGA" TO TIMEGRP
"TMN_CLK_DDR2";
PATH "TS_CLK_VGA_to_DDR2_path" TIG;

TIMEGRP TMN_CLK_DDR2 = BEL "reset_ddr2_node1" BEL "reset_ddr2" BEL
"camc_afifo_uf" BEL "vgadc_afifo_of" BEL
"VGAD_Cntrller_inst/cs_rdg_FSM_FFd1" BEL
"VGAD_Cntrller_inst/read_count_1" BEL
"VGAD_Cntrller_inst/read_count_2" BEL
...

TIMEGRP TMN_CLK_VGA = BEL "reset_vga_node1" BEL "reset_vga" BEL
"VGAD_Cntrller_inst/RGBX_0" BEL "VGAD_Cntrller_inst/RGBX_1" BEL
"VGAD_Cntrller_inst/RGBX_3" BEL "VGAD_Cntrller_inst/RGBX_4" BEL
"VGAD_Cntrller_inst/RGBX_5" BEL "VGAD_Cntrller_inst/RGBX_6" BEL
"VGAD_Cntrller_inst/RGBX_9" BEL "VGAD_Cntrller_inst/RGBX_10" BEL
...


(追加)
reset_vga_node1の後ろの回路を追加しておきます。

    //reset_vga の処理
    always @(posedge clk_vga, posedge dcmv_out_reset) begin
        if (dcmv_out_reset) begin
            reset_vga_node1 <= 1'b1;
            reset_vga <= 1'b1;
        end else begin
            reset_vga_node1 <= ~dcm_vga_locked | ~ddr2_initialize_end; 
            reset_vga <= reset_vga_node1;
        end
    end


reset_vga_node1の入力は、DCMのロック信号とDDR2 SDRAMの初期化信号を反転しています。reset_vga_node1でclk_vgaで同期化して、それをもう一度clk_vgaで同期化してVGA_Display_Controller のリセット信号(reset_vga)として使っています。1クロック以上メタステーブル状態にならなければ大丈夫だと思います。
今までのところ問題ないです。
  1. 2011年01月28日 05:14 |
  2. UCFの書き方
  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

電子サイコロをNSLで書いてみる3(NSLをVerilogに変換してインプリント)

電子サイコロをNSLで書いてみる2(NSLに変換)”でUMLのクラス図からNSLのスケルトンに変換したので、これをサンプルを参照しながら、NSLのメソッドを書いていった。

最初に、”電子サイコロをNSLで書いてみる1(Papyrusでクラス図を作成)”の最後の出来上がりのクラス図は、counter_1to6クラスの中にreg counter_1to6; が定義してあるので、2重定義になってしまった。
NSL_Sample_41_110119.png

counter_1to6クラスの中のregの名前をcouter1to6に変更した。
NSL_Sample_42_110119.png

もう一度、UMLtoNSLでNSLスケルトンを生成して、サンプルを参照しながら、NSLのメソッドを書いていった。出来上がったNSLを下に示す。

// UML2NSL converter Ver. 2010-03-28 Copyright (c) 2009-2010 IP ARCH, Inc. All rights reserved.
// xmi  --- version 2.1 --- 

    #define C5MS_SECOND        ( 18'd250000 - 18'd1 )
//    #define C5MS_SECOND        ( 19'd4 )

    #define SEG_VALUE_6        8'b0111_1101
    #define SEG_VALUE_5        8'b0110_1101
    #define SEG_VALUE_4        8'b0110_0110
    #define SEG_VALUE_3        8'b0100_1111
    #define SEG_VALUE_2        8'b0101_1011
    #define SEG_VALUE_1        8'b0000_0110

declare    dice  {
    
    // -- dice  --
    input    roll;
    output    seg_o[8];
    output    seg_figure[4];
    
}

declare    counter_1to6  {
    
    // -- counter_1to6  --
    output    seg1to6_o[8];
    
    // -- counter_1to6  --
    func_in    countup();

}

declare    hex_to_7segout  {
    
    // -- hex_to_7segout  --
    input    hexdata[3];
    output        segdata_o[8] ;
    
    // -- hex_to_7segout  --
    func_in    output7seg(hexdata);

}

module    dice {
    
    // -- dice  --
    reg    count_5msec[18];
    reg    count_20msec[3];
    counter_1to6    u_counter_1to6;

    /* common operations */
    {
        seg_o = ~u_counter_1to6.seg1to6_o;
        seg_figure = 0b1110;
        
        any {
            count_5msec == C5MS_SECOND : {
                count_20msec++;
                count_5msec := 0;
            } else : {
                count_20msec++;
            }
        }
        
        any {
            count_20msec == 4 : {
                if (roll) {
                    u_counter_1to6.countup();
                }
                count_20msec := 0;
            }
        }        
    }
}

module    counter_1to6 {
    
    // -- counter_1to6  --
    reg    counter1to6[3] = 1;
    hex_to_7segout    u_hex_to_7segout;
    


    /* common operations */
    {
        seg1to6_o = u_hex_to_7segout.output7seg(counter1to6).segdata_o ;
    }

    
    /* func_in countup() operation */
    function    countup {
        any {
            counter1to6 == 3'b110 : {
                counter1to6 := 3'b001;
            } else : {
                counter1to6++;
            }
        }
    }
}

module    hex_to_7segout {
    wire         hex_value[3] ;
    wire        seg_value[8] ;

    func_self    seg_decode(hex_value)    :    seg_value ;

    /* common operations */
    {
        segdata_o = seg_decode(hexdata).seg_value ;
    }

    
    /* func_in output7seg(hexdata) operation */
    func seg_decode {
        any {
            hex_value == 0b001 : seg_value = SEG_VALUE_1 ;
            hex_value == 0b010 : seg_value = SEG_VALUE_2 ;
            hex_value == 0b011 : seg_value = SEG_VALUE_3 ;
            hex_value == 0b100 : seg_value = SEG_VALUE_4 ;
            hex_value == 0b101 : seg_value = SEG_VALUE_5 ;
            hex_value == 0b110 : seg_value = SEG_VALUE_6 ;
        }
    }
        
}


(大分サンプルのコードを参照させていただきました。なにかまずいことがあったらお知れらせください)

VerilogやVHDLで書いた時よりもコードが大分すっきり短くなった。NSLを自分で書いてみると(ほんの少しだが、)やはりサンプルを見てわかった様なつもりになっていても、色々と戸惑うことが多かった。新しい言語を習得するのだから、やはり色々とわからない部分がある。ほんとうに簡単なコードだが、NSLを書いてよかったと思う。
1つの疑問は、declare hex_to_7segout でfunc_in output7seg(hexdata);を宣言していて、module counter_1to6でも、seg1to6_o = u_hex_to_7segout.output7seg(counter1to6).segdata_o ;で使っているが、module hex_to_7segoutには、output7seg(hexdata)の記述がないことだ。これは自分が無知なだけかもしれない?
問い合わせをお願いしているので、結果がわかったら書き足すことにする。

次にNSL CoreでVerilogに変換して(Optimizeオプションをチェック)、ISE12.4 のプロジェクトを生成して、インプリントしてみた。
NSL_Sample_43_110124.png

できたビットファイルをSpartan3 Starter Kit にダウンロードしたら、サイコロが動作した。
NSL_Sample_44_110124.jpg

うまく行った。ほんとうに簡単なサンプルだがうれしい。
最後に、これ用(dice.v) のUCFファイルを下に示す。

NET "m_clock" LOC = T9;
NET "p_reset" LOC = L14;
NET "roll" LOC = M13;

# PlanAhead Generated physical constraints
NET "seg_figure[0]" LOC = D14;
NET "seg_figure[1]" LOC = G14;
NET "seg_figure[2]" LOC = F14;
NET "seg_figure[3]" LOC = E13;
NET "seg_o[0]" LOC = E14;
NET "seg_o[1]" LOC = G13;
NET "seg_o[2]" LOC = N15;
NET "seg_o[3]" LOC = P15;
NET "seg_o[4]" LOC = R16;
NET "seg_o[5]" LOC = F13;
NET "seg_o[6]" LOC = N16;
NET "seg_o[7]" LOC = P16;
#Created by Constraints Editor (xc3s200-ft256-4) - 2011/01/16
NET "m_clock" TNM_NET = m_clock;
TIMESPEC TS_m_clock = PERIOD "m_clock" 20 ns HIGH 50%;



(2011/01/27:追記)
疑問だったhex_to_7segoutのoutput7segの件で回答をいただきました。ありがとうございました。
正しいコードを下に示します。

module    hex_to_7segout {
    wire         hex_value[3] ;
    wire        seg_value[8] ;

    func_self    seg_decode(hex_value)    :    seg_value ;

    /* common operations */
    {
    }

    
    /* func_in output7seg(hexdata) operation */
    func    output7seg    {
        segdata_o = seg_decode(hexdata).seg_value ;
    }
    
    func seg_decode {
        any {
            hex_value == 0b001 : seg_value = SEG_VALUE_1 ;
            hex_value == 0b010 : seg_value = SEG_VALUE_2 ;
            hex_value == 0b011 : seg_value = SEG_VALUE_3 ;
            hex_value == 0b100 : seg_value = SEG_VALUE_4 ;
            hex_value == 0b101 : seg_value = SEG_VALUE_5 ;
            hex_value == 0b110 : seg_value = SEG_VALUE_6 ;
        }
    }
        
}


common operationsは空で、func output7segにコードを書くそうです。動作としては同じで、この方がすっきりする気がします。

  1. 2011年01月24日 05:51 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

ソーシャル・ネットワーク(映画)を見てきました

今日は奥さんとソーシャル・ネットワーク(映画)を見てきました。FaceBookの創業者の話です。やはり、成功の影には色々裏があるな?と思っていみてきました。
不便に思っていることに成功の種があるかもしれないです。私は、今は医療費控除の申請が面倒なので、簡単にできないかな?と思っています。RFIDカードで医者にかかるごとにデータ収集して、後で一括でデータ処理できないでしょうか?
  1. 2011年01月23日 20:17 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Notepad++でNSLのキーワードの色を変える

Notepad++でNSLのキーワードの色が変わらないのが見にくいので、NSLのキーワードの色を変えて見やすくしようと思う。Notepad++のバージョンは5.8.6。

まずは、Notepad++の表示メニューからユーザー定義ダイアログを選択する。
NSL_Keyword_1_110120.png

ユーザー定義のダイアログが開く。新規作成ボタンをクリックする。
NSL_Keyword_2_110120.png

Create New Language...ダイアログでNSLと入力してOKボタンをクリックする。
NSL_Keyword_3_110120.png

拡張子をNSLにして、キーワードリストタブを選択し、キーワードを入れていく。input, output, func_in, func_outは色をわけようと思っている。なかなか何色にするかが難しい。
NSL_Keyword_4_110120.png

これで、キーワードの登録は終わりかな?
NSL_Keyword_5_110120.png

次に、コメント・数値設定タブをクリックして、コメントの形式と数値を設定する。
NSL_Keyword_6_110120.png

最後に演算子を設定する。
NSL_Keyword_7_110120.png

これで終了なので、ダイアログのXボタンをクリックして、終了する。
この設定で、NSLが下のように見えるようになった。
NSL_Keyword_8_110120.png

なおこの設定は、ユーザー定義ダイアログから、XMLファイルとして、Exportすることができる。多分これをImportすれば、他のNotepad++にインポートすることができると思う。今回は、NSL_define.xmlファイルとしてエクスポートした。
最後に、NSL_define.xmlファイルを下に示す。

<NotepadPlus>
    <UserLang name="NSL" ext="nsl nsh">
        <Settings>
            <Global caseIgnored="no" />
            <TreatAsSymbol comment="no" commentLine="no" />
            <Prefix words1="yes" words2="no" words3="no" words4="no" />
        </Settings>
        <KeywordLists>
            <Keywords name="Delimiters">000000</Keywords>
            <Keywords name="Folder+">declare module any</Keywords>
            <Keywords name="Folder-">}</Keywords>
            <Keywords name="Operators">- ! &amp; : [ ] ^ | ~ + &lt; = &gt;</Keywords>
            <Keywords name="Comment">1/* 2*/ 0//</Keywords>
            <Keywords name="Words1">alt any declare for generate goto interface label label_name m_clock module p_reset proc_name proc seq state state_name while finish if else</Keywords>
            <Keywords name="Words2">input output inout func_in func_out func_self reg variable integer wire function func mem </Keywords>
            <Keywords name="Words3">_readmemb _readmemh _finish _display _monitor #ifdef #define #else #endif #ifndef #undef #include</Keywords>
            <Keywords name="Words4"></Keywords>
        </KeywordLists>
        <Styles>
            <WordsStyle name="DEFAULT" styleID="11" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="FOLDEROPEN" styleID="12" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="FOLDERCLOSE" styleID="13" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="KEYWORD1" styleID="5" fgColor="0000FF" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="KEYWORD2" styleID="6" fgColor="C600C6" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="KEYWORD3" styleID="7" fgColor="800000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="KEYWORD4" styleID="8" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="COMMENT" styleID="1" fgColor="008000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="COMMENT LINE" styleID="2" fgColor="008000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="NUMBER" styleID="4" fgColor="FF8040" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="OPERATOR" styleID="10" fgColor="8000FF" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMINER1" styleID="14" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMINER2" styleID="15" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
            <WordsStyle name="DELIMINER3" styleID="16" fgColor="000000" bgColor="FFFFFF" fontName="" fontStyle="0" />
        </Styles>
    </UserLang>
</NotepadPlus>


上のXMLを名前をつけてセーブして、Notepad++からインポートすれば、NSLのキーワード色付けができる(できました)。

ユーザー定義言語のやり方は、”How to create your own definition (user-defined language) of a Syntax Highlighting scheme”に書いてある。
ユーザー定義言語のXMLファイルは”Obtaining files related to user defined language.”にある。私もSystemVerilogとPicoBlazeを入れた。SystemCとXilinxの制約ファイルが無いのが残念だけど、自分で作れば良いと思う。誰か作った方がいたら公開してください。

(2011/01/22:追記)
if, else, function のキーワードが抜けていたので、上のNSL_define.xmlファイルをアップデートしました。
(22:32)演算子に[]を追加しました。
(2011/02/09:修正)
  1. 2011年01月21日 04:05 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:0

FIFOをISimで論理シミュレーションしたときの不具合(Fifo Generator 7.2を使用)

SRAMのコントローラを作成していて、Read/WriteをバーストでアクセスするためにRead用、Write用それぞれのFIFOをFifo Generator 7.2を使って作成した。そのSRAMコントローラをISE12.4のISimでシミュレーションしているときに、おかしな動作になってしまった。FIFOの仕様は、分散RAM仕様のFWFT FIFOで、深度が16(18)、ビット幅が16(Read用)、34(Write用)、DATA_COUNT、almost_full, almost_empty付きだ。

どのようにおかしいかというと、下のISimのシミュレーション図で、まずはwr_fifoの方を見ていく。wr_fifo_emptyだが、wr_fifo_rd_enが'1'になったと同時に'1'になっている(ピンクの四角)。これは、水色の四角で示すwr_fifo_rd_enが'1'から'0'になるclk(見えていないが。。。)の立ち上がりまで'1'になる必要がある。しかも、wr_fifo_countも01のままで00にならない。
rd_fifo_emptyも黄色い四角で示す位置で'1'になるはずがならない。。。
FIFOG_1_110120.png

FIFO付近のVHDLコードを下に示す。

    -- Write Data Path
    wr_fifo_din <= wr_address & wr_data;
    wr_fifo_rd_en_node <= wr_fifo_rd_en;
    wr_fifo_inst : write_fifo port map(
        clk => clk,
        srst => reset,
        din => wr_fifo_din,
        wr_en => wr_enable,
        rd_en => wr_fifo_rd_en,
        dout => wr_fifo_dout,
        full => open,
        almost_full => wr_fifo_full,
        empty => wr_fifo_empty,
        almost_empty => wr_fifo_almost_empty,
        data_count => wr_fifo_count
    );
    
    
    -- Read Data Path
    rd_fifo_rd_en_node <= rd_fifo_rd_en;
    rd_fifo_inst : read_fifo port map(
        clk => clk,
        srst => reset,
        din => rd_address,
        wr_en => rd_enable,
        rd_en => rd_fifo_rd_en,
        dout => rd_fifo_dout,
        full => open,
        almost_full => rd_fifo_full,
        empty => rd_fifo_empty,
        almost_empty => rd_fifo_almost_empty,
        data_count => rd_fifo_count
    );
    
    -- SRAMのRead, Write 用ステートマシン(Read優先)
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                wr_fifo_rd_en <= '0';
                rd_fifo_rd_en <= '0';
            else
                case cs_SRAM_RW is
                    when SRAM_RW_STATE'(idle) =>
                        if rd_fifo_empty='0' then
                            cs_SRAM_RW <= READ_STATE;
                            rd_fifo_rd_en <= '1';
                        elsif wr_fifo_empty='0' then
                            cs_SRAM_RW <= WRITE_STATE1;
                        end if;
                    when READ_STATE =>
                        if rd_fifo_almost_empty='0' then -- まだRead用FIFOに残っている
                            cs_SRAM_RW <= READ_STATE;
                        else
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                            rd_fifo_rd_en <= '0';
                        end if;
                    when WRITE_STATE1 =>
                        cs_SRAM_RW <= WRITE_STATE2;
                        wr_fifo_rd_en <= '1';
                    when WRITE_STATE2 =>
                        wr_fifo_rd_en <= '0';
                        if rd_fifo_empty='0' then -- Read優先, ReadとWriteの間は1クロック間を空ける。
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                        elsif wr_fifo_almost_empty='0' then -- まだWrite用FIFOに残っている
                            cs_SRAM_RW <= WRITE_STATE1;
                        else
                            cs_SRAM_RW <= SRAM_RW_STATE'(idle);
                        end if;
                end case;
            end if;
        end if;
    end process;



これは、どうやらデルタ遅延のいたずらのようだ。
2つのFIFOのrd_enを1つノードを通して入れると正常な動作になった。
FIFOG_2_110120.png
(注)上のVHDLコードにはバグがあったので、修正してあります。

FIFO付近のコードを以下に示す。

    -- Write Data Path
    wr_fifo_din <= wr_address & wr_data;
    wr_fifo_rd_en_node <= wr_fifo_rd_en;
    wr_fifo_inst : write_fifo port map(
        clk => clk,
        srst => reset,
        din => wr_fifo_din,
        wr_en => wr_enable,
        rd_en => wr_fifo_rd_en_node,
        dout => wr_fifo_dout,
        full => open,
        almost_full => wr_fifo_full,
        empty => wr_fifo_empty,
        almost_empty => wr_fifo_almost_empty,
        data_count => wr_fifo_count
    );    
    
    -- Read Data Path
    rd_fifo_rd_en_node <= rd_fifo_rd_en;
    rd_fifo_inst : read_fifo port map(
        clk => clk,
        srst => reset,
        din => rd_address,
        wr_en => rd_enable,
        rd_en => rd_fifo_rd_en_node,
        dout => rd_fifo_dout,
        full => open,
        almost_full => rd_fifo_full,
        empty => rd_fifo_empty,
        almost_empty => rd_fifo_almost_empty,
        data_count => rd_fifo_count
    );


2つのFIFOのrd_en に1つノードを追加した。これで正常にシミュレーションすることができた。

clkはポートから直結なんだけど?FIFO Generator のクロックのパスが長いのだろうか?いずれにせよ。これでだいぶ時間をつぶしてしまった。。IPの中なので、自分では注意できない。よって、おかしいことがあったら、まずはデルタ遅延を疑おうと思った。
  1. 2011年01月20日 12:16 |
  2. Core Generator
  3. | トラックバック:0
  4. | コメント:0

電子サイコロをNSLで書いてみる2(NSLに変換)

電子サイコロをNSLで書いてみる1(Papyrusでクラス図を作成)”でUMLのクラス図を作った。今度はUMLtoNSLでNSLファイルに変換してみる。

UMLtoNSLツールを起動して、dice.nslに変換した。下に変換後のdice.nslを示す。

// UML2NSL converter Ver. 2010-03-28 Copyright (c) 2009-2010 IP ARCH, Inc. All rights reserved.
// xmi  --- version 2.1 --- 



declare    dice  {
    
    // -- dice  --
    input    roll;
    output    seg_o[8];
    output    seg_figure[4];
    
}

declare    counter_1to6  {
    
    // -- counter_1to6  --
    output    seg0to6_o[8];
    
    // -- counter_1to6  --
    func_in    countup();

}

declare    hex_to_7segout  {
    
    // -- hex_to_7segout  --
    input    hexdata[3];
    
    // -- hex_to_7segout  --
    func_in    output7seg(hexdata);

}
module    dice {
    
    // -- dice  --
    reg    count_5msec[18];
        reg    count_20msec[3];
        counter_1to6    u_counter_1to6;
    


    /* common operations */
    {
    
    }

    
}
module    counter_1to6 {
    
    // -- counter_1to6  --
    reg    counter_1to6[3];
        hex_to_7segout    u_hex_to_7segout;
    


    /* common operations */
    {
    
    }

    
    /* func_in countup() operation */
    function    countup {
    
    }
        
}
module    hex_to_7segout {
    
    // -- hex_to_7segout  --
    wire    seg_value[8];
        


    /* common operations */
    {
    
    }

    
    /* func_in output7seg(hexdata) operation */
    function    output7seg {
    
    }
        
}


さて、このスケルトンからNSLのメソッドを書いていくのだが、Notepad++がNSLに対応していないので、キーワードの色分けが出来ていない。Notepad++はキーワードを定義する機能があるので、キーワードを定義してから、メソッドを書いていくことにする。
  1. 2011年01月20日 05:35 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

VHDLのパッケージファイルがISEに認識されずにエラーが出る

VHDLでパラメータやprocedure, functionなどを書いたパッケージファイルをVHDLのファイルでuseしているときに、パッケージをプロジェクトにいれているにもかかわらず、packageがないとエラーが出てしまった。(下のような感じでパッケージファイルをuseする)

library work;
use work.disp_timing_pack.all;


(上の例VHDLの記述は、この下の例とは関係ありません。)
その場合には、Project Navigator のLibrariesタブをクリックして、Librariesウインドウを表示し、パッケージファイルで右クリックする。右クリックメニューから、Sourece Properties...を選択する。
VHDL_Package_1_110119.png

File Properties ダイアログが開く。Include as Global File in Compile List をチェックして、OKボタンをクリックする。
VHDL_Package_2_110119.png

そうすると、Designタブに切り替えると、パッケージファイルがマーク付きで現れる。
VHDL_Package_3_110119.png

一度、これをやっておくと、次にチェックを外しても認識されているようだ。
確かめたのは、ISE12.4のISimで確かめた。どうにもパッケージファイルが見つからなくて困っていたので、やったら、Project Navigator に認識されたみたいだ。
  1. 2011年01月19日 17:31 |
  2. Xilinx ISEについて
  3. | トラックバック:0
  4. | コメント:0

電子サイコロをNSLで書いてみる1(Papyrusでクラス図を作成)

さて、NSLの次の課題として電子サイコロを自分でNSLで書いてみようと思う。電子サイコロはISE11.1のチュートリアルとして、”ISE11.1iのチュートリアル1(導入編)”で紹介してある仕様のものをそのままNSLで書いてみようと思う。
その前に、NSLのチュートリアルはすごく読みやすくて、良いチュートリアルなので、これで勉強しようと思う。

NSLで書き直すに当たって、イベントドリブンに書きなおそうと思う。
diceクラスのcommon operations として、チャタリング除去用の5msecのカウンタを作って、そのイベントでスイッチの値を取って評価する。5msecのカウンタの4回に1回、スイッチが押されていれば、サイコロのカウンタをアップする。というアプローチにしようと思っている。

それでは、Papyrusを立ち上げてクラス図を作ろう。下がクラス図を作った状態。dice, counter_1to6, hex_to_7segoutのクラスがある。hex_to_7segoutはサンプルのクラスをそのまま使用することにする。
NSL_Sample_38_110119.png

下の図がプロパティを設定し終えたところ。
NSL_Sample_39_110119.png

次にメソッドの作成。下の図がメソッドの作成が終了したところ。
NSL_Sample_40_110119.png

インスタンス生成も終了した。
NSL_Sample_41_110119.png

今回はこれで終了、次はNSLのスケルトンを生成して、NSLのメソッドを書いていく。
  1. 2011年01月19日 05:54 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

Interface2011年2月号のNSLサンプルを試す5(インプリメントを試す)

今回はNSLファイルをVerilogとVHDLに変換したものをISE12.4でインプリメントして、Spartan3 Starter Kit で動作させてみようと思う。

まずはVerilogからやってみる。VerilogはNSL CoreのOptimizeオプションをチェックして、Synthesisしたほうがシンプルなコードがでるようだ。
NSL_Sample_35_110116.png

これでCQ出版社からダウンロードしたQuartus II のプロジェクトのtimer7seg.v とほとんど変わらない。ただ、counter_0to5モジュールのp_resetが追加してあるだけだ。

ISE12.4のプロジェクトを作成して、Spartan3 Starter Kit でインプリントしようとしたが、Spartan3 Starter Kit の7セグメントLEDの仕様に合っていないので、timer7seg.nsl を変更することにした。
セグメントの出力は1つで、seg_figureによって、出力するセグメントを決めるように変更した。そして、プッシュボタンスイッチを押したときの極性は1だ。seg_figureを2ビットから4ビットに変更した。変更内容を下に示す。

declare    timer7seg  {
    
    // -- timer_30MHz_to_1sec  --
    input        reset ;
    output        seg_o[8] ;
    output        seg_figure[4] ;        // For support DYNAMIC drive.
}

.............

module    timer7seg {
    reg                cnt_1sec[32] = 0 ;
    reg                cnt_100Hz[19] = 0 ;
    reg                seg_figure_buffer[4] = 4'b1110 ;
    reg                seg1_o[8] = 0xc0;
    reg                seg2_o[8] = 0xc0;
    counter_0to9    u_counter_0to9;

    /* common operations */
    {

        seg1_o := ~u_counter_0to9.seg0to9_o ;
        seg2_o := ~u_counter_0to9.seg0to5_o ;
        
        any {
            seg_figure_buffer == 0b1101 : seg_o = seg2_o;
            seg_figure_buffer == 0b1110 : seg_o = seg1_o;
        
        }

        any {
            cnt_1sec == ONE_SECOND : {
                if(reset) {
                    u_counter_0to9.reset() ;
                } else {
                    u_counter_0to9.countup() ;
                }
                cnt_1sec := 0 ;
            }
            else : {
                cnt_1sec++ ;
            }
        }
        
        any {
            cnt_100Hz == CNT_DYNAMIC : {
                cnt_100Hz := 0 ;
                any {
                    seg_figure_buffer == 0b1110 : seg_figure_buffer := 0b1101 ;
                    seg_figure_buffer == 0b1101 : seg_figure_buffer := 0b1110 ;
                }
            }
            else : {
                cnt_100Hz++ ;
            }
        }
        seg_figure    = seg_figure_buffer ;
    }
}


これで、Verilogに変換したものをISE12.4でインプリントする。
まずは制約ファイル(UCF)を作った。timer7seg.ucfを下に示す。

NET "m_clock" LOC = T9;
NET "p_reset" LOC = L14;
NET "reset" LOC = M13;

# PlanAhead Generated physical constraints
NET "seg_figure[0]" LOC = D14;
NET "seg_figure[1]" LOC = G14;
NET "seg_figure[2]" LOC = F14;
NET "seg_figure[3]" LOC = E13;
NET "seg_o[0]" LOC = E14;
NET "seg_o[1]" LOC = G13;
NET "seg_o[2]" LOC = N15;
NET "seg_o[3]" LOC = P15;
NET "seg_o[4]" LOC = R16;
NET "seg_o[5]" LOC = F13;
NET "seg_o[6]" LOC = N16;
NET "seg_o[7]" LOC = P16;
#Created by Constraints Editor (xc3s200-ft256-4) - 2011/01/16
NET "m_clock" TNM_NET = m_clock;
TIMESPEC TS_m_clock = PERIOD "m_clock" 20 ns HIGH 50%;


インプリントして、Spartan3 Starter Kit にダウンロードしたら、見事に動作した。うれしい。
NSL_Sample_36_110116.jpg

次にVHDLでやってみた。VHDLでやるとエラーが出た。
NSL_Sample_37_110116.png

最初のエラーは、

v_net_1 <= '1' when (v_net_2) else '0' ;


だ。エラーの内容は、

ERROR:HDLParsers:802 - "H:/Documents and Settings/Masaaki/My Documents/NSL/Xilinx_ISE/VHDL/timer7seg.vhdl" Line 71. v_net_2 is not a boolean expression.


v_net_2がboolean じゃなくてstd_logic なので、値を示す必要があるようだ。下のように修正すると通る。

v_net_1 <= '1' when (v_net_2='1') else '0' ;


その他、同様のエラーの部分を数カ所、修正すると論理合成が終了した。これでインプリントした。Spartan3 Starter Kit にダウンロードすると動作した。
NSL CoreのVHDL出力は、そのままではISE12.4のXSTで論理合成出来ないようだ。

(2011/01/18:追記)
Synplify Pro D-2009.12でNSL Coreから出力されたVHDLを論理合成してみましたが、やはり、

v_net_1 <= '1' when (v_net_2) else '0' ;



@E:CD648 : timer7seg.vhdl(71) | Expression does not match type boolean


でエラーになってしまいます。
他にもエラーが出ていました。

Quartus II だとVHDLの出力がそのままでも論理合成出来るそうですが、それ以外の論理合成ツールではVHDLソースの修正が必要なようです。

(2011/01/22:追記)
新しくダウンドードしたNSL Core version 20100119でNSLから生成されたVHDLがXSTの論理合成を通って、Spartan3 Starter Kit にダウンロードすると動作することが確認できました。いろいろ修正していただいて、ありがとうございました。

  1. 2011年01月16日 20:09 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

Interface2011年2月号のNSLサンプルを試す4(NSLをVerilogに変換してシミュレーション)

”Interface2011年2月号のNSLサンプルを試す3(インスタンス作成)”でスケルトンコードを生成することができた。今度はスケルトンコードにメソッドを書かなくてはいけないのだけれども、CQ出版社から落としたプロジェクト一式に入っている完成版のNSLファイルtimer7seg.nslを使って、Verilog、VHDL、SystemCへの変換を行ってみようと思う。NSL Coreのバージョンは20110102、使用したISimのバージョンは12.4だ。

CQ出版社から落としたプロジェクト一式の中のAGX20\timer7seg\NSL_Sourceフォルダの下のtimer7seg.nslを使用する。timer7seg.nslを見るとtimer7segモジュール?のdeclare は下のようになっていて、UMLコードを書いた時よりもinput resetが増えているようだ。(下に引用する)

declare    timer7seg  {
    
    // -- timer_30MHz_to_1sec  --
    input        reset ;
    output        seg1_o[8] ;
    output        seg2_o[8] ;
    output        seg_figure[2] ;        // For support DYNAMIC drive.
}


このSTOPWATCHプロジェクトではキッチンタイマーを作るという目的があるようなので、このreset端子はキッチンタイマーのリセットではないかと思われる。そういえばトップモジュールに1つも入力がないというのはおかしい?よって、以前のUMLのクラス図にinput resetを追加することにした。
NSL_Sample_24_110114.png

これで、UMLtoNSLツールを起動してNSLのスケルトンを吐かせると、declare timer7segにinput reset; が入っていた。これで良いのだと思う。このresetはNSLコードを見ると1秒に1回評価されるようだ。
さて、次はダウンロードしたtimer7seg.nslを使って、NSL Coreツールで、VerilogやVHDL、SystemCに変換してみようと思う。
NSL Coreツールを起動して、NSLファイルを指定するために...ボタンをクリックして、ダウンロードしたプロジェクトの中のtimer7seg.nslを指定した。デフォルトのLanguageはVerilogなので、これでSynthesisボタンをクリックして、Verilogに変換した。
NSL_Sample_25_110114.png

変換されたVerilogはこんな感じだ。下図参照。
NSL_Sample_26_110114.png

//synthesis translate_off、//synthesis translate_on の組がよく出てきて、ネットが 'x' の時にWarningが出るようだ。アサーション・チェッカーなのかな?

次に、LanguageをVHDL に変更して、Synthesisボタンをクリックする。すると、VHDLファイルが出力された。下図参照。
NSL_Sample_27_110114.png

LanguageをSystemC に変更して、Synthesisボタンをクリックする。生成されたSystemCファイル。
NSL_Sample_28_110114.png

LanguageをSimultaion(Verilog) に変更して、Synthesisボタンをクリックする。生成されたVerilogファイル。
NSL_Sample_29_110114.png

テストベンチ(tb)の辺り、当然ながら、resetのスティミュラスは書く必要がありそうだ。

LanguageをSimultaion(SystemC)に変更して、Synthesisボタンをクリックする。生成されたSystemCファイル。
NSL_Sample_30_110114.png

Verilogでシミュレーションを試みた。Simultaion(Verilog) で、ISimでシミュレーションを行った。
シミュレーションを行う際に、resetのスティミュラスを追加した。修正後のソースを下に示す。

module tb;
    parameter tCYC=2;
    parameter tPD=(tCYC/10);

    reg p_reset;
    reg m_clock;
    reg reset;
    wire [7:0] seg1_o;
    wire [7:0] seg2_o;
    wire [1:0] seg_figure;

    timer7seg timer7seg_instance(
        .p_reset(p_reset),
        .m_clock(m_clock),
        .reset(reset),
        .seg1_o(seg1_o),
        .seg2_o(seg2_o),
        .seg_figure(seg_figure)
    );

    initial forever #(tCYC/2) m_clock = ~m_clock;

    initial begin
        $dumpfile("timer7seg.vcd");
        $dumpvars(0,timer7seg_instance);
    end

    initial begin
        #(tPD)
            p_reset = 1;
            m_clock = 0;
            reset = 0;
        #(tCYC)
            p_reset = 0;
            reset = 1;
        #200000 $stop;
    end

endmodule


これでISim用のバッチファイルを書いてシミュレーションした。ISim用のバッチファイルを下に示す。

vlogcomp -work work -incremental timer7seg.v
fuse work.tb -o tb.exe
tb.exe -gui


ISimのシミュレーション結果は、sig2_oが 'XX' になってしまっている。
NSL_Sample_31_110114.png

原因を追求して行ったのだが、どうやら、counter_0to5モジュールのcounter が 'X'になってしまっている。counter_0to9モジュールのcounter は正常な値になっている。
NSL_Sample_32_110114.png

counter_0to9モジュールのcounterの記述はp_resetが入っていて、0にクリアされている。下に記述の一部を引用する。

always @(posedge m_clock or posedge p_reset)
  begin
if (p_reset)
     counter <= 4'b0000;
else 
//synthesis translate_off
if ((reset&countup&(~_net_5))|((reset|(countup&(~_net_5)))&countup&_net_5))   counter <= 4'bx; 
  else 
//synthesis translate_on
if (reset)
      counter <= 4'b0000;
else if (countup&(~_net_5))
      counter <= (counter)+(4'b0001);
else if (countup&_net_5)
      counter <= 4'b0000;
end


counter_0to5モジュールのcounter の記述はp_resetの記述がない。これが取り敢えずcounter の値が 'X' になる原因のようだ。

always @(posedge m_clock)
  begin

//synthesis translate_off
if ((reset&countup&(~_net_6))|((reset|(countup&(~_net_6)))&countup&_net_6))   counter <= 3'bx; 
  else 
//synthesis translate_on
if (reset)
      counter <= 3'b000;
else if (countup&(~_net_6))
      counter <= (counter)+(3'b001);
else if (countup&_net_6)
      counter <= 3'b000;
end


counter_0to5モジュールのcounter の記述にp_clockの記述を追加したところsig2_oも0xC0になった。
NSL_Sample_33_110114.png

ちょっとキッチンタイマーのシミュレーションは時間がかかって現実的じゃないので、timer7seg.nslの最初の時間間隔定義を修正した。

//    #define ONE_SECOND        ( 32'd50000000 - 32'd1 )
//    #define CNT_DYNAMIC        19'b100_1001_0011_1110_0000
      #define ONE_SECOND        ( 32'd4 )
      #define CNT_DYNAMIC        19'b000_0000_0000_0000_1000


これでISimでシミュレーションをしたところ、カウント値が変わるのを確認できた。
NSL_Sample_34_110114.png

そういえば、SystemCでシミュレーションしているとおっしゃっていた。SystemCでシミュレーションする必要があるのかもしれない。Verilogでシミュレーションする場合は、まだバグがあるようだ。

原因はtimer7seg.nslにバグがあったためのようです。counter_0to5モジュールの宣言は下のようでしたが、

module    counter_0to5 {
    
    // -- counter_0to5  --
    reg                counter[3];
    hex_to_7segout    u_hex_to_7segout;


これには、reg counter[3];の初期化の記述がありません。そこで、下のように書き換えたところ、

module    counter_0to5 {
    
    // -- counter_0to5  --
    reg                counter[3] = 0;
    hex_to_7segout    u_hex_to_7segout;


p_resetの記述が入りました。これで問題なくなりました。NSL Coreのバグではありませんでした。

なお、SystemCは殆ど知らないので、SystemCも勉強したいと思っている。
  1. 2011年01月14日 05:58 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

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

筑波山ウォーキング

今日は朝、アリアさんのマグカップで朝食を取った。自家製パン、自家製カスピ海ヨーグルト、エルダーフラワー&カモミールティーだった。いつもの朝食だ。
nikki_1_110110.jpg

(注:パンをガブッと一口食べてしまったことをお詫び致します)

さて、今日は奥さんと筑波山ウォーキングに行って来た。午前11時ころ平沢官衙に着いてウォーキング開始。
Tukubasan_1_110110.jpg

筑波山を見ながらウォーキング。風が冷たかった。
Tukubasan_2_110110.jpg

途中の神郡の桜井菓子店であんドーナツと鹿の子を買った。ここはあんドーナツが有名だそうだ。後で食べたら、衣がサクサクでとても美味しかった。
この後はずっと登り道、筑波山の南斜面だからか?暖かかった。登りでからだが熱くなったこともあるが、実際温かいみたい。梅が咲き始めていた。眺めがいいし良いところだ。。。
Tukubasan_3_110110.jpg

坂を登って、もうすぐ筑波山神社だ。旧筑波山郵便局があった。風情のある建物。今は写真展などをやっているらしい。今日は正月で休みだった。
Tukubasan_4_110110.jpg

もう少し歩くと筑波山神社に着いた。お参りをしてきた。
Tukubasan_5_110110.jpg

来た道を戻った。12時30分くらいになったので、途中のそば ゐだに入った。美味しい蕎麦屋さんということだったのだが、私には短くて、太くて、固い蕎麦だった。(はっきり言ってまずい)おすすめの鴨汁そば(2,500円)を頼んだ。鴨汁なので、暖かいそばかと思ったが、鴨肉を焼いて、タレに漬けて食べ、鴨の脂をタレに落として、それで蕎麦を食べるそうだ。店主が出てきて、薀蓄を語りながら自ら焼いてくれた。食べるタイミングを逃すな!ということだった。はっきり言ってうざかった。でも鴨肉とそば湯はうまかった。
Tukubasan_6_110110.jpg

私にとっては蕎麦は喉越しで食べるものなので、どうも合わないみたい?
さて、食事を終えてまた平沢官衙に戻ってきた。平地は行きよりも風が強かった。
  1. 2011年01月10日 19:01 |
  2. 日記
  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

Interface2011年2月号のNSLサンプルを試す3(インスタンス作成)

Interface2011年2月号のNSLサンプルを試す2(メソッド作成)”の続き

今度はインスタンスを作成する。
右のUML LinksからAssociationを選択して、timer7seg クラスからcounter_0to9 クラスに線を引いて、インスタンスを作成した。
(注)何回も作り直したので、右はじのクラス名が間違っています。正しくはhex_to_7segoutです。
NSL_Sample_19_110106.png

PalletteからSelectをクリックし、インスタンス名をクリックしてName:とMulipliccity:(インスタンス数)を変更する。
NSL_Sample_20_110106.png

すべてのインスタンスを作成した。下図。
NSL_Sample_21_110106.png

これで書き終わったのだが、一番最初にCreate a new Class Diagram をするのを忘れてしまった。それで、今書き換えている。
それに、myUMLModel.uml を右クリックしてもUML to NSL generateの項目が出ないみたいなのだが、どうしてだろう?

そうだ。UML2NSLというのがあった。それでUMLからNSLに変換するんだ。Papyrusマニュアルは古いバージョンなのだろうか?
スタートメニューのIP Apach. IncからUMLtoNSLを起動して、作ったmyUMLModel.umlをUMLtoNSLにドラックアンドドロップした。
NSL_Sample_22_110109.png

Convertボタンをクリックすると、ダイアログが出て、NSLを生成する位置と名前を指定する。ここではSTOPWATCH.nslとした。保存ボタンをクリックすると、Convert Doneダイアログが出て、OKボタンをクリックした。
NSL_Sample_23_110109.png

NSLのスケルトンコードが生成できました。

// UML2NSL converter Ver. 2010-03-28 Copyright (c) 2009-2010 IP ARCH, Inc. All rights reserved.
// xmi  --- version 2.1 --- 



declare    timer7seg  {
    
    // -- timer7seg  --
    output    sig1_o[8];
    output    sig2_o[8];
    output    sig_figure[2];
    
}

declare    counter_0to9  {
    
    // -- counter_0to9  --
    output    seg0to5_o;
    output    seg0to9_o[8];
    
    // -- counter_0to9  --
    func_in    countup();
func_in    reset();

}

declare    counter_0to5  {
    
    // -- counter_0to5  --
    output    seg0to5_o[8];
    
    // -- counter_0to5  --
    func_in    countup();
func_in    reset();

}

declare    hex_to_7segout  {
    
    // -- hex_to_7segout  --
    input    hexdata[4];
    
    // -- hex_to_7segout  --
    func_in    output7seg(hexdata);

}
module    timer7seg {
    
    // -- timer7seg  --
    reg    cnt_1sec[32];
        reg    cnt_100Hz[19];
        reg    sig_figure_buffer[2];
        counter_0to9    u_counter_0to9;
    


    /* common operations */
    {
    
    }

    
}
module    counter_0to9 {
    
    // -- counter_0to9  --
    reg    counter[4];
        counter_0to5    counter_0to5;
    hex_to_7segout    u_hex_to_7segout;
    


    /* common operations */
    {
    
    }

    
    /* func_in countup() operation */
    function    countup {
    
    }
        
    /* func_in reset() operation */
    function    reset {
    
    }
        
}
module    counter_0to5 {
    
    // -- counter_0to5  --
    reg    counter[3];
        hex_to_7segout    u_hex_to_7seg;
    


    /* common operations */
    {
    
    }

    
    /* func_in countup() operation */
    function    countup {
    
    }
        
    /* func_in reset() operation */
    function    reset {
    
    }
        
}
module    hex_to_7segout {
    
    // -- hex_to_7segout  --
    wire    seg_value[8];
        


    /* common operations */
    {
    
    }

    
    /* func_in output7seg(hexdata) operation */
    function    output7seg {
    
    }
        
}


良かった。。。というか、Interface誌をもっと早く、読みなおせば良かった。何時かの時点でPapyrusからNSLを出力するのから、ツールでUMLからNSLを生成する方法に変わったのだろうか?
  1. 2011年01月08日 06:33 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

Interface2011年2月号のNSLサンプルを試す2(メソッド作成)

Interface2011年2月号のNSLサンプルを試す1(クラスとプロパティの作成)”の続き

今回はメソッドを作成する。

クラスの3段目をポイントすると、Add New Operation のアイコンが出てくるので、それをクリックする。
(注)何回も作り直したので、右はじのクラス名が間違っています。正しくはhex_to_7segoutです。
NSL_Sample_11_110106.png

メソッドが生成された。そのメソッドを選択して、名前を output7seg に変更する。
NSL_Sample_12_110106.png

次に引数を入力する。parameters の+ボタンをクリックすると引数が生成される。
NSL_Sample_13_110106.png

引数をダブルクリックして、引数名とバス幅を入力する。
NSL_Sample_14_110106.png

次は、Method:の+ボタンをクリックして、Opaque Behavior を作るそうだ。これは何だかよく分からないが追加する。
NSL_Sample_15_110106.png

output7seg: Method Selection ダイアログが開くので、New OpaqueBehavior ボタンをクリックして、追加する。OKボタンをクリックする。
NSL_Sample_16_110106.png

最後に、メソッド種類の設定を行う。これは下の表のようにVisibility を設定するようなのだが、この種類がどれがどの場合に使うのかが良くわからない?

func_in : public
func_out : protected
proc : private
func_self : package


最終的にNSLに落ちたソースをカンニングすると、この場合はどのメソッドもfunc_in に設定されているようなので、func_in のpublic に設定する(デフォルト値)。
NSL_Sample_17_110106.png

次に、残りのメソッドを生成していく。引数がないメソッドでは、PDFのマニュアルを見る限りでは、引数もOpaque Behavior も作る必要がないようだ。
NSL_Sample_18_110106.png
  1. 2011年01月07日 05:50 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0

Interface2011年2月号のNSLサンプルを試す1(クラスとプロパティの作成)

OV9655(CMOSカメラモジュール)は、FPGA-CAFEに行って変換基板をハンダ付けするまで、お休みとして、Interface2011年2月号NSLサンプルを試してみようと思う。HDLソースのマニュアル化は、VHDLでDoxygenを使用してマニュアル化を図ってみた。VHDL記述はもともとコード量が多いのに、更にDoxygenの記述が増えてしまうので、挫折してしまった。大規模な回路だったのでなおさらだったのだが、かなり書くのがきつかった。
UMLで書いて、それをHDLに落とすというのも、ずーとやれたら良いなと思ってきた。今回のNSLではUMLのクラス図を書いて、スケルトンモデルをNSLに落として、動作モデルは手で記述するようだ。これでも、クラス図は今まで書いてきたブロック図を置き換えることができるとおもう。ブロック図には、入出力記述が無いがクラス図をその代わりにすれば、入出力記述も書くことができる。ただ、UMLからNSLのパスだけでなく、NSLからUMLのクラス図のパスがあったほうが良いと思う。NSLで出来上がった記述に、例えばLEDの表示を追加するとしたらNSLで追加したほうが便利だ。その時にUMLのクラス図をツールでアップデートできた方がうれしい。NSLからアクティビティ図を自動生成してくれるともっとうれしい。
#NSLからUMLに変換するときに、NSLコードが悪かったら、ここが良くないと指定してくれると良いな?と思う。LINTツールの様な使い方ができそう。。。

さて、Interface2011年2月号の97ページからの”第5章 UMLで始めるFPGA/ASIC回路設計”を参考に書かれているサンプルをやってみた。
最初に付録CDから、UMLエディタのPapyrusをインストールというか?コピーした。次にUML2NSLをインストールし、NSLCoreをインストールした。(Overtone社のダウンロードサイトにNSLCore_20110102_setup.zipがあるので、それをダウンロードしてインストールし直した)

Papyrusを立ち上げた。Workspaceを聞いてくるので、Browse...ボタンでフォルダを選択して、OKボタンをクリックする。
NSL_Sample_m1_110108.png

Fileメニュー -> New -> Create a new Papyrus project を選択して、プロジェクトを作成する。
NSL_Sample_m2_110108.png

New Papyrus project ダイアログが出てくる。Project nameを入力してFinish ボタンをクリックする。
NSL_Sample_m3_110108.png

OutlineウインドウのmyUMLModelを右クリックして、右クリックメニューからAdd a diagram -> Create a new Class Diagram を選択して、新しいClass diagramウインドウを生成する。
NSL_Sample_m4_110108.png

Class diagram of myUMLModelウインドウが生成された。
NSL_Sample_m5_110108.png

UMLファイルとかが入っているNSLのフォルダをWorkspaceにコピーする。
NSL_Sample_m6_110108.png

この後、PDFマニュアルにはないのだが、Workspace上のNSLフォルダをPapyrusのNavigatorウインドウのSTOPWATCHプロジェクトにドラックアンドドロップしないと、次でImport Packageするときに見つからなかった。
NSL_Sample_m7_110108.png

NSLのパッケージをインポートする。OutlineウインドウのmyUMLModelを右クリックして、右クリックメニューからImport Package -> Import Package form workspace models を選択する。
NSL_Sample_m8_110108.png

Import Package From Workspaceダイアログが開く。Select a resoure to open のテキストボックスにNSLと入れると、Matching resource にNSL.profile.uml が出てくるので、それを選択して、OKボタンをクリックする。
NSL_Sample_m9_110108.png

次のNSLにチェックを入れて、OKボタンをクリックする。
NSL_Sample_m10_110108.png

OutlineウインドウのmyUMLModelを展開すると、import NSLがあるはず。右の三角形をクリックすると、Palette Windowが出てくlる。
NSL_Sample_m11_110108.png

後は、付録CDの Papyrus_Manual.pdf にSTOPWATCHのクラスの作り方が書いてあるので、それに従ってクラス図を作成すれば良いと思っていたが、記事のクラス図と違っているので、記事のクラス名に合わせることにする。
まずは、Palette Windowを展開して、Packageを選択して、Packageを描く。
NSL_Sample_2_110105.png

次に、クラスを作成して、名前をtimer7segに変更する。
NSL_Sample_3_110105.png

Interface2011年2月号の102ページの図9のクラスを全て書いた。
NSL_Sample_4_110106.png

クラスの2番目のセルをマウスでポイントすると、Add new Propetyアイコンが現れるので、クリックしてプロパティを追加した。
NSL_Sample_5_110106.png

プロパティを選択した状態で、下のPropetiesウインドウ内のValue(s) DefinitionフィールドのTypeの+ボタンをクリックして、Select Typeダイアログを出す。NSL_profle.umlから<Primitive Type>regを選択する。
NSL_Sample_6_110106.png

Value(s) DefinitionフィールドのTypeはNSL::regになった。Propetiesウインドウ内のName:を cnt_1sec に変更した。
NSL_Sample_7_110106.png

次にビット幅を指定する。Propetiesウインドウ内のMulipliccity:でビット幅を指定した。
NSL_Sample_8_110106.png

Propetiesウインドウ内のVisibilityでprivateラジオボタンをチェックした。
NSL_Sample_9_110106.png

なお、Visibilityは、下の表のように設定するそうだ。

input, output : public
wire, reg, mem : private
integer, variable : private


これで1つのプロパティ(reg)の設定が終わったので、全部のプロパティを作成していく。
下の図が全部のプロパティを設定を終了した状態だ。
NSL_Sample_10_110106.png

Interface2011年2月号のNSLサンプルを試す2(メソッド作成)”へ続く。
  1. 2011年01月05日 05:48 |
  2. NSL
  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

FPGAの部屋のまとめサイトを更新(2011/01/03)

FPGAの部屋のまとめサイトを更新しました。
SMMIPVC++SDR SDRAMコントローラの項目を追加しました。2010年までの記事のリンクを更新しました。
  1. 2011年01月03日 06:00 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

2011年の初詣

昨日は初詣にいつもの水海道の天神様に行ってきました(水海道第1高校の近く)。
今年は、上の娘が大学受験なので、お祈りしてきました。第1志望に受かると良いんですけどね。取り敢えずは、センター試験の結果次第だそうです。
天然石おみくじがあったので、引いたみたら小吉でした。天然石は紫水晶でした。娘が交換してくれと言ってきたので、翡翠と交換してあげました。おみくじは、細かい運勢は読まずに結んできました。
奥さんと娘たちは、ふるまい甘酒を飲んでましたが、私は甘酒は嫌いです。飲めません!
その後は、奥さんの実家に年始に行きましたよ。
hatumoude_110102.jpg
  1. 2011年01月02日 06:08 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

2010年のFPGAの部屋の月別アクセス数

皆様、明けましておめでとうございます。

さて、2010年のFPGAの部屋のアクセス数の総計は531,673アクセスでした。ありがとうございました。
Access_1_110101.png

2006年の5月からアクセス数を集計していたので、2007年からの年別アクセス数の推移をグラフにしてみました。
Access_2_110101.png

アクセス数は増えていることがわかりました。今年もいろいろなことにチャレンジしていこうと思っています。今年もどうぞよろしくお願い申し上げます。
  1. 2011年01月01日 05:44 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0