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

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

FPGAの部屋

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

Spartan-3A Starter KitでEDKを使ってカメラ表示8(HDLを書く)

Spartan-3A Starter KitでEDKを使ってカメラ表示7(FIFO容量の修正)”の続き。

Camera_Controller のIPICのインターフェース部分をVHDLで書いている。IPICのマスタWriteだ。詳細は”Spartan-3A Starter KitでEDKを使ってカメラ表示6(PLBV46 Master Burstのバースト転送)”のFixed Length Burst Write Operation参照。

データ転送は32ビット幅、16バーストのみとしている。よって下の信号は、固定となる。

IP2Bus_Mst_BE <= (others => '1');
IP2Bus_Mst_Length <= CONV_STD_LOGIC_VECTOR(64, 12); -- 64バイト、32ビット幅、16バースト
IP2Bus_MstWr_src_dsc_n <= '1';
IP2Bus_MstWr_rem <= (others => '0');


コマンド転送や、データ転送のsof_n, eof_nなどの部分を書き進めている。
Spa3A_SKit_OV7670_58_110829.png

なおフォルダが、cam_controller_64_v1_00_aのデータバス64ビット幅用のフォルダに書いてしまったが、データバス幅32ビットのモジュールとなる。というのは、64ビットバス幅にすると、MicroBlazeの命令用ROM用のBRAMが足りなくなってしまうためだ。後で、camera_controller_v1_00_aフォルダに移動する。

久しぶりにVHDLを書いたので、指がVHDLの書き方を忘れてしまっている。ついつい Verilog の癖で、

if (reset_cam)


などと書いてしまうが、VHDLでは

if reset_cam='1' then


のはず。。。
  1. 2011年08月29日 05:37 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示7(FIFO容量の修正)

Spartan-3A Starter KitでEDKを使ってカメラ表示6(PLBV46 Master Burstのバースト転送)”の続き。

主な作業は週末にやることにして、今日は、今まで作ったSpartan-3A Starter Kit のCamera ControllerやDisplay ControllerのVerilogコードを修正することにした。

元にするSpartan-3A Starter KitでCMOSカメラ・ディスプレイ回路のブロック図を示す。(Spartan-3A Starter KitでCMOSカメラ・ディスプレイ回路1(ブロック図)
CamDispCntrler_DDR2_1_100708.png

上図でARBITERから下は、XPSの回路に任せることになる。Camera ControllerとDisplay Controllerはそれぞれ独立のモジュールとして、それぞれ別のPLBバスにぶら下がることになる。


まずは、FIFOの容量から、今まではすべての回路が自分の作った回路でレイテンシやスループットを計算できたので、必要なFIFOの容量が計算できたが、今回は、PLBやIPICなどのバスやそのラッパーなどを通っているし、マルチポート・メモリ・コントローラ(MPMC) のレイテンシやスループットも分からない。よって、FIFOの容量は、同じBRAMの個数で構成できる最大の容量にしておくことにした。

まずは、Camera Controller のcam_cont_afifoから修正する。
camara controller のブロック図を下に示す。
CamDispCntrler_DDR2_2_100709.png

上図の非同期FIFOがcam_cont_afifoだ。cam_cont_afifoの出力にラッパー回路を通して、IPICに接続する。
現在のFIFO容量は、入力が16ビット幅64深度で、出力が32ビット32深度だ。これで使用しているBRAMは1となる。
Spa3A_SKit_OV7670_52_110826.png

これでも十分な気はするが、最大にすると入力が16ビット幅1024深度、出力が32ビット幅512深度になる。これでは、相当大きいので、今までの4倍の量にすることにした。入力が16ビット幅256深度、出力が32ビット幅128深度とした。
Spa3A_SKit_OV7670_53_110826.png

Read Data Countを使用しているので、そこのビット幅を5ビットから7ビットに変更した。後は変更する部分は無いので、下の構成でGenerateした。
Spa3A_SKit_OV7670_54_110826.png


次に、display controller のcam_data_afifoの容量を修正する。display controller のブロック図を下に示す。
CamDispCntrler_DDR2_3_100709.png

上図の非同期FIFOがcam_data_afifoだ。
こちらは、入力が32ビット幅で128深度、出力が16ビット幅で256深度だったので、4倍の、入力が32ビット幅で512深度、出力が16ビット幅で1024深度とした。
Spa3A_SKit_OV7670_56_110826.png

こちらは、Write Data Countを使用しているので、7ビット幅から9ビット幅に変更した。
下の構成でGenerateした。
Spa3A_SKit_OV7670_57_110826.png

これでFIFOの容量の変更は終了した。

Camera ControllerとDisplay Controllerは、カメラやディスプレイ用のクロックを上位モジュールから、もらっていた。それぞれ別にDCMを付けて、25MHzを生成する必要があるので、そのように修正する。
  1. 2011年08月26日 05:42 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示6(PLBV46 Master Burstのバースト転送)

Spartan-3A Starter KitでEDKを使ってカメラ表示5(PLBV46 Master Burstのシングル転送)”の続き。

前回はシングル転送だったが、今回はバースト転送について見ていきたい。

Fixed Length Burst Read Operation
PLBV46 Master Burst(v1.01a) のFigure 7: Fixed Length Burst Read Timingから引用させていただいた。
Spa3A_SKit_OV7670_50_110825.png

()内はどちらの回路がドライブするかを示す。

1.IP2Bus_Mst_Typeを1(バースト転送)、IP2Bus_MstRd_Reqを1(Read)、IP2Bus_Mst_Addrに有効なアドレスを出力、IP2Bus_Mst_Lengthに転送長(バイト単位)を出力、IP2Bus_MstRd_Reqを1にする。IP2Bus_Mst_BEのバイト・イネーブルは何でも良い。(ユーザー回路)

2.Bus2IP_Mst_CmdAckが1になると、IPICコマンド転送終了。(IPIC) ユーザー回路はコマンド信号をディアサートする。(ユーザー回路)

3.最初の有効なReadデータの最初でBus2IP_MstRd_sof_nが0にアサートされている。その時、Bus2IP_MstRd_REMはオール0の様だ。多分4バイト境界のアドレスからReadしていると思われる。
同時にBus2IP_MstRd_dにReadデータが出力され、Bus2IP_MstRd_src_dsc_nが0になり、Readデータが有効なことを示す。(IPIC)

4.ユーザー回路で、IP2Bus_MstRd_dst_rdy_nが0にすでにアサートされているので、Bus2IP_MstRd_src_dsc_nが0になった最初のクロックで、Bus2IP_MstRd_dのReadデータがユーザー回路に読み込まれる。

5.次のクロックから、次のReadデータがBus2IP_MstRd_dに出力される。Bus2IP_MstRd_src_dsc_nが0でかつIP2Bus_MstRd_dst_rdy_nが0の時に、ユーザー回路に読み込まれる。どちらか1つでも1だと、Bus2IP_MstRd_dに出力されたReadデータは次のクロックまで保持される。

6.この場合は、IP2Bus_Mst_Lengthが020だったので、32バイトの転送だった、バス幅が32ビットなので、1回の転送に4バイト送れるので、転送長は8バーストになる。最後のReadデータの時に、Bus2IP_MstRd_eof_nが0にアサートされる。同時に、Bus2IP_MstRd_REMにも有効な値が出力される。(IPIC)

7.最後のReadデータ転送の次のクロックで、Bus2IP_Mst_Cmpltが1にアサートされて転送終了が宣言される。(IPIC)



Fixed Length Burst Write Operation
PLBV46 Master Burst(v1.01a) のFigure 8: Fixed Length Burst Write Timinから引用させたいただいた。
Spa3A_SKit_OV7670_51_110825.png

()内はどちらの回路がドライブするかを示す。

1.IP2Bus_Mst_Typeを1(バースト転送)、IP2Bus_MstWr_Reqを1(Write)、IP2Bus_Mst_Addrに有効なアドレスを出力、IP2Bus_Mst_BEにバイト・イネーブルを出力して、IP2Bus_MstRd_Reqを1にする。(ユーザー回路)

2.1.と同時に(でなくても良いと思うが)IP2Bus_MstWr_dにWriteデータを出力し、IP2Bus_MstWr_REMはマスク(1でマスク、0で有効なデータ)を出力する。IP2Bus_MstWr_sof_n、IP2Bus_MstWr_src_rdy_nを0にアサートする。(ユーザー回路)

3.IPICがBus2IP_MstWr_dst_rdy_nを0にアサートするまで、最初のWriteデータ(IP2Bus_MstWr_d)と、IP2Bus_MstWr_sof_nのアサートを継続する。

4.IPICがBus2IP_MstWr_dst_rdy_nを0にアサートしたら、次のWriteデータ(IP2Bus_MstWr_d)を次のクロックで出力する。IP2Bus_MstWr_src_rdy_nとBus2IP_MstWr_dst_rdy_nが同時にアサートされたときにWriteデータ転送が有効になる。同時にアサートされない場合は、次のクロックも同じWriteデータを出力する。(ユーザー回路)

5.コマンド転送終了時に、IPICがBus2IP_Mst_CmdAckが1にアサートするので、そうしたらユーザー回路はコマンド信号をディアサートする。

5.最後のWriteデータ転送、この場合は8バースト目でIP2Bus_MstWr_eof_nをユーザー回路が0にアサートする。これのWriteデータ転送が有効になったら、バーストWrite転送は終了となる。

6.バーストWrite転送が終了した次のクロックで、IPICによってBus2IP_Mst_Cmpltが1にアサートされて、バーストWrite転送が完了する。


次は、これを元に今までのCamera Controller、Display Controller とのラッパー回路を作成する。
どちらも、シングル転送はなしで、バースト転送のみで処理を行うようにしようと思う。バースト転送は2から16バーストだ。
640*480/2/16 = 9600で割り切れるので、16バースト転送のみにしようと思う。16個32ビットデータが溜まったら、バースト転送コマンドを発行してバースト転送を行う。(/2はピクセル・データが16ビットなので、32ビットの半分だから、/16は16バースト転送)
連続アドレスになるはずなので、MPMCが効率的にデータを処理することができると思う。

  1. 2011年08月25日 05:33 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示5(PLBV46 Master Burstのシングル転送)

Spartan-3A Starter KitでEDKを使ってカメラ表示4(カスタムIPの作成)”の続き。

XPSのアドレスタプをクリックすると、camera_controller_0, display_controller_0, sccb_controller_0がunmaped addresses の下に入っている。これにメモリサイズを割り当てる。
Spa3A_SKit_OV7670_43_110822.png

まずは、sccb_controller_0に64Kバイトを割り当てた。
Spa3A_SKit_OV7670_44_110822.png

sccb_controller_0 のBase Address に0x84080000を設定した。
Spa3A_SKit_OV7670_45_110822.png

同様に、camera_controller_0, display_controller_0に64Kバイトを割り当て、それぞれBase Addressを0x84040000, 0x84060000に設定した。
Spa3A_SKit_OV7670_46_110822.png


さて、次は、HDLを書いて、PLB Masterとして動作させよう。PLBV46 Master Burst(v1.01a) を参照する。

PLBV46 Master Burst IPは、IBM CoreConnect compatibleのPLBとClient IP Interface をインターフェースするモジュールのようだ。双方向でシングル転送、2から16データビートの固定値のバースト・データ転送に対応している。

以前、PowerPCのインターフェース回路を設計したことがあるが、アドレス転送とデータ転送に信号が分かれていた。PLBもそのようになっているようだ。
下に、シングルWriteとシングルRead転送のプロトコルを説明する。

Single Data Beat Read Operation
PLBV46 Master Burst(v1.01a) のFigure 3: PLB Single Data Beat Read Timingを下に引用させたいただいた。
Spa3A_SKit_OV7670_48_110823.png

()内はどちらの回路がドライブするかを示す。

1.IP2Bus_Mst_Typeを0(シングル転送)、IP2Bus_MstRd_Reqを1(Read)、IP2Bus_Mst_Addrに有効なアドレスを出力、IP2Bus_Mst_BEにバイト・イネーブルを出力して、IP2Bus_MstRd_Reqを1にする。(ユーザー回路)

2.Bus2IP_Mst_CmdAckが1になると、IPICコマンド転送終了。(IPIC) ユーザー回路はコマンド信号をディアサートする。(ユーザー回路)

3.予め、IP2Bus_MstRd_dst_rdy_nを0(active low) にして、ユーザー回路がデータを受け入れ可能なことを宣言しておく。(ユーザー回路)

4.シングル転送なので、Bus2IP_MstRd_sof_nとBus2IP_MstRd_eof_nが同時に0になる。同時にBus2IP_MstRd_dにReadデータが出力され、Bus2IP_MstRd_src_dsc_nが0になり、Readデータが有効なことを示す。(IPIC)

5.IP2Bus_MstRd_dst_rdy_nを0にすでにアサートされていて、IPICはBus2IP_MstRd_src_dsc_nを0にアサートするときに、IPICはBus2IP_Mst_Cmpltを1にアサートして転送終了を宣言する。(IPIC)


あまり詳しい説明は書いていないのだが、これであっているんじゃないか?と思う。

Single Data Beat Write Operation
PLBV46 Master Burst(v1.01a) のFigure 4: PLB Single Data Beat Write Timingを下に引用させたいただいた。
Spa3A_SKit_OV7670_49_110824.png

()内はどちらの回路がドライブするかを示す。

1.IP2Bus_Mst_Typeを0(シングル転送)、IP2Bus_MstWr_Reqを1(Write)、IP2Bus_Mst_Addrに有効なアドレスを出力、IP2Bus_Mst_BEにバイト・イネーブルを出力して、IP2Bus_MstRd_Reqを1にする。(ユーザー回路)

2.1.と同時に(でなくても良いと思うが)IP2Bus_MstWr_dにWriteデータを出力し、IP2Bus_MstWr_REMはマスクのようなので、IP2Bus_Mst_BEを反転して出力すれば良いと思う。IP2Bus_MstWr_sof_n、IP2Bus_MstWr_eof_n、IP2Bus_MstWr_src_rdy_nを0にアサートする。(ユーザー回路)

3.IPICがBus2IP_MstWr_dst_rdy_nを0にアサートして、Writeデータを受け取ったことを示す。(IPIC)

4.IPICが、次のクロックでBus2IP_Mst_CmdAck、Bus2IP_Mst_Cmpltを1にアサートして、データ転送の終了をユーザー回路に通知する。(IPIC) ユーザー回路はすべての信号をディアサートする。(ユーザー回路)



rem[0:3]の参考文献
  1. 2011年08月24日 05:16 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示4(カスタムIPの作成)

Spartan-3A Starter KitでEDKを使ってカメラ表示3(MPMCにポートを追加)”の続き。

今回は、カスタムIPをウィザードで作成する。カスタムIPは、カメラ・コントローラ、ディスプレイ・コントローラ、SCCBコントローラの3つだ。カメラ・コントローラ、ディスプレイ・コントローラは、PLBマスタとスレーブに対応する。SCCBコントローラは、PLBスレーブのみとなる。
最初にカメラ・コントローラ、ディスプレイ・コントローラをPLBマスタのデータバス幅32ビットで作成した。現在のPLBの動作周波数は62.5MHzで、自作のカメラ表示回路のDDR2 SDRAMコントローラ側の周波数125MHzの半分となっている。これだとバスバンド幅が自作に比べて半分になっているので、カメラ・コントローラ、ディスプレイ・コントローラのバッファ用のFIFOの容量を少なくとも2倍にする必要がある。
さて、カスタムIPを作成しよう。

XPSのHardwareメニューからCreate or Import Peripheral... を選択する。

Create and Import Peripheral Wizardが立ち上がる。
Spa3A_SKit_OV7670_23_110820.png

Peripheral Flowで、Select Flowから、Create templates for a new peripheralのラジオボタンを選択する。(デフォルト値)
Spa3A_SKit_OV7670_24_110820.png

Repository or Projectで、To an XPS projectのラジオボタンが選択されていて、Projectに現在のプロジェクトが入力されている。
Spa3A_SKit_OV7670_25_110820.png

Name and Versionで、Name:にcamera_controller と入力した。
Spa3A_SKit_OV7670_26_110820.png

Bus Interface でProcessor Local Bus(PLB v4.6) を選択する。
Spa3A_SKit_OV7670_27_110820.png

IPIF (IP Interface) Servicesが開く。Slave serves and configuration で、User logic software registerとInclude data pase timerにチェックが入っている。更にUser logic master にチェックを入れる。
Spa3A_SKit_OV7670_28_110820.png

Slave Interfaceが開く。スレーブはバースト対応にしないので、デフォルトのままとする。
Spa3A_SKit_OV7670_29_110820.png

User S/W Registerで自分のロジックモジュールで使用するレジスタ数を指定する。デフォルトの1とした。これはMicroBlazeからFIFOのOverflow, UnderflowエラーのReadやクリアなどに使用する。
Spa3A_SKit_OV7670_30_110820.png

Master Interfaceが開く。今回はPLBマスタとPLBスレーブを作るので、マスタの設定がある。Burst supportにチェックを入れる。Data widthはデフォルトの32ビットとする。(実はData widthを64ビットに設定したCAM_CONTROLLER_64も作成してある)
Spa3A_SKit_OV7670_31_110820.png

IP Interconnect (IPIC)で、IP Interconnect (IPIC) interface のどの信号と接続するかを決定する。デフォルト値とした。
Spa3A_SKit_OV7670_32_110820.png

(OPTIONAL) Peripheral Simulation Supportはデフォルト値とした。
Spa3A_SKit_OV7670_33_110820.png

(OPTIONAL) Peripheral Implementation Supportはデフォルト値とした。
Spa3A_SKit_OV7670_34_110820.png

SummaryでFinishボタンをクリックする。
Spa3A_SKit_OV7670_35_110820.png

これで、camera_controllerカスタムIPスケルトンの製作は終了した。次にdisplay_controller を作成した。同様にPLBマスタとPLBスレーブを持つ。
Spa3A_SKit_OV7670_36_110820.png

sccb_controllerは、PLBスレーブのみのカスタムIPとした。
Spa3A_SKit_OV7670_37_110820.png

3つのカスタムIPが生成された。(データバス幅64ビットの_64も2つあるので、合計5つ)

camemra_controller を右クリックメニューからAdd IPした。MPLBをplb_v46_0に接続し、SPLBをmb_plbに接続した。
Spa3A_SKit_OV7670_41_110820.png

display_controller も右クリックメニューからAdd IPした。MPLBをplb_v46_1に接続し、SPLBをmb_plbに接続した。
最後にsccb_controller も追加して、SPLBをmb_plbに接続した。
Spa3A_SKit_OV7670_42_110820.png

  1. 2011年08月22日 05:18 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

カンフー・パンダ2を見てきました

今日はカンフー・パンダ2を見てきました。カンフー・パンダ1は、奥さんと娘で見に行って、とても面白いということだったので、私もDVDを借りてきて見ましたが、どじなパンダがカンフーの龍の戦士となる過程が面白かったです。

という訳で、カンフー・パンダ2が始まったので、奥さんと下の娘と私で見てきました。やはり1と同様、ドジなパンダが活躍していて面白かったです。3流映画の乗りでしょうかね?(いい意味で。)
娘は2の方が面白いと言っていましたが、わたしは1の方が面白かったです。最初のインパクトのせいかもしれません。なんか3があるのかもしれませんね?

映画館はかなり人が入っていました。人気があるみたいです。
  1. 2011年08月21日 22:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示3(MPMCにポートを追加)

Spartan-3A Starter KitでEDKを使ってカメラ表示2(試しにインプリメント)”の続き。

今回は、DDR2 SDRAMをコントロールするMulti Port Memory Controller(MPMC)のポートを2つ増やすことにする。あとで、カメラ・コントローラ、ディスプレイ・コントローラを接続するためだ。

XPSでDDR2_SDRAMをダブルクリックして、MPMCを起動する。PORT0はXCLに設定されているので、PORT1とPORT2にPLBV46を設定する。
Spa3A_SKit_OV7670_18_110820.png

Port Configurationタブをクリックすると、Port1, Port2 にPLBv46 が設定されている。データバス幅は64ビットらしい。
Spa3A_SKit_OV7670_19_110820.png

Bus Interface タブでDDR2_SDRAMを展開すると、SPLB1, SPLB2が増えている。SPLB1でNew Connection を選択する。
Spa3A_SKit_OV7670_20_110820.png

SPLB1はplb_v46_0 に接続され、上にplb_v46_0が追加されている。次にSPLB2も同様に、New Connection を選択する。
Spa3A_SKit_OV7670_21_110820.png

同様に、plb_v46_1が追加され、SPLB2がplb_v46_1に接続された。
Spa3A_SKit_OV7670_22_110820.png

  1. 2011年08月21日 05:21 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

木製アタッシュケースの製作1(板接ぎ)

涼しくなってきたので、木工をやる気になってきました。

今回の製作予定は、木製アタッシュケースです。こんなのや、こんなのがありますが、内装は無しでつくろうと思っています。
軽いので桐で作ることにしました。今日は、板接ぎをしました。
Wood_case_110820.jpg

  1. 2011年08月20日 17:23 |
  2. 木工
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示2(試しにインプリメント)

Spartan-3A Starter KitでEDKを使ってカメラ表示1(BSB Wizard)”の続き。

前回で、XPSのプロジェクトができたので、Project Navigatorに戻って、トップファイルを生成して、インプリメントしてみた。その結果のMAPレポートの一部を下に示す。

Release 13.2 Map O.61xd (nt)
Xilinx Mapping Report File for Design 'system_top'

Design Information
------------------
Command Line   : map -intstyle ise -p xc3s700a-fg484-4 -cm area -ir off -pr off
-c 100 -o system_top_map.ncd system_top.ngd system_top.pcf 
Target Device  : xc3s700a
Target Package : fg484
Target Speed   : -4
Mapper Version : spartan3a -- $Revision: 1.55 $
Mapped Date    : FRI 19 AUG 13:0:46 2011

Design Summary
--------------
Number of errors:      0
Number of warnings:  260
Logic Utilization:
  Number of Slice Flip Flops:         4,223 out of  11,776   35%
  Number of 4 input LUTs:             5,107 out of  11,776   43%
Logic Distribution:
  Number of occupied Slices:          4,155 out of   5,888   70%
    Number of Slices containing only related logic:   4,155 out of   4,155 100%
    Number of Slices containing unrelated logic:          0 out of   4,155   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:       5,251 out of  11,776   44%
    Number used as logic:             4,453
    Number used as a route-thru:        144
    Number used as 16x1 RAMs:             4
    Number used for Dual Port RAMs:     474
      (Two LUTs used per Dual Port RAM)
    Number used as Shift registers:     176

  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

  Number of bonded IOBs:                 90 out of     372   24%
    IOB Flip Flops:                      34
    IOB Master Pads:                      3
    IOB Slave Pads:                       3
  Number of ODDR2s used:                 24
    Number of DDR_ALIGNMENT = NONE       24
    Number of DDR_ALIGNMENT = C0          0
    Number of DDR_ALIGNMENT = C1          0
  Number of BUFGMUXs:                     6 out of      24   25%
  Number of DCMs:                         2 out of       8   25%
  Number of BSCANs:                       1 out of       1  100%
  Number of BSCAN_SPARTAN3As:             1 out of       1  100%
  Number of MULT18X18SIOs:                3 out of      20   15%
  Number of RAMB16BWEs:                  17 out of      20   85%

  Number of RPM macros:            1
Average Fanout of Non-Clock Nets:                3.35

Peak Memory Usage:  223 MB
Total REAL time to MAP completion:  22 secs 
Total CPU time to MAP completion:   17 secs 


LUTsを43パーセント使用していて、かなり使われている。問題は、Number of RAMB16BWEsで20個の内の17個使われている。残り3個だが、前回のカメラ表示回路では、5個のBRAMを使用したので、この分は空けたい。Etherをサクl除して、Data Cacheを削減することにした。Data Chacheは、分散RAMにしようと思う。下は、FPGA EditorでみたBRAMのリスト。
Spa3A_SKit_OV7670_13_110819.png

XPSでmicroblaze_0をダブルクリックすると、MicroBlazeのConfiguration Wizardが開く。
Spa3A_SKit_OV7670_14_110819.png

4ページ目のChaches の設定画面でData Chacheを1KBに設定した。これで使用するBRAMは1個減った。なるべくバスの負荷を下げてDMAをやり安くするためにキャッシュは確保したい。OKボタンをクリックする。
Spa3A_SKit_OV7670_15_110819.png

Ethernet_MACをDelete Instanceした。
Spa3A_SKit_OV7670_16_110819.png

Ethernet_MACのポートをUCFから削除した。
Spa3A_SKit_OV7670_17_110819.png

ProjectメニューからRescan User Repositories を選択して、リポジトリを作りなおした。

XPSを閉じて、もう一度、Project Navigatorで、ポートが変更されているので、EDKのトップファイルを作りなおしてから、インプリメントした。
MAPリポートを下に示す。

Release 13.2 Map O.61xd (nt)
Xilinx Mapping Report File for Design 'system_top'

Design Information
------------------
Command Line   : map -intstyle ise -p xc3s700a-fg484-4 -cm area -ir off -pr off
-c 100 -o system_top_map.ncd system_top.ngd system_top.pcf 
Target Device  : xc3s700a
Target Package : fg484
Target Speed   : -4
Mapper Version : spartan3a -- $Revision: 1.55 $
Mapped Date    : FRI 19 AUG 22:55:42 2011

Design Summary
--------------
Number of errors:      0
Number of warnings:  205
Logic Utilization:
  Number of Slice Flip Flops:         3,555 out of  11,776   30%
  Number of 4 input LUTs:             4,493 out of  11,776   38%
Logic Distribution:
  Number of occupied Slices:          3,621 out of   5,888   61%
    Number of Slices containing only related logic:   3,621 out of   3,621 100%
    Number of Slices containing unrelated logic:          0 out of   3,621   0%
      *See NOTES below for an explanation of the effects of unrelated logic.
  Total Number of 4 input LUTs:       4,614 out of  11,776   39%
    Number used as logic:             3,697
    Number used as a route-thru:        121
    Number used for Dual Port RAMs:     620
      (Two LUTs used per Dual Port RAM)
    Number used as Shift registers:     176

  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

  Number of bonded IOBs:                 73 out of     372   19%
    IOB Flip Flops:                      23
    IOB Master Pads:                      3
    IOB Slave Pads:                       3
  Number of ODDR2s used:                 24
    Number of DDR_ALIGNMENT = NONE       24
    Number of DDR_ALIGNMENT = C0          0
    Number of DDR_ALIGNMENT = C1          0
  Number of BUFGMUXs:                     6 out of      24   25%
  Number of DCMs:                         2 out of       8   25%
  Number of BSCANs:                       1 out of       1  100%
  Number of BSCAN_SPARTAN3As:             1 out of       1  100%
  Number of MULT18X18SIOs:                3 out of      20   15%
  Number of RAMB16BWEs:                  14 out of      20   70%

  Number of RPM macros:            1
Average Fanout of Non-Clock Nets:                3.40

Peak Memory Usage:  217 MB
Total REAL time to MAP completion:  18 secs 
Total CPU time to MAP completion:   15 secs 


Number of 4 input LUTsが43パーセントから、38パーセントに減っている。BRAMが17個から14個に減っている。これならば、大丈夫だと思う。

  1. 2011年08月19日 23:04 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

Spartan-3A Starter KitでEDKを使ってカメラ表示1(BSB Wizard)

SP605を使ってEDKの使い方を勉強してきたが、今回は、本格的にEDKで回路を構成してみようと思う。
Spartan-3A Starter KitでEDKを使って、カメラ表示回路を作ってみようと思う。使用するEDKのバージョンは13.2。

1.まずは、ISEのプロジェクトを作成した。
Spa3A_SKit_OV7670_1_110819.png

2.Hierarchyウインドウで右クリックメニューからNew Source... を選択する。
3.New Source Wizard が開く。
4.Fine Name:にsystem と入力する。
Spa3A_SKit_OV7670_2_110819.png

5.Summaryが表示されるので、Finishボタンをクリックする。
Spa3A_SKit_OV7670_3_110819.png

6.Xilinx Platform Studio(XPS) が立ち上がって、ダイアログが開きBSB Wizard を行うかを聞いてくるので、Yesボタンをクリックする。
Spa3A_SKit_OV7670_4_110819.png

7.Base System Builder - Welcomeダイアログが表示される。I would like to create a new design(デフォルト)のラジオボタンが選択されている。
Spa3A_SKit_OV7670_5_110819.png

8.Board Selection では、すでにSpartan-3A Starter Kit が選択されていた。
Spa3A_SKit_OV7670_6_110819.png

9.System Configuration でSingle-Processor System (デフォルト)を選択する。
Spa3A_SKit_OV7670_7_110819.png

10.Processor Configurationで、Locka Memory を16KBに変更した。System Clock Frequency は62.5MHzでデフォルト値とした。
Spa3A_SKit_OV7670_8_110819.png

11.Peripheral Configuration でデフォルトの状態からxps_timer を追加した。Use Interrrupt にチェックを入れる。
Spa3A_SKit_OV7670_9_110819.png

12.Cache Confguration でInstruction Cache とData Cacheを2KBずつ入れた。(これは、DMACでDMAするときになるべくバスが空いているようにするためだ)
Spa3A_SKit_OV7670_10_110819.png


13.Summaryが表示された。Finishボタンをクリックする。
Spa3A_SKit_OV7670_11_110819.png

14.XPSの画面に、今まで設定してきたシステムが表示された。
Spa3A_SKit_OV7670_12_110819.png
  1. 2011年08月19日 05:09 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

ISE WebPACKでも使用できるMicroBlazeコアとGCCコンパイラ

カスタム設計の MicroBlaze”さんに、自作のMicroBlazeコアがあります。NGCなので、Spartan-3でのみ動作かもしれませんが。。。

GCCは、Webサイトにあるやり方で、EDKのgnuのmicroblazeフォルダをCygwinにコピーすると、mb-gccなどが使えました。(.bashrcにパスを追加しました)私は、ISE12.4のフォルダをコピーしました。

まだ、あまりテストしていませんが、WebPACKからMicroBlazeが使えるのはとても良いと思います。Simple MicroBlazeにも応用ができそうです。Simple MicroBlazeの場合はBMMとELFファイルを使って、DATA2MEMでプログラムを入れる必要があると思います。

  1. 2011年08月17日 05:52 |
  2. MicroBlazeクロスコンパイラ
  3. | トラックバック:0
  4. | コメント:2

EDKのシミュレーション

カスタムIPのBFMシミュレーションはライセンスの関係で出来なかったが、ISEでEDKのインスタンスをADDした場合のシミュレーションをやってみた。

Project Navigatorで右クリックメニューからAdd Source...を選択して、elfファイルを選択する。(axi_timer_test.elfをAddする)
SP605_AXI_CDC_45_110817.png

Adding Source Files...ダイアログが開く。
SP605_AXI_CDC_46_110817.png

Elf/Xmp File Associatonsダイアログが開く。simulationとimplementationの両方にチェックを入れた。
SP605_AXI_CDC_47_110817.png

axi_timer_test.elf がEDKの下に入って、前に入っていたmonitor.elfは外に出た。
SP605_AXI_CDC_48_110817.png

EDKの右クリックメニューに、Elf/Xmp File Associatons...があるので、それを選択する。
SP605_AXI_CDC_49_110817.png

Elf/Xmp File Associatonsダイアログが開いて、elfファイルを選択できるようになった。
SP605_AXI_CDC_50_110817.png

monitor.elfを選択した。
SP605_AXI_CDC_51_110817.png

Project Navigatorに戻ると、EDKの下にmonitor.elfが入った。
SP605_AXI_CDC_52_110817.png

Project Navigatorをシミュレーションモードにして、テストベンチを作った。
SP605_AXI_CDC_53_110817.png

テストベンチ、system_top_tb.v を下に示す。

`timescale 100ps / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   05:32:57 08/16/2011
// Design Name:   system_top
// Module Name:   H:/HDL/FndtnISEWork/Spartan6/SP605_AXI_CharDispCtrler5/system_top_tb.v
// Project Name:  SP605_AXI_CharDispCtrler5
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: system_top
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module system_top_tb;

    // Inputs
    reg SysACE_MPIRQ;
    reg SysACE_CLK;
    reg RS232_Uart_1_sin;
    reg RESET;
    reg [0:3] Push_Buttons_4Bits_TRI_I;
    reg Ethernet_Lite_TX_CLK;
    reg Ethernet_Lite_RX_ER;
    reg Ethernet_Lite_RX_DV;
    reg Ethernet_Lite_RX_CLK;
    reg [3:0] Ethernet_Lite_RXD;
    reg Ethernet_Lite_CRS;
    reg Ethernet_Lite_COL;
    reg [0:3] DIP_Switches_4Bits_TRI_I;
    reg CLK_P;
    reg CLK_N;

    // Outputs
    wire mcbx_dram_we_n;
    wire mcbx_dram_udm;
    wire mcbx_dram_ras_n;
    wire mcbx_dram_odt;
    wire mcbx_dram_ldm;
    wire mcbx_dram_ddr3_rst;
    wire mcbx_dram_clk_n;
    wire mcbx_dram_clk;
    wire mcbx_dram_cke;
    wire mcbx_dram_cas_n;
    wire [2:0] mcbx_dram_ba;
    wire [12:0] mcbx_dram_addr;
    wire SysACE_WEN;
    wire SysACE_OEN;
    wire [6:0] SysACE_MPA;
    wire SysACE_CEN;
    wire RS232_Uart_1_sout;
    wire [0:3] LEDs_4Bits_TRI_O;
    wire Ethernet_Lite_TX_EN;
    wire [3:0] Ethernet_Lite_TXD;
    wire Ethernet_Lite_PHY_RST_N;
    wire Ethernet_Lite_MDC;
    wire dvi_reset_b;
    wire dvi_sda;
    wire dvi_v;
    wire [11:0] dvi_d;
    wire dvi_xclk_n;
    wire dvi_de;
    wire dvi_xclk_p;
    wire dvi_h;
    wire dvi_scl;

    // Bidirs
    wire zio;
    wire rzq;
    wire mcbx_dram_udqs_n;
    wire mcbx_dram_udqs;
    wire mcbx_dram_dqs_n;
    wire mcbx_dram_dqs;
    wire [15:0] mcbx_dram_dq;
    wire [7:0] SysACE_MPD;
    wire SPI_FLASH_SS;
    wire SPI_FLASH_SCLK;
    wire SPI_FLASH_MOSI;
    wire SPI_FLASH_MISO;
    wire IIC_EEPROM_SDA;
    wire IIC_EEPROM_SCL;
    wire Ethernet_Lite_MDIO;

    // Instantiate the Unit Under Test (UUT)
    system_top uut (
        .zio(zio), 
        .rzq(rzq), 
        .mcbx_dram_we_n(mcbx_dram_we_n), 
        .mcbx_dram_udqs_n(mcbx_dram_udqs_n), 
        .mcbx_dram_udqs(mcbx_dram_udqs), 
        .mcbx_dram_udm(mcbx_dram_udm), 
        .mcbx_dram_ras_n(mcbx_dram_ras_n), 
        .mcbx_dram_odt(mcbx_dram_odt), 
        .mcbx_dram_ldm(mcbx_dram_ldm), 
        .mcbx_dram_dqs_n(mcbx_dram_dqs_n), 
        .mcbx_dram_dqs(mcbx_dram_dqs), 
        .mcbx_dram_dq(mcbx_dram_dq), 
        .mcbx_dram_ddr3_rst(mcbx_dram_ddr3_rst), 
        .mcbx_dram_clk_n(mcbx_dram_clk_n), 
        .mcbx_dram_clk(mcbx_dram_clk), 
        .mcbx_dram_cke(mcbx_dram_cke), 
        .mcbx_dram_cas_n(mcbx_dram_cas_n), 
        .mcbx_dram_ba(mcbx_dram_ba), 
        .mcbx_dram_addr(mcbx_dram_addr), 
        .SysACE_WEN(SysACE_WEN), 
        .SysACE_OEN(SysACE_OEN), 
        .SysACE_MPIRQ(SysACE_MPIRQ), 
        .SysACE_MPD(SysACE_MPD), 
        .SysACE_MPA(SysACE_MPA), 
        .SysACE_CLK(SysACE_CLK), 
        .SysACE_CEN(SysACE_CEN), 
        .SPI_FLASH_SS(SPI_FLASH_SS), 
        .SPI_FLASH_SCLK(SPI_FLASH_SCLK), 
        .SPI_FLASH_MOSI(SPI_FLASH_MOSI), 
        .SPI_FLASH_MISO(SPI_FLASH_MISO), 
        .RS232_Uart_1_sout(RS232_Uart_1_sout), 
        .RS232_Uart_1_sin(RS232_Uart_1_sin), 
        .RESET(RESET), 
        .Push_Buttons_4Bits_TRI_I(Push_Buttons_4Bits_TRI_I), 
        .LEDs_4Bits_TRI_O(LEDs_4Bits_TRI_O), 
        .IIC_EEPROM_SDA(IIC_EEPROM_SDA), 
        .IIC_EEPROM_SCL(IIC_EEPROM_SCL), 
        .Ethernet_Lite_TX_EN(Ethernet_Lite_TX_EN), 
        .Ethernet_Lite_TX_CLK(Ethernet_Lite_TX_CLK), 
        .Ethernet_Lite_TXD(Ethernet_Lite_TXD), 
        .Ethernet_Lite_RX_ER(Ethernet_Lite_RX_ER), 
        .Ethernet_Lite_RX_DV(Ethernet_Lite_RX_DV), 
        .Ethernet_Lite_RX_CLK(Ethernet_Lite_RX_CLK), 
        .Ethernet_Lite_RXD(Ethernet_Lite_RXD), 
        .Ethernet_Lite_PHY_RST_N(Ethernet_Lite_PHY_RST_N), 
        .Ethernet_Lite_MDIO(Ethernet_Lite_MDIO), 
        .Ethernet_Lite_MDC(Ethernet_Lite_MDC), 
        .Ethernet_Lite_CRS(Ethernet_Lite_CRS), 
        .Ethernet_Lite_COL(Ethernet_Lite_COL), 
        .DIP_Switches_4Bits_TRI_I(DIP_Switches_4Bits_TRI_I), 
        .CLK_P(CLK_P), 
        .CLK_N(CLK_N), 
        .dvi_reset_b(dvi_reset_b), 
        .dvi_sda(dvi_sda), 
        .dvi_v(dvi_v), 
        .dvi_d(dvi_d), 
        .dvi_xclk_n(dvi_xclk_n), 
        .dvi_de(dvi_de), 
        .dvi_xclk_p(dvi_xclk_p), 
        .dvi_h(dvi_h), 
        .dvi_scl(dvi_scl)
    );
    
    parameter PERIOD = 50; // 200MHz clock
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;
    
    initial    // Clock process for clk
    begin
        CLK_P = 1'b0;
        CLK_N = 1'b1;
        #OFFSET;
        forever begin
            CLK_P = 1'b0;
                CLK_N = 1'b1;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) CLK_P = 1'b1; CLK_N = 1'b0;
            #(PERIOD*DUTY_CYCLE);
        end
    end

    initial begin
        // Initialize Inputs
        SysACE_MPIRQ = 0;
        SysACE_CLK = 0;
        RS232_Uart_1_sin = 0;
        RESET = 1'b1;
        Push_Buttons_4Bits_TRI_I = 0;
        Ethernet_Lite_TX_CLK = 0;
        Ethernet_Lite_RX_ER = 0;
        Ethernet_Lite_RX_DV = 0;
        Ethernet_Lite_RX_CLK = 0;
        Ethernet_Lite_RXD = 0;
        Ethernet_Lite_CRS = 0;
        Ethernet_Lite_COL = 0;
        DIP_Switches_4Bits_TRI_I = 0;

        // Wait 100 ns for global reset to finish
        #1000;
        // Add stimulus here
        #500;
        RESET = 1'b0;
        
    end
      
endmodule


Simulate Behavioral Modelをダブルクリックすると、コンパイルし、ISimが起動した。200usec 程度シミュレーションした結果を下に示す。
SP605_AXI_CDC_54_110817.png

MicroBlazeの命令は、instr[0.31]だと思う。instr_addr[0.31]がそのアドレスだと思うが、0番地から4, 8, C番地と飛んで、その後、0xc0000000番地に飛んで、0xc0000004番地で実行が停止している。後は、ELFファイルを解析する必要がありそうだ。
SP605_AXI_CDC_55_110817.png

このやり方は、”マイクロプロセッサ IP およびペリフェラル IP の使用”の”ELF ファイルを ISE デザインのエンベデッド プロセッサに関連付けるには”、”エンベデッド プロセッサ システムをシミュレーションするには”に書いてあった。
  1. 2011年08月17日 05:26 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

ガイガーカウンターを乾電池駆動にしました

以前作成したガイガーカウンターを、乾電池駆動にして、板に貼り付けました。

電池駆動にする際には、秋月電子の3.3VDC-DCコンバータを実装しました。2本の乾電池からDC-DCコンバータに入力して、その出力をガイガーカウンターに入れました。正常に動作しているようです。
作業はFPGA-CAFEでやらせて頂きました。皆さんありがとうございました。いろいろ面白いお話が出来て楽しかったです。
Geiger_counter_110814.jpg

これにiPnoneのガイガーボットを併用すれば、CPMや(多分)セシウム換算したuSV/hも表示できます。
  1. 2011年08月14日 20:58 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

axi_timerを使う2(割り込みを使用した)

”axi_timerを使う1"で、ポーリングでは、axi_timerを使うことができたが、割り込みでは使えなかった、今回はその理由を探ってみることにした。

まずは、ネットを検索して、MicroBlazeの割り込みに関しての資料を探した。その結果、
Using and Creating Interrupt-Based Systems XAPP778 (v1.0) January 11, 2005
エンベデッド システムツール リファレンス マニュアル EDK10.1 サービス パック1”の付録B 割り込み制御
がわかった。

さて、XPSを起動して、Portsタブをクリックし、axi_timerを展開してみる。Interruptはaxi_timer_0_Interrupt信号に接続されている。
SP605_AXI_CDC_42_110814.png

次に、microblaze_0 を展開してみてみると、Interruptはmicroblaze_0_interrupt 信号に接続されている。
SP605_AXI_CDC_43_110814.png

microblaze_0 のInterrupt をaxi_timer_0_Interruptにつなぎ変えてみた。
SP605_AXI_CDC_44_110814.png

ProjectメニューからRescan User Repositories を選択して、リポジトリを作りなおす。
ISE(Project Navigator) で再度インプリメントした。

SDKを立ち上げ、ビットファイルをダウンロードして、デバックモードで実行したら、割り込みを使用したプログラムが正常に実行できた。そのプログラムを下に示す。

/* * axi_timer_test.c * *  Created on: 2011/08/12 *      Author: Masaaki */

#include "xbasic_types.h"
#include "xio.h"
#include "mb_interface.h"
#include "xparameters.h"

#define AXI_TIMER_0_TCSR0    XPAR_AXI_TIMER_0_BASEADDR    // Control/Status Register 0
#define AXI_TIMER_0_TLR0    XPAR_AXI_TIMER_0_BASEADDR+0x4    // Load Register 0
#define AXI_TIMER_0_TCR0    XPAR_AXI_TIMER_0_BASEADDR+0x8    // Timer/Counter Register 0
#define AXI_TIMER_0_TCSR1    XPAR_AXI_TIMER_0_BASEADDR+0x10    // Control/Status Register 1
#define AXI_TIMER_0_TLR1    XPAR_AXI_TIMER_0_BASEADDR+0x14    // Load Register 1
#define AXI_TIMER_0_TCR1    XPAR_AXI_TIMER_0_BASEADDR+0x18    // Timer/Counter Register 1

#define ENABLE_ALL_TIMERS                (0x1<<10)
#define ENABLE_PULSE_WIDTH_MODULATION    (0x1<<9)
#define    TIMER_INTERRUPT                    (0x1<<8)
#define ENABLE_TIMER                    (0x1<<7)
#define ENABLE_INTERRUPT                (0x1<<6)
#define LOAD_TIMER                        (0x1<<5)
#define AUTO_RELOAD_HOLD_TIMER            (0x1<<4)
#define ENABLE_EXT_CAPTURE_TRIG            (0x1<<3)
#define ENABLE_EXT_GENERATE_SIG            (0x1<<2)
#define DOWN_UP_COUNT_TIMER                (0x1<<1)
#define TIMER_MODE_CAP_GENE                (0x1)

int interrupt = 0;

void axi_timer_init(){
    *(volatile *)(AXI_TIMER_0_TLR0) = 0x004C4B40; // 0.1秒
    // *(volatile *)(AXI_TIMER_0_TLR0) = 0x00989680; // 0.2秒
    *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | LOAD_TIMER; // TLR0へロード
    *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | ENABLE_TIMER | ENABLE_INTERRUPT | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER; // GenerateモードでDWONカウント、割り込みあり、オートロードあり
}

void timer_int_handler(void * arg) {
    interrupt = 1;
}

void write_data(unsigned int address, unsigned int data)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
}

int read_data(unsigned int address)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    return(*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4));
}

int main()
{
    unsigned int addr;
    unsigned int color, char_code, data;
    unsigned int temp;

    axi_timer_init(); // axi_timerの初期化

    // 割り込みハンドラ登録、割り込み許可
    microblaze_register_handler(timer_int_handler, (void *) 0);
    microblaze_enable_interrupts();

    for(addr=0, color=1, char_code=0x21; addr < 100*75; addr++, color++, char_code++){
        data = (color & 0x7)<<7 | char_code;
        write_data(addr, data);
        if (char_code == 0x7e) // キャラクタの~
            char_code = 0x20// キャラクタの!
        if ((color & 0x7) == 7)
            color = 0;

        // axi_timter割り込み待ち
        interrupt = 0;
        while(interrupt==0);
        *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | ENABLE_TIMER | ENABLE_INTERRUPT | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER | TIMER_INTERRUPT;

    }

    return 0;
}


  1. 2011年08月14日 20:45 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

axi_timerを使う1

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る8”でやった表示を0.2秒ごとに書きたいと思い、axi_timerを使ってみることにした。

axi_timerのデータシートはこちら以前にxps_timerのことを書いたことがあった。ほとんど同じだと思う。
今回は、Auto Reload/Hold Timerのビットを1にして、Downカウントにしようと思う。それから、InterruptもONにしたい。
手順を下に示す。timer0をgenerateモードで使用する。

1.XPAR_AXI_TIMER_0_BASEADDR+0x4アドレス(Load Registger, TLR0)に、ロードする値をWriteする。50MHzなので、0.2秒では10000000、16進に直すと0x00989680

2.XPAR_AXI_TIMER_0_BASEADDRアドレス(Control/Status Register, TCSR0)に、10ビット目のENALL、5ビット目のLOAD0を1にして、Writeする (0x00000420)。

3.XPAR_AXI_TIMER_0_BASEADDR+8アドレス(Timer/Counter Register, TCR0)を見ると、0x00989680ガロードされている。

4.XPAR_AXI_TIMER_0_BASEADDRアドレス(Control/Status Register, TCSR0)に、10ビット目のENALL、7ビット目のENT0、6ビット目のEINT0、4ビット目のARHT0、1ビット目のUDT0を1にする。(0x000004D2) GenerateモードでDWONカウント、割り込みあり、オートロードあり。

5.割り込みハンドラを使って、割り込みが来たら、色を替えたキャラクタを表示する。

これをCプログラムにしたのが、下のコードとなる。

/* * axi_timer_test.c * *  Created on: 2011/08/12 *      Author: Masaaki */

#include "xbasic_types.h"
#include "xio.h"
#include "mb_interface.h"
#include "xparameters.h"

#define AXI_TIMER_0_TCSR0    XPAR_AXI_TIMER_0_BASEADDR    // Control/Status Register 0
#define AXI_TIMER_0_TLR0    XPAR_AXI_TIMER_0_BASEADDR+0x4    // Load Register 0
#define AXI_TIMER_0_TCR0    XPAR_AXI_TIMER_0_BASEADDR+0x8    // Timer/Counter Register 0
#define AXI_TIMER_0_TCSR1    XPAR_AXI_TIMER_0_BASEADDR+0x10    // Control/Status Register 1
#define AXI_TIMER_0_TLR1    XPAR_AXI_TIMER_0_BASEADDR+0x14    // Load Register 1
#define AXI_TIMER_0_TCR1    XPAR_AXI_TIMER_0_BASEADDR+0x18    // Timer/Counter Register 1

int interrupt = 0;

void axi_timer_init(){
    *(volatile *)(AXI_TIMER_0_TLR0) = 0x00989680// 0.2秒
    *(volatile *)(AXI_TIMER_0_TCSR0) = 0x00000420// TLR0へロード
    *(volatile *)(AXI_TIMER_0_TCSR0) = 0x000004D2; // GenerateモードでDWONカウント、割り込みあり、オートロードあり
}

void timer_int_handler(void * arg) {
    interrupt = 1;
}

void write_data(unsigned int address, unsigned int data)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
}

int read_data(unsigned int address)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    return(*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4));
}

int main()
{
    unsigned int addr;
    unsigned int color, char_code, data;

    axi_timer_init(); // axi_timerの初期化

    // 割り込みハンドラ登録、割り込み許可
    microblaze_register_handler(timer_int_handler, (void *) 0);
    microblaze_enable_interrupts();

    for(addr=0, color=1, char_code=0x21; addr < 100*75; addr++, color++, char_code++){
        data = (color & 0x7)<<7 | char_code;
        write_data(addr, data);
        if (char_code == 0x7e) // キャラクタの~
            char_code = 0x20// キャラクタの!
        if ((color & 0x7) == 7)
            color = 0;

        // axi_timter割り込み待ち
        interrupt = 0;
        while(interrupt==0);
    }

    return 0;
}


これを実行すると、while(interrupt==0);から進まない。割り込みがかかっていないようだ。

次に割り込みをやめて、AXI_TIMER_0_TCSR0をReadして、T0INが1になるの待つ。そうなったら、一文字Writeして、T0INに1をWriteしてT0INをクリアするという手順でやってみた。今回は、TimerのControl/Statusレジスタのビットの割り当てをデファインして、ORして設定するという手順を取ることにした。そのCコードを下に示す。microblaze_register_handler()、microblaze_enable_interrupts()は行っているが、割り込みルーチンtimer_int_handler()を使用していないので、関係がなくなっている。

/* * axi_timer_test.c * *  Created on: 2011/08/12 *      Author: Masaaki */
#include "xbasic_types.h"
#include "xio.h"
#include "mb_interface.h"
#include "xparameters.h"

#define AXI_TIMER_0_TCSR0    XPAR_AXI_TIMER_0_BASEADDR    // Control/Status Register 0
#define AXI_TIMER_0_TLR0    XPAR_AXI_TIMER_0_BASEADDR+0x4    // Load Register 0
#define AXI_TIMER_0_TCR0    XPAR_AXI_TIMER_0_BASEADDR+0x8    // Timer/Counter Register 0
#define AXI_TIMER_0_TCSR1    XPAR_AXI_TIMER_0_BASEADDR+0x10    // Control/Status Register 1
#define AXI_TIMER_0_TLR1    XPAR_AXI_TIMER_0_BASEADDR+0x14    // Load Register 1
#define AXI_TIMER_0_TCR1    XPAR_AXI_TIMER_0_BASEADDR+0x18    // Timer/Counter Register 1

#define ENABLE_ALL_TIMERS                (0x1<<10)
#define ENABLE_PULSE_WIDTH_MODULATION    (0x1<<9)
#define TIMER_INTERRUPT                    (0x1<<8)
#define ENABLE_TIMER                    (0x1<<7)
#define ENABLE_INTERRUPT                (0x1<<6)
#define LOAD_TIMER                        (0x1<<5)
#define AUTO_RELOAD_HOLD_TIMER            (0x1<<4)
#define ENABLE_EXT_CAPTURE_TRIG            (0x1<<3)
#define ENABLE_EXT_GENERATE_SIG            (0x1<<2)
#define DOWN_UP_COUNT_TIMER                (0x1<<1)
#define TIMER_MODE_CAP_GENE                (0x1)

int interrupt = 0;

void axi_timer_init(){
    *(volatile *)(AXI_TIMER_0_TLR0) = 0x004C4B40; // 0.1秒
    // *(volatile *)(AXI_TIMER_0_TLR0) = 0x00989680; // 0.2秒
    *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | LOAD_TIMER; // TLR0へロード
    *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | ENABLE_TIMER | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER; // GenerateモードでDWONカウント、割り込みあり、オートロードあり
}

void timer_int_handler(void * arg) {
    interrupt = 1;
}

void write_data(unsigned int address, unsigned int data)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
}

int read_data(unsigned int address)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    return(*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4));
}

int main()
{
    unsigned int addr;
    unsigned int color, char_code, data;
    unsigned int temp;

    axi_timer_init(); // axi_timerの初期化

    // 割り込みハンドラ登録、割り込み許可
    microblaze_register_handler(timer_int_handler, (void *) 0);
    microblaze_enable_interrupts();

    for(addr=0, color=1, char_code=0x21; addr < 100*75; addr++, color++, char_code++){
        data = (color & 0x7)<<7 | char_code;
        write_data(addr, data);
        if (char_code == 0x7e) // キャラクタの~
            char_code = 0x20// キャラクタの!
        if ((color & 0x7) == 7)
            color = 0;

        // axi_timter割り込み待ち
        // interrupt = 0;
        // while(interrupt==0);
        do{
            temp = *(volatile *)(AXI_TIMER_0_TCSR0);
        }while((temp & TIMER_INTERRUPT)==0);
        *(volatile *)(AXI_TIMER_0_TCSR0) = ENABLE_ALL_TIMERS | ENABLE_TIMER | AUTO_RELOAD_HOLD_TIMER | DOWN_UP_COUNT_TIMER | TIMER_INTERRUPT;
    }

    return 0;
}


0.2秒に1回では、SVGAではキャラクタを書くのがあまりに遅いので、0.1秒単位に変更した。割り込み使わなければうまくいきました。
SP605_AXI_CDC_41_110813.jpg
  1. 2011年08月13日 20:28 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

お盆、9連休

明日からお盆で、9連休です。職場の節電のために来るなということになりました。
明日は、コミケMaid by Susutawari ブースが 8月13日 東2 T-02a に出るので、行きたかったのですが、田舎では迎え盆のため行けません。。。残念です。FPGA技術No.6に書かせていただいたので、応援に行きたかったです。
明日から、仙台に行っている娘が帰ってくるので、楽しみです。大学のことなどを聞こうと思っていますが、いろいろ友達にあったり忙しいようです。

  1. 2011年08月12日 21:22 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る8

”AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る7”で、異なったクロック・ドメイン間のデータの受け渡しの問題を解決できた。もう少し確かめてみることにした。

今度は、以前のキャラクタ・ディスプレイ・コントローラのテストのように、いろいろな文字を表示しながら、色を変えるプログラムをつくってみた。Cソースを下に示す。

// Monitor
// 2011/08/11

#include "xparameters.h"

void write_data(unsigned int address, unsigned int data)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
}

int read_data(unsigned int address)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    return(*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4));
}

int main()
{
    unsigned int addr;
    unsigned int color, char_code, data;

    for(addr=0, color=1, char_code=0x21; addr < 100*75; addr++, color++, char_code++){
        data = (color & 0x7)<<7 | char_code;
        write_data(addr, data);
        if (char_code == 0x7e) // キャラクタの~
            char_code = 0x21// キャラクタの!
        if ((color & 0x7) == 7)
            color = 0;
    }

    return 0;
}


これを実行すると、成功しました。回路は大丈夫そうです。
SP605_AXI_CDC_40_110811.jpg

  1. 2011年08月11日 05:11 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る7

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る6”で、画面いっぱいにA を出したはずなのに、書けていない場所があった。今回はその理由を探ってみた。(くだらないミスでした)

user_logic.vhd で、CharDispCtrler_SP605.v をインスタンスしている。processer_weには、we_1dを入れたが、これは50MHzのクロックに同期した信号だった。
SP605_AXI_CDC_23_110802.png

CharDispCtrler_SP605.v でクロックをピクセル・クロックにするために40MHz(SVGAでした)に落としている。それなのに、processer_weは50MHzで同期した信号を入れてしまった。アドレスやデータは、その前から確定してるので問題はないようだ。
そこで、50MHzと40MHzをつなぐハンドシェーク回路を付けた。下にそれを示す。clkinが50MHz、clkが40MHzクロックだ。

    reg        we_clkin;
    wire    we_ena_clkin;
    reg        we_ena_clkin_1d, we_ena_clkin_2d;
    reg        we_in_clk_1d, we_in_clk_2d;
    parameter    IDLE_WE =        3'b001,
                WE_ENA_PXCLK =    3'b010,
                WE_WAIT =        3'b100;
    reg        [2:0]    cs_we;
    reg        we;
    
    
    // clkin でのwe を保持して、ハンドシェークする
    always @(posedge clkin) begin
        if (rst)
            we_clkin <= 1'b0;
        else begin
            if (processor_we)
                we_clkin <= 1'b1;
            else if (we_ena_clkin_2d)
                we_clkin <= 1'b0;
        end
    end
    
    // we_node をclkで同期化する
    always @(posedge clk) begin
        if (rst) begin
            we_in_clk_1d <= 1'b0;
            we_in_clk_2d <= 1'b0;
        end else begin
            we_in_clk_1d <= we_clkin;
            we_in_clk_2d <= we_in_clk_1d;
        end
    end
    
    // we を出力するステートマシン
    always @(posedge clk) begin
        if (rst) begin
            cs_we <= IDLE_WE;
            we <= 1'b0;
        end else begin
            case (cs_we)
                IDLE_WE : begin
                    if (we_in_clk_2d) begin
                        cs_we <= WE_ENA_PXCLK;
                        we <= 1'b1;
                    end
                end
                WE_ENA_PXCLK : begin
                    cs_we <= WE_WAIT;
                    we <= 1'b0;
                end
                WE_WAIT : begin
                    we <= 1'b0;
                    if (~we_in_clk_2d)
                        cs_we <= IDLE_WE;
                end
            endcase
        end
    end
    assign we_ena_clkin = (cs_we ==  WE_WAIT) ? 1'b1 : 1'b0;
    
    // we_ena_clkin をclkinで同期化
    always @(posedge clkin) begin
        if (rst) begin
            we_ena_clkin_1d <= 1'b0;
            we_ena_clkin_2d <= 1'b0;
        end else begin
            we_ena_clkin_1d <= we_ena_clkin;
            we_ena_clkin_2d <= we_ena_clkin_1d;
        end
    end
    
            
    dcm_inst dcm_inst_i (
        .clkin(clkin),
        .reset(rst),
        .clkout(clk),
        .clk90(clk90),
        .locked(locked)
    );
    assign reset = !locked;
    assign clkb = !clk;
    assign clk90b = !clk90;
//    assign dvi_reset_b = locked;
    assign dvi_reset_b = 1'b1;
    
    CharDispCtrler CharDispCtrler_inst (
        .clk(clk),
        .reset(reset),
        .processor_addr(processor_addr),
        .processor_din(processor_din),
        .processor_dout(processor_dout),
        .processor_we(we),


これで、コンパイルして、SDKでビットファイルをボードにダウンロードして、実行したら画面に、うまくA が並んだ。成功した。。。
SP605_AXI_CDC_39_110809.jpg

原因は、クロックが違っていることに気がつかなかったことだった。クロックを載せ替えたら問題が無くなった。
  1. 2011年08月10日 21:07 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る6

前回でMicroBlazeシステムにSVGAのキャラクタ・ディスプレイ・コントローラを実装できたので、ソフトウェアを書いて、制御してみることにした。

最初に画面を'A'で埋めてみることにした。empty_applicaion_0を作成して、ここを参考にしながら、monitor.c を書いた。下にリストを示す。

// Monitor
// 2011/08/07

#include "xparameters.h"

void write_data(unsigned int address, unsigned int data)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
}

int read_data(unsigned int address)
{
    *(volatile *)(XPAR_CHARDISPC_0_BASEADDR) = address;
    return(*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4));
}

int main()
{
    unsigned int addr;

    for(addr=0; addr < 100*75; addr++){
        write_data(addr, 0x3C1);
    }

    return 0;
}


これで、ビットファイルをSP605にダウンロードして、デバックモードにSDKを変更した。
SP605_AXI_CDC_36_110809.png

Resumeボタンをクリックして、実行してみた。'A'が全面に表示されるはずが、所々抜けてしまっている。
SP605_AXI_CDC_37_110809.jpg

あれれ?なんでだろう?思いがけない展開になってしまった。書けていないかもしれないので、試しにデータを書くところを増やしてみた。

*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;


欠損は減ってきた気がする。
SP605_AXI_CDC_38_110809.jpg

データの書き込みを増やして行った。増やすごとに欠損が減っていった。4つデータを書いたときに正常になった。

*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;
*(volatile *)(XPAR_CHARDISPC_0_BASEADDR+4) = data;


SP605_AXI_CDC_39_110809.jpg

不思議だ?なぜ?
Write enableは、フレームバッファ用のBRAMのWEに直結しているはずなんだけど。。。Out of Order実行でアドレスを先にWriteしていることがあるわけでもないですよね?それともデータキャッシュが入ってしまっているとか?
そういえば、以前もSMMで2回書かないと上手くいかないということがあったな?
ChipScope Proで本当に4回書いているかを確かめてみたい。
  1. 2011年08月09日 05:15 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

夏休み自由研究お助け企画

土曜日、日曜日と夏休み自由研究お助け企画がありました。今日は代休でお休みです。自宅の部屋の現在の温度は34度なので、かなりキツイです。

さて、夏休み自由研究お助け企画として、中学生相手に土曜日は音の実験をしました。かなり前からやっているものです。パソコンにダイナシステムさんのソフトウェア、HotWavを入れて、自分の音声を録音してもらって波形を観察し、波形を加工してもらいました。喜んでくれたようです。

日曜日は、秋月電子の太陽電池の特性を測ってもらう実験でした。これは、中学校1年生と中学校2年生の差が出てしまいした。中学校2年生はオームの法則、電力をすでに学習しているからです。それでも、1年生と2年生は別の時間帯だったので、1年生の方は電圧、電流、電力を説明してから実験してもらったので、時間が足りなくて、細かいところまで説明できませんでした。それでも、感想を聞いてみたら、楽しかったと言っていたので良かったです。(お世辞には聞こえませんでしたが、聞いたのは1人だったので、他の中学1年生がどう思っていたかはわかりません)
  1. 2011年08月08日 15:23 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る5

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る4”で作ったSP605のMicroBlazeシステムのキャラクタ・ディスプレイ・コントローラをVGA(640x480) からSVGA(800x600) に変更しました。

SVGA Signal 800 x 600 @ 60 Hz timing”を参考にしながら、disp_timing_parameters.vhを修正するだけで行けました。

// 表示タイミングの定義
// 800x600 60Hz, Pixel clock=40MHz

parameter H_ACTIVE_VIDEO= 800;
parameter H_FRONT_PORCH = 40;
parameter H_SYNC_PULSE = 128;
parameter H_BACK_PORCH = 88;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

parameter V_ACTIVE_VIDEO = 600;
parameter V_FRONT_PORCH = 1;
parameter V_SYNC_PULSE = 4;
parameter V_BACK_PORCH = 23;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

parameter H_DISPLAY_SIZE = H_ACTIVE_VIDEO/8; // 横100桁
parameter V_DISPLAY_SIZE = V_ACTIVE_VIDEO/8; // 縦75行

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


そうそう、ピクセルクロックも25MHzから40MHzに変更しました。
下の写真はSDKのXMDコンソールで下の値を入れた時の液晶ディスプレイの表示です。文字が小さくなりました。SVGA(800x600)です。

mwr 0x74200004 0x3C1
mwr 0x74200000 0x64
mwr 0x74200004 0x3C2


SP605_AXI_CDC_35_110806.jpg

下に、VGA(640x480) の時の画面を貼っておきます。
SP605_AXI_CDC_34_110804.jpg

いろいろ面白そうなことができます。WebPACKでもEDKやSDKが使えれば良いのですが。。。

なお、BFMシミュレーションはライセンスが無いと怒られて実行できませんでした。ライセンスを新たに購入しないと実行できないようです。
  1. 2011年08月06日 06:01 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る4

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る3”の続き。

前回でISEにインプリメントが終了した。今回はSDKを立ち上げてビットファイルをダウンロードする。(ISE13.2を使用)
AXIバスのEDKチュートリアルを試す10(カスタムIPを作る4)”を参照。

1.Project NavigatorのDesignのHierarchyウインドウでsystem_i(system.xmp)をクリックして、下のProcessesウインドウでExport Hardware Design to SDK with Bitstream を右クリックメニューから Process Properties... を選択する。

2.Process Propertiesを見るとLaunch SDK after Exportにすでにチェックが入っていた。

3.Project NavigatorのExport Hardware Design to SDK with Bitstream をダブルクリックして、SDKを起動する。

4.SDKが立ち上がって、ワークスペースを聞いてくる。ワークスペースの名前を入れてOKボタンをクリックする。(フォルダを作ってない状態で名前を入れた)
SP605_AXI_CDC_26_110804.png

5.SDKが起動した。
SP605_AXI_CDC_27_110804.png

6.File メニューからNew... -> Xilinx C Project を選択して、プロジェクトを作成する。
SP605_AXI_CDC_28_110804.png

7.Hellow Worldプロジェクトを生成する。
SP605_AXI_CDC_29_110804.png

SP605_AXI_CDC_30_110804.png

8.コンパイルされてDoneした。

9.SP605の電源をONした。

10.SDKでXilinx ToolsメニューからProgram FPGAを選択した。
SP605_AXI_EDK_42_110709.png

11.Program FPGAダイアログが開く。Programボタンをクリックする。
SP605_AXI_CDC_31_110804.png

12.SDKのProject Explorerで、hello_world_0の下のBinariesの下のhello_world_0.elfで右クリックして、右クリックメニューからDebug As -> Lanunch on Hardware を選択する。
SP605_AXI_EDK_44_110709.png

13.リンカー・スクリプトが走って、実行形式プログラム入のビットファイルがボードにダウンロードされる。C/C++ to Debugにパースペクティブを変更するダイアログが開くので、Yesボタンをクリックする。
SP605_AXI_EDK_45_110709.png

14.SDKにデバック用のパースペクティブが表示された。
SP605_AXI_CDC_32_110804.png

15.SDKの上の真ん中のウインドウタブでXMDを選択する。
SP605_AXI_CDC_33_110804.png

16.XMDコンソールで下のコマンドを入力した。

mwr 0x74200000 0x0
mwr 0x74200004 0x3C1
mwr 0x74200000 0x4
mwr 0x74200004 0x3C2



17.SP605のDVI-Iコネクタから、VGA変換プラグを通して液晶ディスプレイに接続すると、AとBの文字が見えた。
SP605_AXI_CDC_34_110804.jpg

18.XMDコンソールで下のコマンドを入力してリードした。(XMDコンソールの内容をコピペする)リードもOKだ。

XMD% mrd 0x74200000
74200000: 00000004

XMD% mrd 0x74200004
74200004: 000003C2

XMD% mwr 0x74200000 0x0
XMD% mrd 0x74200004
74200004: 000003C1



うまく行った。嬉しい。
注意点としては、カスタムIPを修正したら、XPSでクリーンアップして、Project Navigatorでインプリメントしてから、Export Hardware Design to SDK with Bitstream をダブルクリックしてSDKを立ち上げないと、ハードウェアの変更が反映されないことだ。これで、時間を潰してしまった。

今度は、ソフトウェアを開発してみたい。モニタ作るのも良いかも?その前に現在の画面は、640x480なので、800x600くらいに拡大しようか?

(追記)
アドレスマップを解説します。

0x74200000 :レジスタ1、キャラクタ・ディスプレイ・コントローラのアドレスを示す。Readの場合はレジスタ1の内容がそのまま出力される。
0x74200004 :レジスタ2、キャラクタ・ディスプレイ・コントローラのデータを示す。このレジスタにWriteすると、キャラクタ・ディスプレイ・コントローラのフレーム・バッファのレジスタ1で示された番地にデータがWriteされる。Readの場合は、フレーム・バッファのレジスタ1で示された番地の内容をReadする。


キャラクタ・ディスプレイ・コントローラについては、”キャラクタ・ディスプレイ・コントローラの構成”辺りを参照してください。
  1. 2011年08月04日 05:39 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る3

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る2”の続き。

基本的には、”AXIバスのEDKチュートリアルを試す9(カスタムIPを作る3)”を見ながら、同じように作業を進めています。

1.system\pcores\chardispc_v1_00_a\dataのchardispc_v2_1_0.mpd を開いて、##Portsの項目にDVI関係のポート宣言を追加する。

PORT dvi_xclk_p = "", DIR = O
PORT dvi_xclk_n = "", DIR = O
PORT dvi_de = "", DIR = O
PORT dvi_h = "", DIR = O
PORT dvi_v = "", DIR = O
PORT dvi_d = "", DIR = O, VEC = [11:0]
PORT dvi_reset_b = "", DIR = O
PORT dvi_sda = "", DIR = O
PORT dvi_scl = "", DIR = O



2.XPSでProjectメニューから> Rescan User Repositoriesを選択して、chardispc pcoreの変更をXPSに認識させる。

3.XPSのIP CatalogからProject Local PCores -> USER -> CHARDISPC を選んで、右クリックメニューからAdd IPを選択する。

4.XPS Core Configダイアログが開く。多分、C_NUM_REGはレジスタの数を示すと思うので2 に変更した。
SP605_AXI_CDC_9_110731.png

5.Instantiate and Connect IPダイアログが開く。Select the MicroBlaze Instance to Connect toでmicroblze_0が選ばれている。MicroBlazeは1個だけなので、選べるのはmicroblze_0のみ。

6.XPSのBus Interfaceタブを見ると、chardispc コアが入っているのがわかる。次に、chardispc とDVI関連の信号間に外部接続を作る必要がある。
SP605_AXI_CDC_10_110731.png

7.Portsタブをクリックする。chardispc_0 を展開して、DVI関連の信号をすべて選択して、右クリックメニューからMake External を選択する。
SP605_AXI_CDC_11_110731.png

8.外部ピンは、名前の前にchardispc_0_ が付いて、名前の後ろに_pin が付いたファイル名になった。
SP605_AXI_CDC_12_110731.png

9.設定した外部品の名前の前のchardispc_0_ と名前の後ろの_pin を削除した。
SP605_AXI_CDC_24_110802.png

10.Addressタブをクリックすると、blink_0のアドレス領域が0x74800000から0x7480FFFFであることがわかる。64Kbyteのアドレスを割りつけられている。
SP605_AXI_CDC_13_110731.png

・MHSファイルで、DVI関連のピン名を変更することもできるようだ。Projectタブを選択して、Project Files のMHS File: system.mhs をダブルクリックする。PORTの最後の方にchardispc_0 関連の信号ピンが見える。
SP605_AXI_CDC_14_110731.png

・名前の前のchardispc_0_ と名前の後ろの_pin を削除した。FileメニューからSaveを選択して、セーブする。
SP605_AXI_CDC_15_110731.png

・Reload Projectダイアログが出る。Reloadボタンをクリックする。
SP605_AXI_CDC_16_110731.png

・プロジェクトがリロードされて、External Portsの名前が変更された。
SP605_AXI_CDC_17_110731.png


11.UCFを編集する。UCF File: data/system.ucfをダブルクリックする。

12.system.ucfファイルが表示された。DVI関連の信号の制約を追加し、セーブした。
SP605_AXI_CDC_18_110731.png

追加したUCFを下に示す。

NET "dvi_d[0]" IOSTANDARD = LVCMOS25;
NET "dvi_d[0]" DRIVE = 12;
NET "dvi_d[0]" LOC = K16;
NET "dvi_d[1]" IOSTANDARD = LVCMOS25;
NET "dvi_d[1]" DRIVE = 12;
NET "dvi_d[1]" LOC = U19;
NET "dvi_d[2]" IOSTANDARD = LVCMOS25;
NET "dvi_d[2]" DRIVE = 12;
NET "dvi_d[2]" LOC = T20;
NET "dvi_d[3]" IOSTANDARD = LVCMOS25;
NET "dvi_d[3]" DRIVE = 12;
NET "dvi_d[3]" LOC = N16;
NET "dvi_d[4]" IOSTANDARD = LVCMOS25;
NET "dvi_d[4]" DRIVE = 12;
NET "dvi_d[4]" LOC = P16;
NET "dvi_d[5]" IOSTANDARD = LVCMOS25;
NET "dvi_d[5]" DRIVE = 12;
NET "dvi_d[5]" LOC = M17;
NET "dvi_d[6]" IOSTANDARD = LVCMOS25;
NET "dvi_d[6]" DRIVE = 12;
NET "dvi_d[6]" LOC = M18;
NET "dvi_d[7]" IOSTANDARD = LVCMOS25;
NET "dvi_d[7]" DRIVE = 12;
NET "dvi_d[7]" LOC = R15;
NET "dvi_d[8]" IOSTANDARD = LVCMOS25;
NET "dvi_d[8]" DRIVE = 12;
NET "dvi_d[8]" LOC = R16;
NET "dvi_d[9]" IOSTANDARD = LVCMOS25;
NET "dvi_d[9]" DRIVE = 12;
NET "dvi_d[9]" LOC = P17;
NET "dvi_d[10]" IOSTANDARD = LVCMOS25;
NET "dvi_d[10]" DRIVE = 12;
NET "dvi_d[10]" LOC = P18;
NET "dvi_d[11]" IOSTANDARD = LVCMOS25;
NET "dvi_d[11]" DRIVE = 12;
NET "dvi_d[11]" LOC = R17;
NET "dvi_de" IOSTANDARD = LVCMOS25;
NET "dvi_de" DRIVE = 12;
NET "dvi_de" LOC = J17;
NET "dvi_h" IOSTANDARD = LVCMOS25;
NET "dvi_h" DRIVE = 12;
NET "dvi_h" LOC = J16;
NET "dvi_reset_b" IOSTANDARD = LVCMOS25;
NET "dvi_reset_b" DRIVE = 12;
NET "dvi_reset_b" LOC = L15;
NET "dvi_v" IOSTANDARD = LVCMOS25;
NET "dvi_v" DRIVE = 12;
NET "dvi_v" LOC = B22;
NET "dvi_xclk_n" SLEW = FAST;
NET "dvi_xclk_n" IOSTANDARD = LVCMOS25;
NET "dvi_xclk_n" DRIVE = 12;
NET "dvi_xclk_n" LOC = C22;
NET "dvi_xclk_p" SLEW = FAST;
NET "dvi_xclk_p" IOSTANDARD = LVCMOS25;
NET "dvi_xclk_p" DRIVE = 12;
NET "dvi_xclk_p" LOC = C20;
NET "dvi_sda" IOSTANDARD = LVCMOS25;
NET "dvi_sda" DRIVE = 12;
NET "dvi_sda" LOC = AA4;
NET "dvi_scl" IOSTANDARD = LVCMOS25;
NET "dvi_scl" DRIVE = 12;
NET "dvi_scl" LOC = W13;


13.XPSを閉じて、Project Navigatorに戻り、Hierarchyウインドウでsystemを選択する。下のProcessesウインドウでGenerate Top HDL Source をダブルクリックして、トップレベルファイルを生成する。

14.ProcessesウインドウでGenerate Programming File をダブルクリックして、インプリメントを開始した。

15.インプリメントが終了した。使用したLUTは19%だった。前回が21%だったので、ロジックを増やしたはずが減っている?何か消えているかもしれない?
SP605_AXI_CDC_25_110803.png

下にMAPリポートの一部を示す。

Release 13.2 Map O.61xd (nt)
Xilinx Mapping Report File for Design 'system_top'

Design Information
------------------
Command Line   : map -intstyle ise -p xc6slx45t-fgg484-3 -w -logic_opt off -ol high -t 1 -xt 0 -register_duplication off
-r 4 -global_opt off -mt off -ir off -pr off -lc off -power off -o system_top_map.ncd system_top.ngd system_top.pcf 
Target Device  : xc6slx45t
Target Package : fgg484
Target Speed   : -3
Mapper Version : spartan6 -- $Revision: 1.55 $
Mapped Date    : TUE 2 AUG 20:52:36 2011

Design Summary
--------------
Number of errors:      0
Number of warnings:   29
Slice Logic Utilization:
  Number of Slice Registers:                 4,348 out of  54,576    7%
    Number used as Flip Flops:               4,340
    Number used as Latches:                      0
    Number used as Latch-thrus:                  0
    Number used as AND/OR logics:                8
  Number of Slice LUTs:                      5,190 out of  27,288   19%
    Number used as logic:                    4,792 out of  27,288   17%
      Number using O6 output only:           3,660
      Number using O5 output only:             119
      Number using O5 and O6:                1,013
      Number used as ROM:                        0
    Number used as Memory:                     252 out of   6,408    3%
      Number used as Dual Port RAM:             96
        Number using O6 output only:             4
        Number using O5 output only:             1
        Number using O5 and O6:                 91
      Number used as Single Port RAM:            4
        Number using O6 output only:             4
        Number using O5 output only:             0
        Number using O5 and O6:                  0
      Number used as Shift Register:           152
        Number using O6 output only:            48
        Number using O5 output only:             1
        Number using O5 and O6:                103
    Number used exclusively as route-thrus:    146
      Number with same-slice register load:    124
      Number with same-slice carry load:        20
      Number with other load:                    2

Slice Logic Distribution:
  Number of occupied Slices:                 2,103 out of   6,822   30%
  Number of LUT Flip Flop pairs used:        6,156
    Number with an unused Flip Flop:         2,169 out of   6,156   35%
    Number with an unused LUT:                 966 out of   6,156   15%
    Number of fully used LUT-FF pairs:       3,021 out of   6,156   49%
    Number of unique control sets:             357
    Number of slice register sites lost
      to control set restrictions:           1,374 out of  54,576    2%

  A LUT Flip Flop pair for this architecture represents one LUT paired with
  one Flip Flop within a slice.  A control set is a unique combination of
  clock, reset, set, and enable signals for a registered element.
  The Slice Logic Distribution report is not meaningful if the design is
  over-mapped for a non-slice resource or if Placement fails.

IO Utilization:
  Number of bonded IOBs:                       127 out of     296   42%
    Number of LOCed IOBs:                      127 out of     127  100%
    IOB Flip Flops:                             64

Specific Feature Utilization:
  Number of RAMB16BWERs:                        34 out of     116   29%
  Number of RAMB8BWERs:                          1 out of     232    1%
  Number of BUFIO2/BUFIO2_2CLKs:                 1 out of      32    3%
    Number used as BUFIO2s:                      1
    Number used as BUFIO2_2CLKs:                 0
  Number of BUFIO2FB/BUFIO2FB_2CLKs:             0 out of      32    0%
  Number of BUFG/BUFGMUXs:                       8 out of      16   50%
    Number used as BUFGs:                        8
    Number used as BUFGMUX:                      0
  Number of DCM/DCM_CLKGENs:                     2 out of       8   25%
    Number used as DCMs:                         2
    Number used as DCM_CLKGENs:                  0
  Number of ILOGIC2/ISERDES2s:                  16 out of     376    4%
    Number used as ILOGIC2s:                    16
    Number used as ISERDES2s:                    0
  Number of IODELAY2/IODRP2/IODRP2_MCBs:        32 out of     376    8%
    Number used as IODELAY2s:                    8
    Number used as IODRP2s:                      2
    Number used as IODRP2_MCBs:                 22
  Number of OLOGIC2/OSERDES2s:                  86 out of     376   22%
    Number used as OLOGIC2s:                    40
    Number used as OSERDES2s:                   46
  Number of BSCANs:                              1 out of       4   25%
  Number of BUFHs:                               0 out of     256    0%
  Number of BUFPLLs:                             0 out of       8    0%
  Number of BUFPLL_MCBs:                         1 out of       4   25%
  Number of DSP48A1s:                            3 out of      58    5%
  Number of GTPA1_DUALs:                         0 out of       2    0%
  Number of ICAPs:                               0 out of       1    0%
  Number of MCBs:                                1 out of       2   50%
  Number of PCIE_A1s:                            0 out of       1    0%
  Number of PCILOGICSEs:                         0 out of       2    0%
  Number of PLL_ADVs:                            1 out of       4   25%
  Number of PMVs:                                0 out of       1    0%
  Number of STARTUPs:                            0 out of       1    0%
  Number of SUSPEND_SYNCs:                       0 out of       1    0%



(2011/08/04:追記)
CHARDISPC を追加するときのXPS Core Configダイアログで指定したC_NUM_REGは2だったが、system\pcores\chardispc_v1_00_a\data\chardispc_v2_1_0.mpd で指定されたC_NUM_REGの値は1だった。

PARAMETER C_NUM_REG = 1, DT = INTEGER


これでも、CHARDISPC の動作には問題はないようだ。C_NUM_REG = 2でも、C_NUM_REG = 1でも実際にインプリメントして試してみたが、同様に動作した。
  1. 2011年08月03日 04:42 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る2

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る1”の続き。

カスタムIPのHDLコードを接続する。

1.XPSのFileメニューからOpen...を選択して、pcores -> chardispc_v1_00_a -> hdl -> vhdlフォルダのchardispc.vhdを選択して開く。141行目に、DVI関連のポート宣言を追加する。(--USER ports added hereの下)
SP605_AXI_CDC_19_110731.png

2.更に、USER_LOGIC_I : entity chardispc_v1_00_a.user_logic のポート記述を追加する。
SP605_AXI_CDC_20_110731.png

3.chardispc.vhdをセーブした。

4.XPSのFileメニューからOpen...を選択して、pcores -> chardispc_v1_00_a -> hdl -> vhdlフォルダのuser_logic.vhdを選択して開く。ポート宣言を追加した。
SP605_AXI_CDC_22_110802.png

5.キャラクタ・ディスプレイ・コントローラ、CharDispCtrler_SP605.v のコンポーネント宣言を追加して、インスタンスした。
SP605_AXI_CDC_23_110802.png

6.CharDispCtrler_SP605.vの下のHDLファイル名を、pcores -> chardispc_v1_00_a -> data -> chardispc_v2_1_0.pao に追加した。下に、chardispc_v2_1_0.paoの内容を示す。(ame_feb4さん、教えて頂いてありがとうございました)

##############################################################################
## Filename: H:/HDL/FndtnISEWork/Spartan6/SP605_AXI_CharDispCtrler/system/pcores/chardispc_v1_00_a/data/chardispc_v2_1_0.pao
## Description: Peripheral Analysis Order
## Date: Sat Jul 30 05:47:37 2011 (by Create and Import Peripheral Wizard)
##############################################################################

lib proc_common_v3_00_a all
lib axi_lite_ipif_v1_01_a all
lib chardispc_v1_00_a user_logic vhdl
lib chardispc_v1_00_a chardispc vhdl
lib chardispc_v1_00_a char_gen_rom.v verilog
lib chardispc_v1_00_a CharDispCtrler.v verilog
lib chardispc_v1_00_a CharDispCtrler_SP605.v verilog
lib chardispc_v1_00_a dcm_inst.vhd vhdl
lib chardispc_v1_00_a disp_timing.v verilog
lib chardispc_v1_00_a frame_buffer.v verilog
lib chardispc_v1_00_a freqdiv.vhd vhdl
lib chardispc_v1_00_a One_Transaction_SCCB.vhd vhdl
lib chardispc_v1_00_a SCCB_Reg_Controller.vhd vhdl
lib chardispc_v1_00_a SCCB_reg_values_ROM.vhd vhdl


7.VHDLファイルはpcores -> chardispc_v1_00_a -> hdl -> vhdlフォルダに追加した。Verilogファイルはpcores -> chardispc_v1_00_a -> hdl -> verilogフォルダを作成して、そこに入れた。

(2011/08/04:追記)
MicroBlazeの動作クロックを100MHzに設定したので、AXI4LiteのIPへのクロックも100MHzと思っていたのだが、system.mhs ファイルを見てみると、

PORT S_AXI_ACLK = clk_50_0000MHzPLL0


と記述があって、50MHzクロックのようだった。clock_generator を見てみたが、50MHzで間違いなかった。
なお、MIG (AXI4) は100MHzクロックが供給されていた。
CHARDISPC のDCMの分周比を50MHzクロック用に変更した。

AXIバスのEDKでキャラクタ・ディスプレイ・コントローラのカスタムIPを作る3”に続く。
  1. 2011年08月02日 05:35 |
  2. EDK
  3. | トラックバック:0
  4. | コメント:0