FC2カウンター FPGAの部屋 2010年02月

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

FPGAの部屋

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

無償ツールで実践する「ハード・ソフト協調検証」をやってみる3(協調シミュレーション準備)

今度は、”無償ツールで実践する「ハード・ソフト協調検証」(6) ―― 協調シミュレーションを実行する”(以下の文章ではハード・ソフト協調検証」(6)と呼ぶことにする)をやってみることにする。
Avalon_BFM_DPI_C.zipをダウンロードし解凍すると、Avalon_BFM_DPI_C\Avalon_BFM_DPI_C\progフォルダがあった。これはprogフォルダを抜き出して、avalon_bfm_simフォルダにコピーすれば良いのか?ハード・ソフト協調検証」(6)では、”set_sim.doをset_dpi_sim.doにコピーします”と書いてあるが、avalon_bfm_simフォルダには、onchip_memory2_0.hexファイルしか存在しない。ここに色々なファイルが生成されていないのはおかしい。
前の過程を慎重に見直すと、ハード・ソフト協調検証(5)の図16でERRORが出ている。私のやったSOPC Builderでも同様にエラーが出ていた。
hard_soft_6_100228.png

このエラーはavalon_bfm_burst_0モジュールで、Always_Burst_Max_Burst:0なのにmaster Linewrap_Bursts: 1になっているためのようだ。と言うことは、ハード・ソフト協調検証(5)の図10の設定のどこかをいじる必要があるのかもしれない。
もう一度、Altera Avalon MM Master BFMのダイアログを出してみてみると、Burst AttributesにLinewrap bursts:という項目があるので、このチェックを外した。
hard_soft_7_100228.png

これでFinishボタンをクリックして、Generateしたところ、問題なくGenerateが成功した。
hard_soft_8_100228.png

avalon_bfm_simフォルダを見ると、set_sim.doはないが、setup_sim.doがあった。たぶんこれだろう?その他、ファイルも出来ていた。
hard_soft_9_100228.png

avalon_bfm_simフォルダに、avalon_bfm_sim.mpfも出来ていたので、Avalon_BFM_DPI_C.zipを解凍したAvalon_BFM_DPI_C\Avalon_BFM_DPI_Cフォルダの下のprogフォルダとwave.doをavalon_bfm_simフォルダにコピーすれば良いのだと思う?たぶん。。。
setup_dpi_sim.doをsetup_sim.doとして、avalon_bfm_simフォルダにコピーすれば良いかと思ったが、念のためにWinMergeで調べてみると、ディレクトリパスが絶対パスで書いてあった。その部分は変更しないようにし、それ以外の異なる部分をコピーした。
hard_soft_10_100228.png

これで、ハード・ソフト協調検証(5)の12.シミュレーションの準備まで終了した。
ここでは、Avalon BFMのシミュレーション環境として自動生成されたsetup_sim.doに対して、tb_prog.svをシミュレーションする記述を付加した。

13.SystemVerilogコードをコンパイルする
ModelSim AE6.5b を起動して、avalon_bfm_sim.mpfをロードした。
Transcriptペインでdo setup_sim.do と入力して、setup_sim.doを起動した。下にログを示す。

do setup_sim.do
# h:/altera/91/quartus//sopc_builder
# h:/altera/91/quartus//bin/perl
# Sopc_Builder Directory: h:/altera/91/quartus//sopc_builder
# @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
# @@
# @@ setup_sim.do
# @@
# @@ Defined aliases:
# @@
# @@ s -- Load all design (HDL) files.
# @@ re-vlog/re-vcom and re-vsim the design.
# @@
# @@ c -- Re-compile memory contents.
# @@ Builds C- and assembly-language programs
# @@ (and associated simulation data-files
# @@ such as UART simulation strings) for
# @@ refreshing memory contents.
# @@ Does NOT re-generate hardware (HDL) files
# @@ ONLY WORKS WITH LEGACY SDK (Not the Nios IDE)
# @@
# @@ w -- Sets-up waveforms for this design
# @@ Each SOPC-Builder component may have
# @@ signals 'marked' for display during
# @@ simulation. This command opens a wave-
# @@ window containing all such signals.
# @@
# @@ l -- Sets-up list waveforms for this design
# @@ Each SOPC-Builder component may have
# @@ signals 'marked' for listing during
# @@ simulation. This command opens a list-
# @@ window containing all such signals.
# @@
# @@ h -- print this message
# @@
# @@


Transcriptペインでsを入力してコンパイルした。コンパイルはうまく行ったがvsimでエラー発生。下にログを示す。

s
# Model Technology ModelSim ALTERA vlog 6.5b Compiler 2009.10 Oct 1 2009
# -- Compiling module burstcount_fifo_for_avalon_bfm_burst_0_upstream_module
# -- Compiling module rdv_fifo_for_mm_master_bfm_0_m0_to_avalon_bfm_burst_0_upstream_module
# -- Compiling module avalon_bfm_burst_0_upstream_arbitrator
# -- Compiling module avalon_bfm_burst_0_downstream_arbitrator
# -- Compiling module mm_master_bfm_0_m0_arbitrator
# -- Compiling module onchip_memory2_0_s1_arbitrator
# -- Compiling module avalon_bfm_reset_clk_0_domain_synch_module
# -- Compiling module avalon_bfm
# -- Compiling module lcell
# -- Compiling module ALTERA_MF_MEMORY_INITIALIZATION
# -- Compiling module ALTERA_MF_HINT_EVALUATION
# -- Compiling module ALTERA_DEVICE_FAMILIES
# -- Compiling module dffp
# -- Compiling module pll_iobuf
# -- Compiling module stx_m_cntr
# -- Compiling module stx_n_cntr
# -- Compiling module stx_scale_cntr
# -- Compiling module MF_pll_reg
# -- Compiling module MF_stratix_pll
# -- Compiling module arm_m_cntr
# -- Compiling module arm_n_cntr
# -- Compiling module arm_scale_cntr
# -- Compiling module MF_stratixii_pll
# -- Compiling module ttn_m_cntr
# -- Compiling module ttn_n_cntr
# -- Compiling module ttn_scale_cntr
# -- Compiling module MF_stratixiii_pll
# -- Compiling module cda_m_cntr
# -- Compiling module cda_n_cntr
# -- Compiling module cda_scale_cntr
# -- Compiling module MF_cycloneiii_pll
# -- Compiling module MF_cycloneiiigl_m_cntr
# -- Compiling module MF_cycloneiiigl_n_cntr
# -- Compiling module MF_cycloneiiigl_scale_cntr
# -- Compiling module cycloneiiigl_post_divider
# -- Compiling module MF_cycloneiiigl_pll
# -- Compiling module altpll
# -- Compiling module altlvds_rx
# -- Compiling module stratix_lvds_rx
# -- Compiling module stratixgx_dpa_lvds_rx
# -- Compiling module stratixii_lvds_rx
# -- Compiling module flexible_lvds_rx
# -- Compiling module stratixiii_lvds_rx
# -- Compiling module stratixiii_lvds_rx_channel
# -- Compiling module stratixiii_lvds_rx_dpa
# -- Compiling module altlvds_tx
# -- Compiling module stratix_tx_outclk
# -- Compiling module stratixii_tx_outclk
# -- Compiling module flexible_lvds_tx
# -- Compiling module dcfifo_dffpipe
# -- Compiling module dcfifo_fefifo
# -- Compiling module dcfifo_async
# -- Compiling module dcfifo_sync
# -- Compiling module dcfifo_low_latency
# -- Compiling module dcfifo_mixed_widths
# -- Compiling module dcfifo
# -- Compiling module altaccumulate
# -- Compiling module altmult_accum
# -- Compiling module altmult_add
# -- Compiling module altfp_mult
# -- Compiling module altsqrt
# -- Compiling module altclklock
# -- Compiling module altddio_in
# -- Compiling module altddio_out
# -- Compiling module altddio_bidir
# -- Compiling module altdpram
# -- Compiling module altsyncram
# -- Compiling module alt3pram
# -- Compiling module parallel_add
# -- Compiling module scfifo
# -- Compiling module altshift_taps
# -- Compiling module a_graycounter
# -- Compiling module altsquare
# -- Compiling module altera_std_synchronizer
# -- Compiling module altera_std_synchronizer_bundle
# -- Compiling module alt_cal
# -- Compiling module alt_aeq_s4
# -- Compiling module alt_eyemon
# -- Compiling module alt_dfe
# -- Compiling module signal_gen
# -- Compiling module jtag_tap_controller
# -- Compiling module dummy_hub
# -- Compiling module sld_virtual_jtag
# -- Compiling module sld_signaltap
# -- Compiling module altstratixii_oct
# -- Compiling module altparallel_flash_loader
# -- Compiling module altserial_flash_loader
# -- Compiling module altsource_probe
# -- Compiling module LPM_MEMORY_INITIALIZATION
# -- Compiling module LPM_HINT_EVALUATION
# -- Compiling module LPM_DEVICE_FAMILIES
# -- Compiling module lpm_constant
# -- Compiling module lpm_inv
# -- Compiling module lpm_and
# -- Compiling module lpm_or
# -- Compiling module lpm_xor
# -- Compiling module lpm_bustri
# -- Compiling module lpm_mux
# -- Compiling module lpm_decode
# -- Compiling module lpm_clshift
# -- Compiling module lpm_add_sub
# -- Compiling module lpm_compare
# -- Compiling module lpm_mult
# -- Compiling module lpm_divide
# -- Compiling module lpm_abs
# -- Compiling module lpm_counter
# -- Compiling module lpm_latch
# -- Compiling module lpm_ff
# -- Compiling module lpm_shiftreg
# -- Compiling module lpm_ram_dq
# -- Compiling module lpm_ram_dp
# -- Compiling module lpm_ram_io
# -- Compiling module lpm_rom
# -- Compiling module lpm_fifo
# -- Compiling module lpm_fifo_dc_dffpipe
# -- Compiling module lpm_fifo_dc_fefifo
# -- Compiling module lpm_fifo_dc_async
# -- Compiling module lpm_fifo_dc
# -- Compiling module lpm_inpad
# -- Compiling module lpm_outpad
# -- Compiling module lpm_bipad
# -- Compiling module oper_add
# -- Compiling module oper_addsub
# -- Compiling module mux21
# -- Compiling module io_buf_tri
# -- Compiling module io_buf_opdrn
# -- Compiling module oper_mult
# -- Compiling module tri_bus
# -- Compiling module oper_div
# -- Compiling module oper_mod
# -- Compiling module oper_left_shift
# -- Compiling module oper_right_shift
# -- Compiling module oper_rotate_left
# -- Compiling module oper_rotate_right
# -- Compiling module oper_less_than
# -- Compiling module oper_mux
# -- Compiling module oper_selector
# -- Compiling module oper_decoder
# -- Compiling module oper_bus_mux
# -- Compiling module oper_latch
# -- Compiling package verbosity_pkg
# -- Compiling package avalon_mm_pkg
# -- Importing package verbosity_pkg
# -- Compiling module altera_avalon_mm_master_bfm
# -- Importing package verbosity_pkg
# -- Importing package avalon_mm_pkg
# -- Compiling module mm_master_bfm_0
# -- Compiling module avalon_bfm_burst_0
# -- Compiling module onchip_memory2_0
# -- Compiling module test_bench
# -- Compiling module tb_prog
# -- Importing package avalon_mm_pkg
# -- Importing package verbosity_pkg
#
# Top level modules:
# lcell
# altpll
# altlvds_rx
# altlvds_tx
# dcfifo
# altaccumulate
# altmult_accum
# altmult_add
# altfp_mult
# altsqrt
# altclklock
# altddio_bidir
# altdpram
# alt3pram
# parallel_add
# scfifo
# altshift_taps
# a_graycounter
# altsquare
# altera_std_synchronizer_bundle
# alt_cal
# alt_aeq_s4
# alt_eyemon
# alt_dfe
# sld_virtual_jtag
# sld_signaltap
# altstratixii_oct
# altparallel_flash_loader
# altserial_flash_loader
# altsource_probe
# lpm_constant
# lpm_inv
# lpm_and
# lpm_or
# lpm_xor
# lpm_bustri
# lpm_compare
# lpm_abs
# lpm_counter
# lpm_latch
# lpm_ff
# lpm_shiftreg
# lpm_ram_dq
# lpm_ram_dp
# lpm_ram_io
# lpm_rom
# lpm_fifo
# lpm_fifo_dc
# lpm_inpad
# lpm_outpad
# lpm_bipad
# oper_add
# oper_addsub
# mux21
# io_buf_tri
# io_buf_opdrn
# oper_mult
# tri_bus
# oper_div
# oper_mod
# oper_left_shift
# oper_right_shift
# oper_rotate_left
# oper_rotate_right
# oper_less_than
# oper_mux
# oper_selector
# oper_decoder
# oper_bus_mux
# oper_latch
# test_bench
# tb_prog
# vsim +nowarnTFMPC -L lpm_ver -L sgate_ver -L altera_mf_ver -L altgxb_ver -L stratixiigx_hssi_ver -L stratixgx_ver -L stratixgx_gxb_ver -L stratixiigx -L altera_ver -L stratixiii_ver -L stratixii_ver -L cycloneii_ver -L cycloneiii_ver -L stratixiv_hssi_ver -L arriaii_ver -L arriaii_pcie_hip_ver -L arriaii_hssi_ver -L stratixiv_pcie_hip_ver -L cycloneiv_pcie_hip_ver -L cycloneiv_hssi_ver -L hardcopyiv_pcie_hip_ver -L hardcopyiv_hssi_ver -t ps -sv_root prog -sv_lib dpi_main test_bench tb_prog
# (vsim-3763) SystemVerilog DPI cannot access file 'prog\dpi_main.dll'
# No such file or directory. (errno = ENOENT)
# Use the -help option for complete vsim usage.
# Error loading design


ModelSim AE6.5b を終了した。
MSYSを起動した。avalon_bfm_simフォルダに移動して、

vsim -c -dpiexportobj prog/exportobj.obj test_bench tb_prog


コマンドを入れると、成功したようだ。
hard_soft_11_100228.png

後で気がついたのだが、上の図で、prog/exportobj.objのはずがprog/wxportobj.objと入力してしまったようだ。wxportobj.objをexportobj.objにリネームした。
ここでは、setup_sim.doスクリプトをModelSim上で実行してから、アライアスされたsコマンドでコンパイルし、コマンドラインからのvsimでC言語からリンクされるファイルexportobj.objを生成した。

14.C言語プログラムをコンパイルする
MSYSで、progフォルダに移動して、

gcc -c dpi_main.c


を実行した。その結果、dpi_main.oが生成された。
次に、

gcc -shared -o dpi_main.dll dpi_main.o exportobj.obj /c/altera/91/modelsim_ase/win32aloem/mtipli.dll


を実行すると、dpi_main.dllが生成された。
長くなってしまうので、今日はここまでにする。
ここでは、先程vsimで生成した exportobj.obj と dpi_main.c をコンパイルしたオブジェクトファイルをリンクして、dpi_main.dll を生成した。
  1. 2010年02月28日 15:52 |
  2. SystemVerilog
  3. | トラックバック:0
  4. | コメント:0

無償ツールで実践する「ハード・ソフト協調検証」をやってみる2(SystemVerilogコードとCコード)

無償ツールで実践する「ハード・ソフト協調検証」(4) ―― SystemVerilog側のDPI-Cの記述を作成する”からSystemVerilogのコード(tb_prog.sv)をダウンロードして確認した。今のところ、Verilog2001のコードとそんなに違いがないような。。。
'h3とビット幅を省略しても書けたのか?早速、VeritakのVerilogチュートリアルのデータ型を確認した。それによると、あまり推奨されないけど、’h 837FFのように書けるとのことだった。tb_prog.svは見ただけだが、大体納得した。つまり、tb_prog.svは、BFMでインスタンスを定義されたAvalon Bus Fuction Model(BFM)に対して、メソッドをコールして、Avalonバスに対して、Write, Readアクセスを発生させる。また、initial文でC言語で書かれたテストベンチをコールする。

次に、”無償ツールで実践する「ハード・ソフト協調検証」(5) ―― テスト・プログラムの作成とBFMのコードの生成”でC言語のコード、dpi_func.hとdpi_func.c をダウンロードした。今度はすぐに分かった。SystemVerilog側でbfm_writeやbfm_read、bfm_nopなどのtaskをC側から呼び出してテストするようだ。最初にCのルーチンdpi_main()は、SystemVerilog側から

import "DPI-C" context task dpi_main();


で宣言しておいて、initial文で呼び出している。
当然、Cから呼ばれるSystemVerilogのtask文も

export "DPI-C" task bfm_write32;
export "DPI-C" task bfm_read32;
export "DPI-C" task bfm_write16;
export "DPI-C" task bfm_read16;
export "DPI-C" task bfm_write8;
export "DPI-C" task bfm_read8;
export "DPI-C" task bfm_nop;


で外部参照宣言されている。
と言うことはCで自由にテストベンチを書けると言うことなんだろう?

次にQuartus2 9.1(久しぶりです)を立ち上げて、avalon_bfmというプロジェクトを作った。無償ツールで実践する「ハード・ソフト協調検証」(5) ―― テスト・プログラムの作成とBFMのコードの生成”で言うと図6と図7の間あたり。
hard_soft_1_100227.png

プロジェクトができたら、SOPC Builderを立ち上げる。SOPC BuilderはToolsメニューからも起動することができる。図8が出てくる前にCreate New Systemダイアログが出る。System Name が入っていなかったので、avalon_bfmを入力した。
hard_soft_2_100227.png

Create New SystemダイアログのOKボタンをクリックすると、SOPC Builderが開いた。図8まで来た。
次に、図9。SOPC Builderの左のペインからLibrary のAvalon Verification Suite を展開して、Altera Avalon MM Master BFMをクリックし、Addボタンをクリックすると、Altera Avalon MM Master BFMのダイアログ(図10)が現れた。デフォルト値で良いようなので、そのままFinish。mm_master_bfm_0ができた。
hard_soft_3_100227.png

図11、図12で、On-Chip Memory のRAMを追加した。そして、onchip_memory2_0が追加された。追加した2つのIPコアを接続した。
hard_soft_4_100227.png

これで、GenerateボタンをクリックしてVerilogコードを生成した。Simulation : Create project simulator files. をチェックした。
hard_soft_5_100227.png

第5回まで終わった。
ここでは、SOPC BuilderでAvalonバスのバス・ファンクションモデルを生成して、Avalonバスに接続されるOn-Chip Memory のRAMモジュール(今回このモジュールがテスト対象)生成して、それぞれを接続した。
  1. 2010年02月27日 21:04 |
  2. SystemVerilog
  3. | トラックバック:0
  4. | コメント:0

無償ツールで実践する「ハード・ソフト協調検証」をやってみる1(MinGWとMSYSのインストール)

Verification Engineerの戯言さんの”SystemVerilogの世界へようこそ”のWebサイトの”無償ツールで実践する「ハード・ソフト協調検証」(全8回)”をやってみることにした。
まずは、”無償ツールで実践する「ハード・ソフト協調検証」(8,最終回) ―― シミュレータやコンパイラの入手方法”から、ModelSim AEはすでに入っているので、MINGW32/MSYSのインストールをすることにする。”MINGW32/MSYSについて”のページを見ながらインストールする。まずは、MinGW-5.1.6.exeをダウンロードして、インストールしようと思ったが、”無償ツールで実践する「ハード・ソフト協調検証」(8,最終回) ―― シミュレータやコンパイラの入手方法”にMSYSからインストールするように書いてあったので、MSYSからインストールすることにした。
MINGW32/MSYSについて”のページのMSYS-1.0.11.exeのリンクはリンク切れしていた。ダンロードするページがどこにあるかを探すため、とりあえずMinGWのメインページに行った。ここから探すと、MSYSのページがあった。ところでMSYSって何だろう?と思って調べてみたら、ウィッキペディアのMSYSのページがあった。それによると、CygwinみたいにUNIXのコマンドが使えるけど、プログラム開発に限定的だそうだ。すでにCygwingがパソコンにインストールしてあるので、そっちでいいかな?とは思ったが、トレースできなくなる可能性もあるのでMSYSもインストールすることにした。MSYS-1.0.11.exeをダウンロードしてインストールする。
最初にMSYSをインストールしない方が良いようです。一旦インストールしたMSYSを削除して、”MinGW + MSYSのインストール方法”を参考にMinGWからインストールすることにしました。このサイトではg++をインストールしていますが、どうなんでしょうか?g++はC++と同等ですよね?一応インストールしておこうかな?
このMinGWもCygwinと一緒で必要パッケージをダウンロードして、インストールするんですね。サイトの画面通りにMinGWのインストールは終了しました。
次にMSYSのインストールです。あれ、Select Componentsダイアログがなかったような気がします。あと、14.でMinGWのパスを入力する際に、ドライブ名を大文字で入れないとダメみたいです。私は失敗してやり直ししました。
MSYSのインストールが終了後、システム環境変数のpathにMinGW\binへのパスを追加しました。
システム環境変数C_INCLUDE_PATHにMinGW\includeへのパスを追加。
システム環境変数CPLUS_INCLUDE_PATHにMinGW\includeへのパスを追加。
システム環境変数LIBRARY_PATHにMinGW\libへのパスを追加。
システム環境変数MINGW_DIRにMinGWへのパスを追加。

次にvimをインストールする。vim-7.2-1をここからダウンロードする。ダウンロードしたら、ファイル名がvim-7.2-1-msys-1.0.11-bin.tar.lzma.tarだった、lzmaの圧縮を解く前にtarを展開する必要がある。

tar xvf vim-7.2-1-msys-1.0.11-bin.tar.lzma.tar


を実行したら、フォーマットがあわないと言われてエラー。もしかしたらと、後ろの.tarを除いて、

lzma -d vim-7.2-1-msys-1.0.11-bin.tar.lzma


を実行。そうすると、vim-7.2-1-msys-1.0.11-bin.tarに展開された。これを、下のコマンドで展開した。

tar xvf vim-7.2-1-msys-1.0.11-bin.tar


そうするとbinとshareフォルダができた。これをmsys/1.0の下にコピーした。これでMSYSのコマンドプロンプトからvimと打つとvimが起動した。
vim_100225.png

これでvimまで起動した。

次は、”MinGW + MSYSのインストール方法”に書いてあった日本語を扱えるようにする。
Index of /resources/files/libiconvからlibiconv-1.11-1-i386-mingw32.tar.gzをダウンロードする。

tar zxvf libiconv-1.11-1-i386-mingw32.tar.gz


で展開する。usrフォルダが出来る。その中のusr/localの下のすべてのフォルダをコピーしようとしたら、あれ?私のインストールしたMSYSには、msys\1.0\homeの下のユーザー名がない。。。おかしい?もう一度MSYSをアンインストールして、もう一度インストールすることにした。
やはり、msys\1.0\homeの下のユーザー名フォルダは出来ない。。。自分でユーザー名フォルダを作ることにした。その上で、libiconv-1.11-1-i386-mingw32を解凍したusr/localの下のすべてのフォルダをコピーした。
さて、このままでは自分のホームとして認識されないので、環境変数HOMEとそれに、HISTFILEを変更する必要がありそうだ。
ネットで検索してみたところ、”NTEmacs + MinGW + MSYSでWindows上にC言語開発環境を構築してみる - その4”に”MSYSのデフォルトのホームディレクトリはC:\msys\1.0\homeなのですが、環境変数HOMEが設定されているとHOMEで指定されているパスをホームディレクトリを認識します。”と書いてあった。自分の環境変数を見てみたら、ユーザー環境変数にHOMEが設定されていた。ああこれだったのか。HOME環境変数を削除したところ、MSYSのホームがhome/ユーザー名になった。
これでインストールは終了かな?良かった。。。
  1. 2010年02月25日 06:30 |
  2. SystemVerilog
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路の休止等々

これまで、キャラクタ描画テスト回路を作ってきた。シミュレーションでは、だいぶイケているようなのだが実機で動作しない。今日もバグが有ったので、潰したのだが、ディスプレイ画面は単色で塗りつぶされてしまう。ChipScope PROかなふたふさんのMITOU JTAGあたりが使えれば良いのだが、そのもない。とりあえずISE12.1が出たら、お試しで1ヶ月ChipScopeが使えると思うので、それまで保留にしようと思う。やはり、DDR2 SDRAMコントローラがおかしいのかな?DDR2 SDRAMコントローラは一連の流れで、動作を確認しChipScopeで見て、読み書きしているのを確認したハズのだが???それでも配線を同様にしてもReadデータが受からない自体が発生したので、まだ見落としがあるのかもしれない。
だいぶ、ブログを書きながら趣味でやるには辛くなってきた。やはりChipScopeがないと手詰まりだ。

仕事では今のところ、画像処理がメインで、Excelの値のテーブルからVHDLファイルを自動生成するRubyソフトウェアを開発して、自動生成したVHDLの演算回路に周辺を付けている。もう1つのプロジェクトも画像処理関係で、確か5月位(6月かもしれません?たしか場所はパシフィコ横浜だったと思うので)に画像関係?の展示会に出すそうだ。私も説明要員として行くので、その時はよろしくお願いします。展示会の名前を忘れてしまったが、もしかしてESEC?でも名前がないし?違うのかな?後で何に出すのかを聞いておくことにする。

次は、Xilinxを離れて、AlteraでVerification Engineerの戯言さんの無償ツールで実践する「ハード・ソフト協調検証」(全8回)を自分でやってみたいと思っています。かなり詳しく書かれているので、これをやってみた。ここがうまくいかなかった。とかの散発的なレポートになるかもしれませんが。。。
最近のQuartus2やAltera用ModlSimがライセンスいらなくなったことや、Nios2/eプロセッサコアの無償化、ChipScopeと同様のSignal Tap2が無償のことなど(どんな回路を作っているのかというレポートを承認する必要がある)Alteraの方が家でやるにはやりやすい環境ですね。(当然、対応FPGAの制限はありますが)それに、SOPC Builderも使いやすそうですし。現在のキャラクタ描画テスト回路をSDRAM対応にして、DE0ボードに載せてみても良いかもしれません。そうすればSignal Tap2でデバックし放題ですものね。。。魅力的です。
仕事では、Xilinxなので、ChipScopeも機能を限定的でもフリーで使えるようになればうれしいのですが。。。家でブログを書きながらいろいろ試しているのは、仕事をスムーズに進められるようにするための勉強の意味もあるので、Xilinxからは、なかなか離れられません。しかし、Alteraの環境が良いので浮気したいと思うようになってきました。
  1. 2010年02月24日 05:41 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

真壁のひなまつり

昨日は真壁のひなまつりに行ってきました。真壁のひなまつりとは、古い真壁の家並み各家々のひな人形を公開して、見せてくれるお祭りです。江戸時代のひな人形から、現代のひな人形まで、色々なひな人形が各家々に飾ってあります。それを観光客が見て歩くというものです。昨日は日曜日と言うことがあって大変な人だかりでした。いろいろな地元の物産を売っていて、大変な賑わいです。大いに地域振興になっていると感じました。
さて、真壁は家から17Kmくらいで割と近いので、車で30分と言うところです。マップをあらかじめダウンロードして、駐車場を目指して行きました。
朝、10時30分頃だったので駐車場はまだすいていました。他にも駐車場があったので、かなり止められそうです。
町を散策し始めると、かなりの人が歩いています。さて、人形を飾っている家には番号が書いてあります。それを目印にマップを見るようです。最初の家の人形はだいぶ古そうです。ひな人形としては変わっています。(私が見ると)
hinaningyou_1_100221.jpg

家の中に飾ってあるようなひな人形や、可愛らしいひな人形もありました。
hinaningyou_2_100221.jpg
hinaningyou_3_100221.jpg

現在は使われなくなった古い趣きのある郵便局にも大きなひな人形が飾ってありました。なかは絵や写真も飾ってあって、展示場として使っているようです。
hinaningyou_4_100221.jpg

かなりの人が来ていました。下の写真は午前中ですが、午後にはもっと人が増えました。土日はゆっくり見られないようです。
hinaningyou_5_100221.jpg

これが江戸時代、明治、大正、昭和と並んでいるひな人形、見事でした。
hinaningyou_6_100221.jpg

その隣では、餃子まんが売っていました。美味しそう。思わず買って食べてしまいましたが、美味しかったです。餃子と違ってにんにくはあまり効いていないです。もう少し餃子らしいのが良いかも?
hinaningyou_7_100221.jpg

懐かしい牛乳受けを見ました。こんな牛乳受けがどこの家にもあって、毎朝、牛乳が届いていました。懐かし~い。思わず写真にとってしまいました。(年がバレますね?)
hinaningyou_8_100221.jpg

真壁高校の生徒さんたちも、自分たちで作った野菜とかいちご、お弁当を販売していました。その他に、特産の石にほった図柄に、絵の具で絵をつけるイベントもやっていました。500円でした。うちの娘も挑戦しました。帰ってから、木で枠を作って玄関に飾りました。(石の加工は、NC旋盤か何かで加工するんでしょうか?)
hinaningyou_9_100221.jpg

私も、磨いた御影石の板を300円で売っていたので、買ってきました。これを木のテーブルか?鍋敷きに埋め込んで使いたいと思います。

お昼は結局、現地で買った焼き芋と餃子まんでお腹いっぱいになっちゃいましたが、手打ちそばとかも実演して、食べさせていました。これ食べたかったですね。お腹いっぱいで残念だったです。食べた人は、美味しかったね~と言っていました。今度行ったらぜひ食べたい。。。

楽しめました。キャラクタ描画テスト回路のインプリメントの疲れを癒してくれましたね。。。
  1. 2010年02月22日 05:41 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

キャラクタ描画テスト回路の実機デバック4(DCMの配置)

前回、BUFG入力までの配線が長くなりすぎていたのが原因だったので、DCMの配置を見直すことにした。もともとDCMは1つも配置を固定してない。全部ツール任せになっていた。
DCMは3つ使っていて、水晶発振器の50MHzをDDR2 SDRAMの動作周波数150MHzに変換するDCM(DCM1とする)、水晶発振器の50MHzをVGAコントローラの動作周波数65MHzに変換するDCM(DCM2とする)、DCM1の150MHzを元にDDR2 SDRAMコントローラに必要な反転クロック、90度位相がずれたクロックを生成するDCM(DCM3とする)だ。
DCM1は2つのBUFG、DCM2は2つのBUFG、DCM3は3つのBUFGを使用する。このSpartan3A700には、24個のBUFGMUX(BUFGMUXはBUFGと市ても使える)があって、FPGAチップの上下の真ん中に4個ずつ、左右の真ん中に8個ずつ配置されている。水晶発振器のクロック入力はFPGAチップの上側の真ん中にあるので、最初のDCMはその近くが良い。下図のようにDCM1とDCM3が上側に配置されていて、DCM2が下側に配置されている。BUFGはDCMの真ん中に配置されている。色がついていないBUFGMUX、DCMは使用されていないもの。DCM1とDCM3で合計5個BUFGを使用するので、DCM1用のBUFGが下に追いやられてしまったようだ。
Bitmap_VGAC_debug_11_100221.png

解決策としては、豊富なBUFGMUXを持つ左側の真ん中にDCM3を持っていこうと思う。DCM3の配置を下の制約で示す位置に固定した。

INST "ddr2_sdram_cont_i/dcm_module_inst/DCM_INST1/DCM_SP" LOC = DCM_X0Y2;


インプリメントの結果、DCM1、DCM2が上側真ん中、DCM3が左側の真ん中に配置されて、DDR2 SDRAMのデータバス出力のタイミングエラーはなくなった。
これで、実機にダウンロードしてやってみたところ、VGA画面も出なくなってしまった?

この後、色々な試行錯誤を繰り返した。悶々とした時間が過ぎた。(途中で桜川市の真壁にひな人形まつりを見に行ってリフレッシュ)

結局DCMは配置によって、クロックパスが極端に遅くなることがあって、(これはすぐには気がつかないので、非常にわかりにくい。注意する必要がある)結局、DCM1は上側の真ん中、DCM2,DCM3は並んで、左側の真ん中に配置した。下に配置制約を示す。

INST "ddr2_sdram_cont_i/dcm_module_inst/DCM_INST1/DCM_SP" LOC = DCM_X0Y1;
INST "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm/DCM_SP" LOC = DCM_X0Y2;
INST "dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm/DCM_SP" LOC = "DCM_X2Y3";


さて、ddr2_dqとddr2_dqsにIBUF_DELAY_VALUE = 1を入れると、データが安定することが分かった。となるとRead関係で残るはsd_loop_inのみ。sd_loop_inにもIBUF_DELAY_VALUE = 1を入れると、データが不安定になった。そういえば、前回、sd_loop_inは配線を固定してない。
sd_loop_inもDDR2 SDRAMバーストテスト回路から配線制約を吐き出させて、キャラクタ描画テスト回路の制約ファイルに追加した。下が制約。

NET "sd_loop_in_IBUF"
ROUTE="{3;1;3s700afg484;df4ab136!-1;-70632;33392;S!0;-159;0!1;1612;-912!"
"1;1596;1056!1;1680;-1720!1;-1464;-3608!1;-1618;10040!1;-225;1797!1;-1632;"
"-10456!2;-3069;-3647!3;450;5392!3;4355;1359!4;4;-12032!4;4255;-597!5;"
"3927;-4329!5;0;-7000!6;-474;9200!6;178;6576!6;184;13320!7;-1185;4651!7;"
"-1867;-629!8;4111;-10997!8;192;-13688!9;0;-6876!9;3952;222!10;3905;-657!"
"11;2808;3082!11;2917;-5975!11;1152;657;L!11;1152;313;L!12;2123;3408;L!13;"
"-511;-4883!13;1168;-1715;L!13;1168;-1371;L!14;13605;-139!14;-447;-2703!"
"15;24;-6784!16;1099;79!17;-17;-7547!17;-652;-752!18;-658;-744!19;3905;"
"-657!20;1099;-97!21;2976;-3486!22;3935;-4073!22;-652;-752!23;3952;98!24;"
"1152;313;L!24;1152;657;L!25;1152;313;L!25;1152;657;L!26;-2848;-1044!27;"
"-2957;1261!31;-2953;1265!34;-8965;428;L!34;-8965;772;L!35;3935;-4073!36;"
"3935;-4073!37;6944;-24!38;3952;98!39;1099;79!40;1099;79!41;1152;313;L!41;"
"1152;657;L!42;6912;0!43;-2968;104!44;12173;-119!45;1099;79!46;1152;657;L!"
"46;1152;313;L!51;1352;-701;L!51;-2104;-1045;L!52;1352;-701;L!53;1176;"
"-1377;L!56;1152;657;L!56;1152;313;L!57;1152;657;L!57;1152;313;L!58;-2304;"
"313;L!58;1152;313;L!58;1152;657;L!58;-2304;657;L!59;1152;657;L!59;1152;"
"313;L!60;6944;-24!61;6944;-24!64;-2112;-1039;L!65;1160;651;L!65;1160;307;"
"L!66;-7565;776;L!66;-7565;432;L!67;15333;-139!84;1152;657;L!84;1152;313;L"
"!85;-2304;313;L!85;-2304;657;L!91;-7237;772;L!91;-7237;428;L!}";


これを追加して、ddr2_dqとddr2_dqsのIBUF_DELAY_VALUE = 1をとってみたが、やはり安定しない。
sd_loop_inの配線を固定した状態でも、ddr2_dqとddr2_dqsのIBUF_DELAY_VALUE = 1を制約に加えれば安定する。
DDR2 SDRAMバーストテスト回路とキャラクタ描画テスト回路のsd_loop_inの配線の遅延値は配線を固定したにも関わらず、1.439nsec と1.412nsec と異なっている。この僅かな遅れが致命的なのか?
とりあえず、一部、最初に少しがまだ動いていて、おかしいようだが、これは他の原因かもしれないので、とりあえず、現在は動作を禁止しているキャラクタ生成コントローラを動作させてみようと思う。
UCFに追加した制約を以下に示す。

// 02/20 @ 12:48:23
NET "ddr2_sdram_cont_i/read_write_io_inst/ddr2_cont_iob_inst/dqs_clk_node<0>"
ROUTE="{3;1;3s700afg484;c20d0b8b!-1;-70632;12888;S!0;-159;0!1;-161;-887!"
"2;-1291;-2737!3;-29;-8091!4;259;-695!5;-1703;-139!6;108;53;L!}";
// 02/20 @ 12:51:22
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<0>"
ROUTE="{3;1;3s700afg484;a5bd1784!-1;-70632;26072;S!0;-159;0!1;2447;-605!"
"2;4489;301!2;4489;645!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<1>"
ROUTE="{3;1;3s700afg484;751a0e0!-1;-70632;19640;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<2>"
ROUTE="{3;1;3s700afg484;89ffb99b!-1;-70632;6136;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<3>"
ROUTE="{3;1;3s700afg484;61a7f9cb!-1;-70632;9192;S!0;-159;0!1;2447;-605!2;"
"4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<4>"
ROUTE="{3;1;3s700afg484;5a9ec78e!-1;-70632;9512;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<5>"
ROUTE="{3;1;3s700afg484;c3906147!-1;-70632;5816;S!0;-159;0!1;2447;-605!2;"
"4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<6>"
ROUTE="{3;1;3s700afg484;3cdde0e5!-1;-70632;19320;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<7>"
ROUTE="{3;1;3s700afg484;48045bde!-1;-70632;26392;S!0;-159;0!1;1696;1968!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<8>"
ROUTE="{3;1;3s700afg484;8152c779!-1;-70632;40144;S!0;-159;0!1;1696;1720!"
"2;1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<9>"
ROUTE="{3;1;3s700afg484;bfa7b4d9!-1;-70632;53328;S!0;-159;0!1;1696;2040!"
"2;1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<10>"
ROUTE="{3;1;3s700afg484;ace04032!-1;-70632;36448;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<11>"
ROUTE="{3;1;3s700afg484;fc333603!-1;-70632;49952;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<12>"
ROUTE="{3;1;3s700afg484;4ce19306!-1;-70632;50272;S!0;-159;0!1;1696;1720!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<13>"
ROUTE="{3;1;3s700afg484;7f7f4c8c!-1;-70632;39824;S!0;-159;0!1;2447;-605!"
"2;4489;301!2;4489;645!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<14>"
ROUTE="{3;1;3s700afg484;10d3a509!-1;-70632;36768;S!0;-159;0!1;1696;1720!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<15>"
ROUTE="{3;1;3s700afg484;473a4c3d!-1;-70632;53648;S!0;-159;0!1;2479;-949!"
"2;4457;661!3;0;8!3;0;-336!4;167;0;L!5;167;0;L!}";

INST "ddr2_sdram_cont_i/dcm_module_inst/DCM_INST1/DCM_SP" LOC = DCM_X0Y1;
INST "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm/DCM_SP" LOC = DCM_X0Y2;
INST "dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm/DCM_SP" LOC = "DCM_X2Y3";

NET "ddr2_dq[0]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[1]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[2]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[3]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[4]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[5]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[6]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[7]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[8]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[9]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[10]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[11]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[12]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[13]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[14]" IBUF_DELAY_VALUE = 1;
NET "ddr2_dq[15]" IBUF_DELAY_VALUE = 1;
#
NET "ddr2_dqs[0]" IBUF_DELAY_VALUE = 1;
# NET "sd_loop_in" IBUF_DELAY_VALUE = 1;


# sd_loop_in // 02/21 @ 20:52:31
NET "sd_loop_in_IBUF"
ROUTE="{3;1;3s700afg484;df4ab136!-1;-70632;33392;S!0;-159;0!1;1612;-912!"
"1;1596;1056!1;1680;-1720!1;-1464;-3608!1;-1618;10040!1;-225;1797!1;-1632;"
"-10456!2;-3069;-3647!3;450;5392!3;4355;1359!4;4;-12032!4;4255;-597!5;"
"3927;-4329!5;0;-7000!6;-474;9200!6;178;6576!6;184;13320!7;-1185;4651!7;"
"-1867;-629!8;4111;-10997!8;192;-13688!9;0;-6876!9;3952;222!10;3905;-657!"
"11;2808;3082!11;2917;-5975!11;1152;657;L!11;1152;313;L!12;2123;3408;L!13;"
"-511;-4883!13;1168;-1715;L!13;1168;-1371;L!14;13605;-139!14;-447;-2703!"
"15;24;-6784!16;1099;79!17;-17;-7547!17;-652;-752!18;-658;-744!19;3905;"
"-657!20;1099;-97!21;2976;-3486!22;3935;-4073!22;-652;-752!23;3952;98!24;"
"1152;313;L!24;1152;657;L!25;1152;313;L!25;1152;657;L!26;-2848;-1044!27;"
"-2957;1261!31;-2953;1265!34;-8965;428;L!34;-8965;772;L!35;3935;-4073!36;"
"3935;-4073!37;6944;-24!38;3952;98!39;1099;79!40;1099;79!41;1152;313;L!41;"
"1152;657;L!42;6912;0!43;-2968;104!44;12173;-119!45;1099;79!46;1152;657;L!"
"46;1152;313;L!51;1352;-701;L!51;-2104;-1045;L!52;1352;-701;L!53;1176;"
"-1377;L!56;1152;657;L!56;1152;313;L!57;1152;657;L!57;1152;313;L!58;-2304;"
"313;L!58;1152;313;L!58;1152;657;L!58;-2304;657;L!59;1152;657;L!59;1152;"
"313;L!60;6944;-24!61;6944;-24!64;-2112;-1039;L!65;1160;651;L!65;1160;307;"
"L!66;-7565;776;L!66;-7565;432;L!67;15333;-139!84;1152;657;L!84;1152;313;L"
"!85;-2304;313;L!85;-2304;657;L!91;-7237;772;L!91;-7237;428;L!}";


しかし、だいぶ苦労してしまった。昨日一日は、ひな人形まつりを見に行った以外はインプリメントし続けた。MIGのDDR2 SDRAMのIPもUCFがガチガチになっているんだろう?もしくはLUTのプリミティブで直接書いてあって、配線も固定されているとか?もしくはエリア制約をうまくかけてあるのかな?機会があればMIGでやってみたい。
  1. 2010年02月22日 04:57 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路の実機デバック3(配線の固定)

前回、配線がとんでもないことになっていたので、以前のDDR2 SDRAMバーストテスト回路の配線をUCFに吐き出して、キャラクタ描画テスト回路の制約ファイルにコピーすることにした。
配線の制約ファイル(UCF)への吐き出し方については、”FPGA Editorで配置と配線を割り当てる3”を参照のこと。
最初にデータバスdq_dataの配線の制約を吐き出させる。FPGA Editor を起動して、Directec Routing Constraintsダイアログを起動して、dq_dataを選択して、制約を吐き出させる。
DDR2_burst_test_4_100220.png

これがその制約。

// 02/20 @ 12:51:22
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<0>"
ROUTE="{3;1;3s700afg484;a5bd1784!-1;-70632;26072;S!0;-159;0!1;2447;-605!"
"2;4489;301!2;4489;645!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<1>"
ROUTE="{3;1;3s700afg484;751a0e0!-1;-70632;19640;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<2>"
ROUTE="{3;1;3s700afg484;89ffb99b!-1;-70632;6136;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<3>"
ROUTE="{3;1;3s700afg484;61a7f9cb!-1;-70632;9192;S!0;-159;0!1;2447;-605!2;"
"4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<4>"
ROUTE="{3;1;3s700afg484;5a9ec78e!-1;-70632;9512;S!0;-159;0!1;1696;1720!2;"
"1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<5>"
ROUTE="{3;1;3s700afg484;c3906147!-1;-70632;5816;S!0;-159;0!1;2447;-605!2;"
"4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<6>"
ROUTE="{3;1;3s700afg484;3cdde0e5!-1;-70632;19320;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<7>"
ROUTE="{3;1;3s700afg484;48045bde!-1;-70632;26392;S!0;-159;0!1;1696;1968!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<8>"
ROUTE="{3;1;3s700afg484;8152c779!-1;-70632;40144;S!0;-159;0!1;1696;1720!"
"2;1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<9>"
ROUTE="{3;1;3s700afg484;bfa7b4d9!-1;-70632;53328;S!0;-159;0!1;1696;2040!"
"2;1784;1376!2;1784;1032!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<10>"
ROUTE="{3;1;3s700afg484;ace04032!-1;-70632;36448;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<11>"
ROUTE="{3;1;3s700afg484;fc333603!-1;-70632;49952;S!0;-159;0!1;2447;-605!"
"2;4489;645!2;4489;301!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<12>"
ROUTE="{3;1;3s700afg484;4ce19306!-1;-70632;50272;S!0;-159;0!1;1696;1720!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<13>"
ROUTE="{3;1;3s700afg484;7f7f4c8c!-1;-70632;39824;S!0;-159;0!1;2447;-605!"
"2;4489;301!2;4489;645!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<14>"
ROUTE="{3;1;3s700afg484;10d3a509!-1;-70632;36768;S!0;-159;0!1;1696;1720!"
"2;1784;1032!2;1784;1376!3;167;0;L!4;167;0;L!}";
NET "ddr2_sdram_cont_i/read_write_io_inst/dq_data<15>"
ROUTE="{3;1;3s700afg484;473a4c3d!-1;-70632;53648;S!0;-159;0!1;2479;-949!"
"2;4457;661!3;0;8!3;0;-336!4;167;0;L!5;167;0;L!}";


インスタンス名はキャラクタ描画テスト回路用に変更した。

次に、dqs_clk_nodeノードも遅延が大きいので、DDR2 SDRAMバーストテスト回路の配線の制約として吐き出させる。
DDR2_burst_test_5_100220.png

インスタンス名はキャラクタ描画テスト回路用に変更した制約を下に示す。同時にdqs_clk用のBUFGを固定した。

// 02/20 @ 12:48:23
NET "ddr2_sdram_cont_i/read_write_io_inst/ddr2_cont_iob_inst/dqs_clk_node<0>"
ROUTE="{3;1;3s700afg484;c20d0b8b!-1;-70632;12888;S!0;-159;0!1;-161;-887!"
"2;-1291;-2737!3;-29;-8091!4;259;-695!5;-1703;-139!6;108;53;L!}";
INST "ddr2_sdram_cont_i/read_write_io_inst/ddr2_cont_iob_inst/BUFG_inst" LOC = BUFGMUX_X0Y5;


これらの変更を加えて、インプリメントしたらエラーが発生。dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm/DCM_SP.CLKFXのクロックルートがクロック専用ラインを通れないようだ。下の制約を加えたらインプリメントが成功した。

PIN "dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm/DCM_SP.CLKFX" CLOCK_DEDICATED_ROUTE = FALSE;


とりあえずこれでインプリメントした。DDR2 SDRAMのデータバスDQで出力タイミング続出。入力タイミングはDDR2 SDRAMバーストテスト回路と同様となってOKそうだ。タイミング解析結果を下に示す。
Bitmap_VGAC_debug_9_100220.png

ピンク枠の部分がBUFGへの入力で問題の部分。FPGA Editorでクロスプローブする。(リンクをクリック)配線が表示されるが、FPGAのチップの上から下まで配線が伸びている。
Bitmap_VGAC_debug_10_100220.png

これだと、通常の配線を長く通り過ぎているので、まずい。

なぜそうなったかは、長くなったので、次回に。。。
  1. 2010年02月20日 21:36 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路の実機デバック2(テスト回路の挿入)

さて、ビットマップVGAコントローラはOKのようなので、DDR2 SDRAMコントローラを疑うことにした。具体的には、DDR2 SDRAMコントローラから読んでくる値が毎回正しいのかを検証することにした。Chipscope PROがあれば簡単なのだが、家ではライセンスがないので、検証回路を組んで、LEDに表示することにした。
下がBitmap_VGA_Controller.v に組み込んだ検証回路だ。

    // テスト回路
    always @(posedge clk_vga) begin
        if (reset_vga)
            start_vram_data <= 16'd0;
        else begin
            if (h_count==1 && v_count==0 && pixel_afifo_rd_en)
                start_vram_data <= vram_data_out;
        end
    end
    always @(posedge clk_vga) begin
        if (reset_vga)
            diff_start_data <= 1'b0;
        else begin
            if (h_count==1 && v_count==0 && pixel_afifo_rd_en) begin
                if (start_vram_data==vram_data_out)
                    diff_start_data <= 1'b1;
                else
                    diff_start_data <= 1'b0;
            end
        end
    end
    assign start_vram_data_out = start_vram_data[6:0];    


検証回路の動作は、h_countは水平カウンタ、v_countは垂直カウンタでそれらが1, 0で、非同期FIFOのリード・イネーブル(pixel_afifo_rd_en)が1の時のデータを1フレーム前と今とで比べて、同じだったらdiff_start_dataを1にする。これはLEDに出力する。LEDは8個あるので、後の7個にはラッチしたデータの下位7ビットを出力する。うまくいけば、diff_start_dataは1のまま、start_vram_data_outは固定された値になるはず。
これでインプリメントして、実機にダウンロード。すると、最初の列の幾つかは流れているものの、その他は流れていない画像が表示された。
Bitmap_VGAC_3_100219.jpg

最初の方は、流れているので、LEDはかなりちかちかしている。これはデータが安定しないことを示す。diff_start_dataのLEDにもちかちかしている。データがあっている時も有れば、違っている時もあるみたい。
次にh_count==1の部分をh_count==512として、ちょうど真ん中のデータを見るとdiff_start_dataもずっと1のままで、データのLEDも安定した。
理由はわからないが、安定してきたようだ。これからなぜ、安定してきたかを検証してみよう。

まずは、動いている以前のDDR2 SDRAMのバーストテストのプロジェクトをリファレンスとしてみていく。
DQ0(データバス)の入力の静的タイミングを下の図に示す。
DDR2_burst_test_1_100219.png

データパスのネットの遅延が0.411nsec でとても良い感じになっている。
つぎに、キャラクタ描画テスト回路(ビットマップVGAコントローラ)のDQ0(データバス)の入力の静的タイミングを下の図に示す。
Bitmap_VGAC_debug_7_100219.png

データパスの遅延は、3.618nsec となっていて、DDR2 SDRAMバーストテストの0.411nsec とはかけ離れてしまっている。これが原因か?

次にFPGA Editor でDQ0(データバス)の配線をチェックしてみよう。まずは、DDR2 SDRAMバーストテストのDQ0(データバス)の配線を示す。
DDR2_burst_test_3_100219.png

非常に素直に配線されている。
次に、キャラクタ描画テスト回路のDQ0(データバス)の配線をFPGA Editor で見てみよう。下の図に示す。
Bitmap_VGAC_debug_8_100219.png

なんじゃこりゃ―?というような配線になっている。少なくとも原因の1つはこれだ。。。
制約もほとんど違いがないし、なぜなんだろうか?違いがあるとすればTIG制約だな。今、TIG制約を外してやってみたが、Place & Routeでエラー発生。やはり外せない。。。やるとすれば、配線の固定をする必要があるのか?IPでも、そこまでやっているのを見たことはないが、やる必要があるならば、するしかないかな???

上記の事柄について、アドバイスやなにか情報があったら教えて下さい。
  1. 2010年02月19日 06:08 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

ビットマップVGAコントローラのデバック2(実機デバック)

キャラクタ描画テスト回路の実機デバックをしていたが、どうも全体をデバックしていると問題の切り分けが難しいので、単体でデバックしてみることにした。
ビットマップVGAコントローラを単体でデバックするには、新たに画像データを作る回路とDCMで50MHzクロックから65MHzと150MHzを生成する回路を付け加える必要がある。画像データはRGBが000から始まって、インクリメントして行くような回路を付け加えた。DCMは使っていたdcm_DDR2VGA_clk.vが使えるので、そのまま使用した。
その、Bitmap_VGA_Controller_top.vを下に示す。

// Bitmap_VGA_Controller_top.v
// Bitmap_VGA_Controllerをテストするトップファイル

module Bitmap_VGA_Controller_top(SYS_CLK, SYS_RST, red_out, green_out, blue_out, hsyncx, vsyncx);
`include "Address_Map_Define.vh"

    input wire SYS_CLK;
    input wire SYS_RST;
    output wire    [3:0] red_out;
    output wire    [3:0] green_out;
    output wire  [3:0] blue_out;
    output wire hsyncx;
    output wire vsyncx;

    wire clk_vga; // 65MHz クロック入力(VGA用)
    wire clk_ddr2; // 150MHz クロック入力(DDR2へのインターフェース用)
    wire reset_vga; // clk_vga用リセット
    wire reset_ddr2; // clk_ddr2リセット
    wire [31:0] vram_start_addr; // バイトアドレス
    wire vram_request; // VRAMへのRead要求。アービタへ
    wire vram_grant; // VRAMへのRead許可。アービタから
    wire [31:0] vram_address; // バイトアドレス
    wire read_write;
    wire vram_req_we; // VRAM へのRead要求のWrite Enable
    wire vram_addr_fifo_full; // VRAMのRead要求用FIFOのFULL
    wire [31:0] vram_data_in;
    reg vram_data_valid;
    wire afifo_overflow; // 非同期FIFO のオーバーフロー・エラー
    wire afifo_underflow; // 非同期FIFO 
    wire clk_ddr2_locked, clk_vga_locked;
    
    reg [15:0] vram_data_in1, vram_data_in2;
    reg vram_req_we_1d;
    
    dcm_DDR2_VGA_clk dcm_DDR2_VGA_clk_i(
        .sysclk(SYS_CLK),
        .reset(SYS_RST),
        .clk_ddr2(clk_ddr2),
        .dcm_ddr2_locked(clk_ddr2_locked),
        .clk_vga(clk_vga),
        .dcm_vga_locked(clk_vga_locked)
    );
    assign reset_vga = SYS_RST | ~clk_vga_locked;
    assign reset_ddr2 = SYS_RST | ~ clk_ddr2_locked;
    
    Bitmap_VGA_Controller Bitmap_VGA_Cntrler_i(
        .clk_vga(clk_vga),
        .clk_ddr2(clk_ddr2),
        .reset_vga(reset_vga),
        .reset_ddr2(reset_ddr2),
        .vram_start_addr(VRAM_START_ADDRESS),
        .vram_request(vram_request),
        .vram_grant(vram_grant),
        .vram_address(vram_address),
        .read_write(read_write),
        .vram_req_we(vram_req_we),
        .vram_addr_fifo_full(vram_addr_fifo_full), 
        .vram_data_in(vram_data_in), 
        .vram_data_valid(vram_data_valid), 
        .red_out(red_out), 
        .green_out(green_out), 
        .blue_out(blue_out), 
        .hsyncx(hsyncx), 
        .vsyncx(vsyncx), 
        .afifo_overflow(afifo_overflow), 
        .afifo_underflow(afifo_underflow)
    );        

    assign vram_addr_fifo_full = 1'b0;
    assign vram_grant = 1'b1;
    always @(posedge clk_ddr2) begin // vram_req_weを1クロック遅延する
        if (reset_ddr2) 
            vram_req_we_1d <= 1'b0;
        else
            vram_req_we_1d <= vram_req_we;
    end
    
    always @(posedge clk_ddr2) begin
        if (reset_ddr2) begin
            vram_data_in1 <= 16'h0000;
            vram_data_in2 <= 16'h0fff;
        end else begin
            if (vram_req_we || vram_req_we_1d) begin // 1リクエストで2つデータを出力する
                if (vram_address==VRAM_START_ADDRESS) begin
                    vram_data_in1 <= 16'h0000;
                    vram_data_in2 <= 16'h0000;
                end else begin
                    vram_data_in1 <= vram_data_in1 + 16'd1;
                    vram_data_in2 <= vram_data_in2 + 16'd1;
                end
            end
        end
    end
    assign vram_data_in = {vram_data_in1, vram_data_in2};
    
    always @(posedge clk_ddr2) begin
        if (reset_ddr2)
            vram_data_valid <= 1'b0;
        else begin
            if (vram_req_we || vram_req_we_1d) // 1リクエストで2つデータを出力する
                vram_data_valid <= 1'b1;
            else
                vram_data_valid <= 1'b0;
        end
    end
endmodule

`default_nettype wire


テストベンチを作成して、シミュレーションを行った。その結果、アービタに出力するアドレスがおかしいバグが1つ見つかったが、他は大丈夫そうだった。シミュレーション結果を下に示す。
Bitmap_VGAC_debug_5_100217.png

大丈夫そうだったので、ISE11.4でインプリメントした。
やはり、以前のTIG制約をUCFに追加しないとタイミングエラーが出てしまった。

PIN "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm.CLKFX" TNM = VGA_CLK_OUTPUT;
PIN "dcm_DDR2_VGA_clk_i/dcm_DDR2_clk_dcm.CLKFX" TNM = DDR2_CLK_OUTPUT;
TIMESPEC TS_VGA2DDR2_CLK_TIG = FROM "VGA_CLK_OUTPUT" TO "DDR2_CLK_OUTPUT" TIG;
TIMESPEC TS_DDR22VGA_CLK_TIG = FROM "DDR2_CLK_OUTPUT" TO "VGA_CLK_OUTPUT" TIG;


無事にインプリメントできた。
Bitmap_VGAC_debug_6_100217.png

実機にダウンロードして、ディスプレイに表示させた。
Bitmap_VGAC_2_100217.jpg

画像は安定している。問題ない気がする。1つバグは修正したので、もう一度、キャラクタ描画テスト回路に戻ってやってみよう。それでもおかしい場合はDDR2 SDRAMコントローラがうまくDDR2 SDRAMのデータを読めていないのかもしれない。
もう1つ心配なのが、Spartan3A Starter Kitの抵抗分割A/Dコンバータで、果たしてドットクロック65MHzのXGAがうまく出力出来て、1ドットが見えるのか?ということが心配になってきた。その場合はSGAかVGAに落とすしかないかな?

(2010/02/18:修正)
Bitmap_VGA_Controller_top.vとシミュレーション波形を変更しました。DDR2 SDRAMコントローラは1つReadコマンドを投げると、32ビットデータ2つが帰ってくるので、整合が取れなくなっていました。
  1. 2010年02月17日 05:28 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

バンクーバーオリンピック

モーグル女子の上村選手残念でした。もう少し中盤で攻めても良いかな?とは思いましたが、良かったのではないでしょうか?スローで見ると、ちゃんとカービングになっていてびっくりしました。
USAとカナダの選手の滑りは凄かったですね。里谷選手も中盤凄い滑りで、ジャンプは残念だったですが、本当に本番に強いと言うのが良くわかりました。年齢が若かったら耐え切ってメダルに届いていたんじゃないでしょうか?
昨日はずっとこのモーグルのテレビにかじりついていました。
アルペンも楽しみです。この会場のウィスラースキー場には、遠い昔、20年くらい前に行ってきました。ウィスラーとブラッコムスキー場が2つあって、どっちの山にも行けます。麓のウィスラービレッジに泊まったので、このリフトに乗るとウィスラー、次の日は違うリフトに乗るとブラッコムに行くという感じでした。
2つにスキー場とも森林限界を超えていて、広大なスキー場です。ウィスラーの頂上は岩がゴロゴロしていました。斜度は25度以上かな?そこに大きな岩があるので、慎重に滑りました。暴走してぶつかるとイチコロですね。ウィスラーでは大砲があって、雪がふった朝だろうと思いますが、大砲を打って人工雪崩を起こしてから滑ると思いました。新雪や綺麗なコブバーンもあって楽しめました。
ブラッコムはウィスラーよりも全般的にキツイ気がして、足がつかれました。頂上では、反対側にも降りていけそうで、危ない気がしました。スキー上の境界が曖昧です。上に行ったときは地吹雪だったので、怖くなって慎重に降りてきましたね。
カナダのスキー場には他に、バンフ近郊のスキー場、レイクルイーズ、サンシャインビレッジスキー場にも行ってきました。どれも良かったです。
また行きたいですね。でも、あのロングコースに足が持たないでしょう。やはり、若いときに行くべきですね。。。
  1. 2010年02月15日 06:04 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路の実機デバック1

前回、キャラクタ描画テスト回路のインプリメントをして、実機にダウンロードしてテストしてみたが、おかしな画面になってしまった。もう一度、シミュレーションをしてみることにした。
シミュレーションしてみたのが、下の画面。
Bitmap_VGAC_debug_3_100214.png

あれ?clk_vgaのクロックがでていない。以前のシミュレーション波形を下に示す。
Bitmap_VGAC_debug_2_100211.png

やはり、clk_vgaがでていない。Verilogソースは、”キャラクタ描画テスト回路のインプリメント1(TIG制約)”で”最初にVGA信号用のDCMとDDR2 SDRAM用のDCMを同じクロック入力パッドから入力していたので、片方のクロック配線が一般配線に回ってしまうというエラーが出てしまった。これは、DDR2 SDRAM用のDCM出力 (BUFG出力) からVGA信号用のDCMのクロック入力につなぐくことにして問題解決。”というところしか、いじってないので、ここが悪いのだろう?
DDR2 SDRAM用のDCMのLOCKED信号を反転して、VGA信号用のDCMのリセットに入れることにした。この対策をした結果、clk_vgaも出力されて、元のシミュレーション波形と一致した。
とりあえず、インプリメントして、実機で見てみた。少し画面は変化したが、あまり変わらない。
次に、キャラクタ生成コントローラへのGRNATを止めてみた。つまり、画面には何も書かないようにした。そうしたところ色はなくなったが、まだ動いているように感じる画像だった。
次に、シミュレーションで確認してみようと思ったが、時間とディスク容量がかかりすぎるので、このままでは無理だ。そこで、VGA信号のタイミングをいじることにした。垂直関係の信号を下のようにいじってみた。(パラメータ化しておくと、こういう時に一発でタイミングを変更出来て便利だ)

parameter V_ACTIVE_VIDEO = 2;
parameter V_FRONT_PORCH = 0;
parameter V_SYNC_PULSE = 1;
parameter V_BACK_PORCH = 0;
// parameter V_ACTIVE_VIDEO = 768;
// parameter V_FRONT_PORCH = 3;
// parameter V_SYNC_PULSE = 6;
// parameter V_BACK_PORCH = 29;


これで垂直同期までシミュレーションで現実的な時間で見ることが出来る。
シミュレーションを下の図に示す。
Bitmap_VGAC_debug_4_100215.png

hsyncxとvsyncxが水平同期と垂直同期だ。問題なさそう。
次に、pixel_afifo_rd_enの長さを測る。15,753,848psecだった。これをクロックの65MHzの逆数で割ると、約1024となり(ぴったりには割れないが、誤差かな?)、非同期FIFOから読み出しているデータ数にも問題はなさそう。

今のところ、どこが問題なのか良くわからなくなってきたので、ビットマップVGAコントローラ単体で、適当なデータを与えて表示させてみようと思う。やはり、単体テストを行わないのは、まずかったか?やはり、単体テストからですね。当たり前か。。。
  1. 2010年02月15日 05:35 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路のインプリメント2(配置制約を付加)

”キャラクタ描画テスト回路のインプリメント1(TIG制約)”で150MHzと65MHzの2つの周波数のクロック間のタイミング解析を解析しないように設定した。今度は、DDR2 SDRAMコントローラのRead用FIFO素子の配置を固定する。配置は、以前、DDR2 SDRAMコントローラを作ったときに、作ってある(Spartan3A Starter KitのDDR2 SDRAMコントローラの途中経過5(ロジックセルの固定の微調整)を参照)。その制約をインスタンス名を少し変えて、UCFファイルに追加した。下にその制約の一部を示す。

INST "ddr2_sdram_cont_i/read_write_io_inst/rddata_afifo_inst/DQS2intclk_FIFO_FALL/DPRAM_GEN[15].RAM16X1D_inst" LOC = SLICE_X2Y79;
INST "ddr2_sdram_cont_i/read_write_io_inst/rddata_afifo_inst/DQS2intclk_FIFO_FALL/DPRAM_GEN[14].RAM16X1D_inst" LOC = SLICE_X0Y71;


この制約を追加して、インプリメントした。その結果を下に示す。
Bitmap_VGAC_implement_10_100213.png

タイミング制約が1つ満たされていない。タイミング解析結果を下図に示す。
Bitmap_VGAC_implement_11_100213.png

150MHzパスが123psecほどタイミングエラーが出ている。色々、コストテーブルを変更してインプリメントしてみたが、この結果が最良のようだ。とりあえず、これでも動作に支障はないだろうということで、実際にSpartan3A Starter Kitにコンフィギュレーションして実機で確認してみた。
そうすると下のように、なんだか分からない画面が出た。
Bitmap_VGAC_1_100214.jpg

訳がわからない。液晶ディスプレイのメニューを表示させた。
Bitmap_VGAC_2_100214.jpg

同期は取れているようなので、書くキャラクタのアドレスを間違えているのかもしれない?
もう一度、シミュレーションで確認してみようと思う。
  1. 2010年02月14日 05:09 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路のインプリメント1(TIG制約)

前回、キャラクタ描画テスト回路のシミュレーションを行ったので、今度はインプリメントをしてみた。
最初にDDR2 SDRAMのバーストテストの時のUCFを貼りつけて、VGA出力などの足りないところはSpartan3A Starter Kitのユーザーズガイドから持ってきてUCFを完成させた。それでインプリメントしたところ、最初にVGA信号用のDCMとDDR2 SDRAM用のDCMを同じクロック入力パッドから入力していたので、片方のクロック配線が一般配線に回ってしまうというエラーが出てしまった。これは、DDR2 SDRAM用のDCM出力 (BUFG出力) からVGA信号用のDCMのクロック入力につなぐくことにして問題解決。
次に入力クロックの周期だが、20nsecでは到底メットしないとのエラーが出て、Place & Route(以下P&Rと省略)でエラーで止まってしまう。幾つか値を入れたところ100nsecでやっと通って、インプリメントが成功した。全くもっておかしいので、P&R後のタイミング解析結果を見てみたところ、非同期FIFO のclk_vga(65MHz予定クロック)ロジックからclk_ddr2(150MH予定クロック)ロジックまでの非同期FIFO のパスを解析してしまっている。
Bitmap_VGAC_implement_1_100213.png

これは、2つのクロックを使用するロジック間のパスのTIG制約を加える必要がある。以前に、”UCFの書き方3”で説明したことがあるが、今度はConstraints EditorからTIG制約を追加してみようと思う。それでは制約を追加しよう。
Project NavigatorのProcessesペインのUser ConstraintsからCreate Timing Constraints をダブルクリックする。
Bitmap_VGAC_implement_2_100213.png

Constraints EditorがProject Navigator上に表示されるので、左のConstraints TypeからGroup ConstraintsのBy DCM Outputsを選択して、DCM/PLL/MMCM 出力ピンごとの制約のグループ化を行うことにする。double click to add a new constraints... をダブルクリックすると、Group Constraints by DCM/PLL/MMCM Outputs (TNM)ダイアログが出てくる。
Bitmap_VGAC_implement_3_100213.png

ダイアログのTime name を入力して、VGAクロック用のDCMを選択する。Available output net pins: リストからCLKFXをクリックで選択して、AddボタンでOutput net pin targets: リストに追加する。(VGA用クロックはCLKFXで作っている)Createボタンをクリックして、制約を生成する。
Bitmap_VGAC_implement_4_100213.png

同様にDDR2_CLKの制約を生成する。
Bitmap_VGAC_implement_5_100213.png

2つのグループ制約が生成できた。
Bitmap_VGAC_implement_6_100213.png

次にTIG制約を生成しよう。
左のConstraints TypeからTiming ConstraintsのExceptionsのPathsを選択する。右の1ライン目を右クリックして、右クリックメニューからCreate Constraints を選択する。
Bitmap_VGAC_implement_7_100213.png

Path Exceptionsダイアログが表示される。TIMESPEC nameにTS_VGA2DDR2_CLK_TIGを入力して、Time groupsにFrom group:にVGA_CLK_OUTPUTを選択し、To groups:にDDR2_CLK_OUTPUTを選択する。Constraint typeでMark as false pathsのラジオボタンをクリックする。Createボタンをクリックする。これでVGA_clkで動作するロジックからDDR2_clkで動作するロジックへのパスを無視する設定をすることができた。
Bitmap_VGAC_implement_8_100213.png

次に、DDR2_clkで動作するロジックからVGA_clkで動作するロジックへのパスを無視する設定をする。これが出来上がり図。
Bitmap_VGAC_implement_9_100213.png

これでセーブして、UCFファイルを見てみると、下のような制約が付加された。

PIN "dcm_DDR2_VGA_clk_i/dcm_VGA_clk_dcm.CLKFX" TNM = VGA_CLK_OUTPUT;
PIN "ddr2_sdram_cont_i/dcm_module_inst/DCM_INST1.CLK0" TNM = DDR2_CLK_OUTPUT;
TIMESPEC TS_VGA2DDR2_CLK_TIG = FROM "VGA_CLK_OUTPUT" TO "DDR2_CLK_OUTPUT" TIG;
TIMESPEC TS_DDR22VGA_CLK_TIG = FROM "DDR2_CLK_OUTPUT" TO "VGA_CLK_OUTPUT" TIG;


これで、入力クロックの周期制約をもう一度、20nsecにしてインプリメント。P&Rの途中でけられることはなくなった。良かった。やはり、上記のパスが原因だった。しかし、タイミングエラーはまだある。
  1. 2010年02月13日 10:00 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

キャラクタ描画テスト回路のシミュレーション

大体、キャラクタ描画テスト回路のシミュレーションが終了した。
キャラクタ描画テスト回路の構成図を下に示す。
Char_Draw_Test_1_100201.png

関連する資料
Spartan3A Starter KitのビットマップVGAコントローラの仕様1
Spartan3A Starter KitのビットマップVGAコントローラの仕様2
キャラクタ生成コントローラの仕様
キャラクタ生成コントローラの仕様2



キャラクタ描画テスト回路の主なモジュールのシミュレーション波形を下に示す。
Bitmap_VGAC_debug_2_100211.png

ビットマップVGAコントローラについては、”ビットマップVGAコントローラのデバック1”で説明済みだ。
DDR2 SDRAMはDDR2 SDRAMコントローラの出力だ。上に書いてあるREADがビットマップVGAコントローラのDDR2 SDRAMのRead、WRITEがキャラクタ生成コントローラのWriteを表す。Writeを見ると間が空いているのがわかると思うが、これは、キャラクタを描画する際のドットの行が変わるときに、VRAMアドレスが不連続となるためだ。WRITEの時に下のChar_Graphic_Processorを見ると、動作しているのが確認できる。よく見ると間が空いているのがわかると思う。これは非同期FIFOにDDR2 SDRAMへのWriteを積んでいくが、ビットマップVGAコントローラがDDR2 SDRAMを使用しているため、非同期FIFOがFULLになるとWaitするためだ。ビットマップVGAコントローラがDDR2 SDRAMの使用を終了すると、アービタからのGRANTがアクティブとなって、キャラクタのビットをDDR2 SDRAMに書き込んでいく。この後のキャラクタの書き込みは、1秒間に20キャラクタ書く予定なので、50ms後となり、現在のシミュレーション時間では見ることが出来ない。

本当はもっとCとのインターフェースを作って、表示を確認するシミュレーションをすれば良いのだろうが、シミュレーション時間も半端ないだろうし、これで大体、シミュレーションは終了として、次はインプリメントに移ることにする。
  1. 2010年02月11日 19:21 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

Notepad++にChange Makersプライグインを入れる

以前のNotepad++には、変更された箇所が黄色の線で示され、セーブしたら緑色の線で示される機能があった。この機能がどうしても欲しかったので、調べてみるとNotepad++用プライグインのサイトがあって、そこにChange Makersがあった。このプラグインを入れると、私の希望の機能が実現できるようだ。
早速、Change MakersのサイトからUnicode用のプラグインをダウンロードした。
ダウンロードした内容(下の図)をNotepad++を閉じてから、Notepad++のフォルダの下のpluginsフォルダにコピーする。
Change_Makers_1_100210.png

すべてコピーしないと動かないようだ。
Notepad++を起動すると左脇に1列増えている。まだChange Makersがイネーブルされていないので、変更しても表示されない。プラグインメニューからChange Makersを選んで、Disable Pluginのチェックを外すと有効になる。
Change_Makers_2_100210.png

更に左脇の増えている1列が気になるので、それを削除しよう。やはりプラグインメニューからPlugin Maker Marign のSecond View: Show Margin のチェックを外す。こうすると左脇の余計なマージンがなくなるはずだ。
Change_Makers_3_100210.png

これで、Notepad++の画面で文字を入力してみると、黄色い金平糖マークが表示される。
Change_Makers_4_100210.png

次に、そのファイルをセーブすると緑の金平糖マークになる。
Change_Makers_5_100210.png

とりあえず目的は達したが、いろいろなプラグインがあるようなので、後で見てみよう。

(追記)
いままでの記述はWindwos XPだったが、Vistaでは挙動が違うようだ。まずは、Change Makersが最初から有効になっていた。
Plugin Maker MarignのSecond View: Show Margin のチェックは外せなかった。その代わりにNppPlugin_PluginMargin.dll を入れなくても怒られずに、入れなければ左脇の余計なマージンは出てこない。どうなるか分からないが、これでやってみようと思う。(自己責任でお願いします)
  1. 2010年02月10日 05:51 |
  2. EDAツールについて
  3. | トラックバック:0
  4. | コメント:0

ビットマップVGAコントローラのデバック1

ビットマップVGAコントローラをデバックしている。大体動作してきたと思う。
下にシミュレーション波形を示す。
Bitmap_VGAC_debug_1_100209.png

vram_addressが読んでくるVRAM(DDR2 SDRAM)のアドレスを示す。読んでくる時にカウントアップされている。vram_req_weはアービタへのVRAMのリクエストを書き込む信号。リクエストしたVRAMアドレスのデータがvram_data_inにでてきて、その有効はvram_data_validによって示される。
cs_rdgステートマシがビットマップVGAコントローラの描画データの読み込み状態を示す。最初にidle_rdgになっているが、リセットが外れたら、init_full_modeになって、描画データを貯めておくpixel_async_fifoをFULL状態になるまで、アービタにリクエストを出す。リクエストがDDR2 SDRAMコントローラに届いて、VRAMにある描画データを読み込みpixel_async_fifoがFULLになったら、cs_rdgステートマシンはwait_half_full状態に移行し、pixel_async_fifoが描画データを吐き出して、半分になるのを待つ。半分になったら、cs_rdgステートマシはreq_vram_burstステートに移行し、pixel_async_fifoの容量半分をアービタにリクエストをだして、描画データを読んでくる。
最初に、pixel_async_fifoがFULLになってから、描画もスタートする。これは、cs_rdgステートマシがinit_full_modeからwait_half_full状態に移行したときにh_countのカウントが始まることでわかると思う。今のところ、動作的にはうまく行っているようだ。ちなみにDDR2 SDRAMから読んでくるデータはまだ、書き込んでいないのでXとなってしまっている。
pixel_async_fifoがFULLから半分になるのが2.672usec、req_vram_burstステートに移行して描画データを読んでから、もう一度req_vram_burstステートに移行するまでの時間は1.541usecだった。最初は描画が止まっているので、長い時間になっている。req_vram_burstステートでは、ちょうどpixel_async_fifoの容量の半分のデータをアービタにリクエストしているが、もう少し増やそうと思う。
  1. 2010年02月09日 05:44 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0

VeritaKシミュレーション時のデバック方法(エディタ ドライバ記述に飛ぶ)

いままでは、Veritakをあまり気にしないで使ってきたが、いろいろと便利な機能があるようなので、使ってみた。そのことを備忘録として書いておくことにした。
今のところ、グラフィック・コントローラ・テスト回路は、DDR2 SDRAMコントローラのアドレスFIFOがOVERFLOWになり、FIFOのアサーションでシミュレーションがストップされているがその原因を探ることにした。
下のシミュレーション波形でddr2_addr_fifo_fullが1になったときに、ddr2_addr_fifo_weが1になるのがおかしい。つまりFIFOがFULLになったときに書き込んでいる。これをトラブルシュートする。
Veritak_debug_1_100208.png

その前に、私の環境はVeritak-Basic 3.75A で、エディタのNotepad++ v5.6.6にNppVeritakPlugin04をインストールして使用している。Notepad++の使用とプラグインのインストールはここを参照
さて、今回はWaveform Viewerの信号名の右クリックメニューのうちの”エディタ ドライバ記述に飛ぶ”を使いたかった。普通にやるとエラーダイアログが出て使用することが出来ないので、検索したところ、ここに記述があった
このマニュアルによると、Trace Debug Mode でコンパイルする必要があるそうだ。早速、Verilogプロジェクtメニューからプロジェクト設定を選択して、Project Settingダイアログを出して、Debug Mode をTrace Debug Modeに設定し、もう一度コンパイル、シミュレーションをした。これで、右クリックメニューのうちの”エディタ ドライバ記述に飛ぶ”を使う準備ができた。
Veritak_debug_2_100208.png

さて、ddr2_addr_fifo_weの右クリックメニューのうちの”エディタ ドライバ記述に飛ぶ”を選択する。その時にT1カーソルの位置(ピンクの四角の位置)のドライバ記述に飛ぶと言うことなので、T1カーソルをddr2_addr_fifo_fullが1になったときに合わせる。
Veritak_debug_3_100208.png

そうするとNotepad++の該当するドライバ記述に飛ぶ。
Veritak_debug_4_100208.png

その時に、信号にマウスカーソルを合わせるとT1カーソル時の値が表示される。これの表示は信号の階層が深いと画面の右端にフェードアウトしてしまうので、なるべくNotepad++を左に持ってくる。(この辺の回避方法があったら教えてください)
Veritak_debug_5_100208.png

ここで、ddr2_addr_fifo_we <= Bitmap_VGAC_addr_we;の記述があるので、Bitmap_VGAC_addr_weの記述を見たいということになる。Bitmap_VGAC_addr_weを選択して、Npp-Veritak IFダイアログのAdd Waveformボタンをクリックする。
Veritak_debug_6_100208.png

そうするとVeritakのWaveform ViewerにBitmap_VGAC_addr_weが追加されているので、右クリックメニューのうちの”エディタ ドライバ記述に飛ぶ”を選択する。
Veritak_debug_7_100208.png

そうするとBitmap_VGAC_addr_weのドライバ記述に飛ぶことができる。
Veritak_debug_8_100208.png

こうやって、便利に原因を特定していくことができる。

#ちなみに、このバグは、ブログを書くために残しておいたので、まだでバック出来ていない。ブログ書きながらなので、デバックが進まないが、後でやり方がわからなくならないように残しておく。

(追記)
バグの原因がわかりました。Bitmap_VGAC_addr_weのドライバ記述のステーマシンのステート値の定義でした。下のように書かれていました。

parameter [1:0] vram_req_we_low= 2'b01,
           vram_req_we_high= 2'b01; // active


下のように修正したら直りました。

parameter [1:0] vram_req_we_low= 2'b01,
           vram_req_we_high= 2'b10; // active


  1. 2010年02月08日 05:50 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Veritakでステートマシンのステート表示

今まで、Verilogのステートマシンは論理合成不可の部分にストリングで書いていたが、(”Verilogでのシミュレーションの疑問(解決編)”参照) Veritakでenum選択でステートが表示できると聞いたような気がしたので、やってみることにした。
cs_mainステートマシンを選んで、右クリック。右クリックメニューから”表示の選択”を選び、その下の”enum選択”を選ぶ。
Veritak_enum_1_100207.png

parameter selectionダイアログが出てくる。ここで、使うパラメータをすべて選択してもステートは表示されない。
Veritak_enum_2_100207.png

ステートマシンのパラメータの宣言は下のようになっている。

parameter wait_cmd_fifo_not_empty =4'b0001;
parameter vram_addr_counter_load =4'b0010;
parameter next_char_code_load =4'b0100;
parameter char_generation_state =4'b1000;


Veritakマニュアル2.4.2 Enum Displayを見るとparameterの書き方が悪いのがわかった。それによると、下のように書く必要があるらしい。

parameter [3:0] wait_cmd_fifo_not_empty = 4'b0001,
                vram_addr_counter_load =  4'b0010,
                next_char_code_load =     4'b0100,
                char_generation_state =   4'b1000;


上のように書き換え、コンパイル、シミュレーションして、cs_mainステートマシンを選んで、右クリック。右クリックメニューから”表示の選択”を選び、その下の”enum選択”を選んで、parameter selectionダイアログを出す。
Veritak_enum_3_100207.png

param0~param3 まで値が入って、この行を選択してOKボタンをクリックすると、ステート値が表示された。
Veritak_enum_4_100207.png

うまく行ってよかった。上記のように全部のステートマシンを書き換えようと思う。

見てわかるとおりに、グラフィック・コントローラ・テスト回路の動作はまだまだおかしい。まだ、DDR2 SDRAMコントローラのアドレスFIFOがOVERFLOWになり、FIFOのアサーションでシミュレーションがストップされている。Verilogのアサーションだけども、やはりアサーションは便利だ。
これからステートマシンのステート値を定義するparameterを書き換えてデバックする予定だ。
  1. 2010年02月07日 19:15 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

NetBeans IDE 6.8 でRubyをデバック

この頃、仕事でVHDLファイルを生成するためのRubyプログラムを書いている。Rubyはダウンロードしたのだが、コマンドプロンプトでやるのでは、どうにも効率がわるい。
そこで、NetBeans IDE 6.8を使ってRubyを書いて、デバックしてみることにした。Java SE Development Kit 6u18 および NetBeans IDE 6.8をダウンロードしてインストールし、起動した。
起動後にRubyプラグインを入れる必要がある。ツールメニューからプラグインを選択すると、プラグインダイアログが開く。使用可能なプラグインタブをクリックして、RubyおよびRailsを選択してインストールする。
更に既存のRubyファイルをプロジェクトに入れてデバックしてみることにした。下の図が新規プロジェクトを作って、既存のRubyソフトをプロジェクトに入れたところ。
NetBeans_IDE_68_1_100205.png

ここのText Editorで記述をミスればワーニングやエラーが出てくる。理由も出てくる。ここでは英語だが、一部日本語でも職場ではでてきた。
NetBeans_IDE_68_2_100205.png

更に、ここで書くと、例えばfile. と入力するとその下のメソッドを表示してくれる。説明もあるものは出てくる。しかしこんなにメソッドがあるのか?まだ良くわからないけどしぼれるのかな?
NetBeans_IDE_68_3_100205.png

次にデバックなのだが、まだ良くわからないのだが、単体ファイルをデバックするときには、デバックメニューからファイルをデバックを選ぶと良いみたいだ。(デバックの前に行番号をクリックしてブレークポイントを設定しておく)
NetBeans_IDE_68_4_100205.png

そうするとファイルのデバックダイアログが出てくる。
NetBeans_IDE_68_5_100205.png

ここに、実行引数とRubyオプションを入れて、了解ボタンをクリックしデバックカーを実行する。そうするとデバックモードになって、ブレークポイントで停止する。Text Editorの変数にマウスカーソルを合わせると値が表示されるようだ。
NetBeans_IDE_68_6_100205.png

右下の変数タブをクリックすると変数の値を見ることができる。
NetBeans_IDE_68_7_100205.png

コマンドプロンプトからやるのよりもとても便利。
更にデバッカーを起動すると、サーバー用のTCPポート3000が使われていてサーバーが起動出来ないと言うエラーが出たが、これはRuby Railsのサンプルプロジェクトをロードする。プロジェクトを右クリックし、右クリックメニューからプロパティーを選ぶとプロジェクトプロパティーのダイアログが出てくるので、そこのサーバーポート番号を変更する。
NetBeans_IDE_68_8_100205.png

NetBeans IDE 6.8を使ってRubyを書くと便利だと思った。

#職場でやってみたのだが、うまくいかなかったので、家でもやってみたらうまく行った。備忘録として書いてみました。

(2010/02/08:追記)
RubyおよびRailsプラグインの記述を追加。

  1. 2010年02月06日 05:19 |
  2. Ruby
  3. | トラックバック:0
  4. | コメント:0

ISE Text Editor のオートコンプリート機能

ISE Test Editorを使っていたときに、Notepad++の癖でCTRLキー+RETURNキーを押してしまった。そうしたら、同様にリストボックスがでてきた。えー、もしかして、補完機能があったのか?
ISE_text_editor_1_100205.png

リストから単語を選ぶ時は、上向き矢印と下向き矢印で単語を選択して、Enterキーで確定する。
ヘルプを見ると”オートコンプリートを使用したテキストの追加”ができるみたい。ヘルプを下に引用。
ISE_text_editor_3_100205.png

ISE Test Editorのヘルプを見ると、他にISimのブレークポイントなども設定できるようだ。
さらに”al”と入力して、CTRL+RETURNキーを押すと、下のようにalways, always_ff, always_combなどが予約語のリストに上がってきた。これってSystemVerilog対応の準備だろうか?マニュアルにはalways_ff, always_combが予約語とは書いていない。
ISE_text_editor_2_100205.png

恥ずかしながら、ISE Test Editorにオートコンプリート機能がついていることを知らなかった。皆さんは御存知でしたか?
ISE Test Editorを快適に使えるようになってよかった。

(追加)
検索したら、”32494 - 11.1 ISE Text Editor - オートコンプリートを使用すると「FATAL_ERROR:GuiUtilities:Gui_Clip_ApplicationBase.c:316:1.20」というエラー メッセージが表示される”が見つかりました。これによるとISE11.1で、オートコンプリート使用時に、リストをマウスでクリックするとProject Navigatorがクラッシュするそうです。
32633 - ISE Design Suite 11 - ISE 11.x アップデート README (11.2、11.3、11.4)”を見るとISE11.4までで直っているみたいです。ISE11.4で実際にやってみましたが、リストをマウスでクリックしても選べないだけで、Project Navigatorはクラッシュしませんでした。ISE11.1の方はご注意ください。
  1. 2010年02月05日 04:56 |
  2. その他のXilinxのツールについて
  3. | トラックバック:0
  4. | コメント:2

キャラクタ描画テスト回路の経過1(エラー出まくり)

キャラクタ描画テスト回路を一応、Verilogコーディングし終えて、デバックをしているがエラー出まくり。
現在のProject Navigatorの様子を下に示す。こんな感じの階層になっている。
Char_Draw_Test_2_100203.png

今出来なくて悩んでいることがある。それはparameterでビット幅を定義することだ。defineでビット幅を定義できることは知っているのだけど、parameter ではできないのだろうか?

parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。

parameter CHAR_GEN_CONTROLLER_ADDR = DECODE_ADDRESS_LENGTH'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = DECODE_ADDRESS_LENGTH'h0;

cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (DECODE_ADDRESS_LENGTH-8)'d4, 4'd0};
cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (32-(DECODE_ADDRESS_LENGTH+4))'d4, 4'd0};


上の例がエラーになってしまう。どうやって書くかを検索中。

(たっくさんの最初のコメント後に修正)
上に書き写したVerilogソースが間違っていたので修正しました。すみません。
つまり、DECODE_ADDRESS_LENGTH, CHAR_GEN_CONTROLLER_ADDR, DDR2_SDRAM_ADDRのパラメータを別のインクルードファイルにしておいて、お手軽にすべてのVerilogソースのアドレスデコードのビット幅を変化させたいということです。やってみたのですが、DECODE_ADDRESS_LENGTH'hFとかは書けないみたいです。つまりビット幅の所にパラメータで定義した値を書けないのかな?ということです。
これだと上の3行のシンタックスチェックが通るのはやってあります。(cpu_address = ... は確かめていない)

`define DCODE_ADDRESS_LENGTH 4 // デーコードするアドレス長、上のビットから何ビットデーコードするか。

parameter CHAR_GEN_CONTROLLER_ADDR = `DECODE_ADDRESS_LENGTH'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = `DECODE_ADDRESS_LENGTH'h0;

cpu_address <= {CHAR_GEN_CONTROLLER_ADDR, (32-(`DECODE_ADDRESS_LENGTH+4))'d4, 4'd0};


#今度は大丈夫かな?心配になってきた。。。

(2010/02/04追記)
上の最後の行はエラーになると、たっくさんに教えていただいた。たっくさん、ありがとうございました。
結局、このように書き直した。

parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。

parameter CHAR_GEN_CONTROLLER_ADDR = 4'hF; // キャラクタ生成コントローラのアドレスマップ
parameter DDR2_SDRAM_ADDR = 4'h0;

cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 4;
cpu_address[3:0] <= 4'd0;


ついでに、アドレスマップを定義するAddress_Map_Define.vhを下に示す。

// Address_Map_Define.vh
// アドレスマップを定義する

    parameter DECODE_ADDRESS_LENGTH = 4; // デーコードするアドレス長、上のビットから何ビットデーコードするか。
    
    parameter CHAR_GEN_CONTROLLER_ADDR = 4'hF; // キャラクタ生成コントローラのアドレスマップ
    parameter DDR2_SDRAM_ADDR = 4'h0;


次に、キャラクタ生成コントローラのコマンド、ステータスレジスタのマップを表すCommand_Status_Define.vhを示す。

// Command_Status_Define.vh

    // Command Registers
    
    // 0番地の割り当て
    parameter CHAR_CODE_UPPER_HIGH        = 31; // キャラクタ・コードの上位バイト
    parameter CHAR_CODE_UPPER_LOW        = 24;
    parameter CHAR_CODE_LOWER_HIGH        = 23; // キャラクタ・コードの下位バイト
    parameter CHAR_CODE_LOWER_LOW        = 16;
    parameter NOT_PAINTED_BACKGROUND    = 15; // 0 - 文字の背景を塗りつぶす, 1 - 文字の背景を塗りつぶさない
    parameter DRAW_IMMEDIATELY            = 14; // 0 - 8番地の書き込みを待つ, 1 - 0番地の書き込みだけで描画
    parameter RED_FEILD_HIGH            = 11;
    parameter RED_FEILD_LOW                = 8;
    parameter GREEN_FEILD_HIGH            = 7;
    parameter GREEN_FEILD_LOW            = 4;
    parameter BLUE_FEILD_HIGH            = 3;
    parameter BLUE_FEILD_LOW            = 0;
    
    // 4番地の割り当て
    parameter MAGNIFICATION_HIGH        = 15; // 拡大倍率
    parameter MAGNIFICATION_LOW            = 11;
    // Red, Green, Blue の割り当ては0番地と同じ
    
    // 8番地の割り当て
    parameter VRAM_START_ADDRESS_HIGH    = 31;
    parameter VRAM_START_ADDRESS_LOW    = 0;
    
    // Status Register
    parameter FIFO_COUNT_HIGH            = 4;
    parameter FIFO_COUNT_LOW            = 0;
    
    // 各領域のビット幅
    `define CHAR_CODE_UPPER_WIDTH 8
    `define CHAR_CODE_LOWER_WIDTH 8
    `define RED_FEILD_WIDTH 4
    parameter RED_FEILD_WIDTH = 4;
    `define GREEN_FEILD_WIDTH 4
    parameter GREEN_FEILD_WIDTH = 4;
    `define BLUE_FEILD_WIDTH 4
    parameter BLUE_FEILD_WIDTH = 4;
    `define MAGNIFICATION_WIDTH 5
    `define VRAM_START_ADDRESS_WIDTH 32
    `define FIFO_COUNT_WIDTH 5


最後に、今回問題のあった記述のあるプロセッサの代わりをするステートマシン、Char_Draw_for_Test.v

// テスト用キャラクタ描画モジュール
// Char_Draw_for_Test.v
// 
// グラフィックメモリの先頭からキャラクタを描画する。0~9まで、A~Zまで描画したら元に戻る。背景色は黒とする
// Char_Gen_Controller.v のCPUのインターフェースを操作する。
// DDR2 SDRAMは64Mbytes, よって先頭を0x0とすると0x3FF_FFFFまで。
// グラフィックメモリは1024X768X2bytes = 1,572,864 bytes = 0x18_0000
// グラフィックメモリは0x300_0000からとする
// キャラクタは128X96文字 = 12,288文字を1画面に描画できる

`default_nettype none

module Char_Draw_for_Test (clk_vga, reset_vga, cpu_address, cpu_write_data, cpu_read_data, cpu_data_we);

    input wire clk_vga; // VGAのクロック、65MHzの予定
    input wire reset_vga; // clk_vga用リセット
    output reg [31:0] cpu_address; // CPUのアドレス
    output wire [31:0] cpu_write_data; // CPUのWrite データ
    input wire [31:0] cpu_read_data; // CPUのRead データ
    output reg cpu_data_we; // CPUのデータ入力のWrite Enable
    
    `include "Address_Map_Define.vh"
    `include "Command_Status_Define.vh"
    
    parameter idle_char                = 6'b000001;
    parameter CGC_first_cmd0_set    = 6'b000010;
    parameter CGC_cmd4_set            = 6'b000100;
    parameter CGC_cmd8_set            = 6'b001000;
    parameter Wait_CGC_cmd0            = 6'b010000;
    parameter CGC_cmd0_loop            = 6'b100000;
    reg [5:0] cs_char;
    reg [7:0] char_code_count; // キャラクタのカウンタ
    reg [RED_FEILD_HIGH:RED_FEILD_LOW] red_count;
    reg [GREEN_FEILD_HIGH:GREEN_FEILD_LOW] green_count;
    reg [BLUE_FEILD_HIGH:BLUE_FEILD_LOW] blue_count;
    wire op_ena;
    reg [13:0] vram_disp_count;
    reg [31:0] cmd_data;

    // 周波数分周
    freqdiv #(.DIVISOR(3250000)) // 65MHzを20Hzにする
    freqdiv_inst (
        .clk(clk_vga),
        .reset(reset_vga),
        .op_ena(op_ena)
    );
    
    // キャラクタを書きまくるステートマシン
    always @(posedge clk_vga) begin
        if (reset_vga)
            cs_char <= idle_char;
        else begin
            case (cs_char)
                idle_char :
                    cs_char <= CGC_first_cmd0_set;
                CGC_first_cmd0_set : // キャラクタ生成コントローラの0番地に最初のキャラクタと色をセット
                    cs_char <= CGC_cmd4_set;
                CGC_cmd4_set : // キャラクタ生成コントローラの4番地背景色、倍率をセット
                    cs_char <= CGC_cmd8_set;
                CGC_cmd8_set : // キャラクタ生成コントローラの8番地アドレスをセットして1キャラクタ描画
                    cs_char <= Wait_CGC_cmd0;
                Wait_CGC_cmd0 : // 次のキャラクタを書くまでのWait
                    if ((cpu_read_data[FIFO_COUNT_HIGH:FIFO_COUNT_LOW]<5'h01110) && op_ena)
                        cs_char <= CGC_cmd0_loop;
                CGC_cmd0_loop : // ループしながらキャラクタと色を+1しながら
                    if (vram_disp_count>14'd12287) // 1画面描画済み
                        cs_char <= CGC_first_cmd0_set;
                    else
                        cs_char <= Wait_CGC_cmd0;
            endcase
        end
    end
    
    
    // キャラクタ生成コントローラのコマンドデータの用意
    always @(posedge clk_vga) begin
        if (reset_vga) begin
            cpu_address <= 32'd0;
            cmd_data <= 32'd0;
            cpu_data_we <= 1'b0;
        end else begin
            case (cs_char)
                idle_char :begin
                    cpu_address <= 32'd0;
                    cmd_data <= 32'd0;
                    cpu_data_we <= 1'b0;
                end
                CGC_first_cmd0_set : begin
                    cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
                    cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
                    cpu_address[3:0] <= 4'd0;
                    
                    cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
                    cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= `CHAR_CODE_LOWER_WIDTH'h30; // 0x30
                    cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
                    cmd_data[DRAW_IMMEDIATELY] <= 1'b0; // アドレスの書き込みを待つ
                    cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
                    cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
                    cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
                    cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
                    
                    cpu_data_we <= 1'b1;
                end
                CGC_cmd4_set : begin
                    cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
                    cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
                    cpu_address[3:0] <= 4'd4;
                    
                    cmd_data[31:MAGNIFICATION_HIGH+1] <= 0;
                    cmd_data[MAGNIFICATION_HIGH:MAGNIFICATION_LOW] <= 0; // 倍率1倍
                    cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= `RED_FEILD_WIDTH'd0;
                    cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= `GREEN_FEILD_WIDTH'd0;
                    cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= `BLUE_FEILD_WIDTH'd0;
                    
                    cpu_data_we <= 1'b1;
                end
                CGC_cmd8_set : begin
                    cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
                    cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
                    cpu_address[3:0] <= 4'd8;
                    
                    cmd_data <= VRAM_START_ADDRESS;
                    cpu_data_we <= 1'b1;
                end
                Wait_CGC_cmd0 : begin
                    cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
                    cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
                    cpu_address[3:0] <= 4'd0;
                    
                    cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
                    cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= char_code_count;
                    cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
                    cmd_data[DRAW_IMMEDIATELY] <= 1'b1; // アドレスの書き込みを待つ
                    cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
                    cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
                    cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
                    cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
                    
                    cpu_data_we <= 1'b0;
                end
                CGC_cmd0_loop : begin
                    cpu_address[31:31-(DECODE_ADDRESS_LENGTH-1)] <= CHAR_GEN_CONTROLLER_ADDR;
                    cpu_address[31-(DECODE_ADDRESS_LENGTH):4] <= 0;
                    cpu_address[3:0] <= 4'd0;
                    
                    cmd_data[CHAR_CODE_UPPER_HIGH:CHAR_CODE_UPPER_LOW] <= 0;
                    cmd_data[CHAR_CODE_LOWER_HIGH:CHAR_CODE_LOWER_LOW] <= char_code_count;
                    cmd_data[NOT_PAINTED_BACKGROUND] <= 1'b0; // 背景を塗りつぶす
                    cmd_data[DRAW_IMMEDIATELY] <= 1'b1; // アドレスの書き込みを待つ
                    cmd_data[DRAW_IMMEDIATELY-1 : RED_FEILD_HIGH+1] <= 0;
                    cmd_data[RED_FEILD_HIGH:RED_FEILD_LOW] <= red_count;
                    cmd_data[GREEN_FEILD_HIGH:GREEN_FEILD_LOW] <= green_count;
                    cmd_data[BLUE_FEILD_HIGH:BLUE_FEILD_LOW] <= blue_count;
                    
                    cpu_data_we <= 1'b1;
                end
            endcase
        end
    end
    assign cpu_write_data = cmd_data;
    
    // vram_disp_count の処理
    always @(posedge clk_vga) begin
        if (reset_vga)
            vram_disp_count <= 14'd0;
        else
            if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) begin
                if (vram_disp_count>14'd12287)
                    vram_disp_count <= 14'd0;
                else
                    vram_disp_count <= vram_disp_count + 14'd0;
            end
    end
            
    // キャラクタのカウンタ
    always @(posedge clk_vga) begin
        if (reset_vga)
            char_code_count <= 8'h30;
        else begin
            if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) begin
                if (char_code_count==8'h39) // 9
                    char_code_count <= 8'h41; // A
                else if (char_code_count==8'h5A) // Z
                    char_code_count <= 8'h61; // a
                else if (char_code_count==8'h7A) // z
                    char_code_count <= 8'h30; // 0
                else
                    char_code_count <= char_code_count + 8'd1;
            end
        end
    end
    
    // Red のカウント
    always @(posedge clk_vga) begin
        if (reset_vga)
            red_count <= {RED_FEILD_WIDTH{1'b1}};
        else
            if (cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop)
                red_count <= red_count - `RED_FEILD_WIDTH'd1;
    end
    
    // Green のカウント
    always @(posedge clk_vga) begin
        if (reset_vga)
            green_count <= {GREEN_FEILD_WIDTH{1'b1}};
        else
            if ((cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) && red_count==`RED_FEILD_WIDTH'd0) // Redが0の時に-1
                green_count <= green_count - `GREEN_FEILD_WIDTH'd1;
    end
    
    // Blue のカウント
    always @(posedge clk_vga) begin
        if (reset_vga)
            blue_count <= {BLUE_FEILD_WIDTH{1'b1}};
        else
            if ((cs_char==CGC_cmd8_set || cs_char==CGC_cmd0_loop) && green_count==`GREEN_FEILD_WIDTH'd0) // Greenが0の時に-1
                blue_count <= blue_count - `BLUE_FEILD_WIDTH'd1;
    end
    
endmodule


なお、まだシミュレーションしていないので、変更する可能性があります。(というか、絶対に変更になるでしょう?)

(2010/02/05:追記)
上のChar_Draw_for_Test.vを書き換えました。ブロック文とノンブロック文が混在していました。どうもRubyを書いていてVerilogを書くと混在になってしまいます。。。

(2010/02/07:追記)
Command_Status_Define.vhの各領域のビット幅を下のように修正しました。

// 各領域のビット幅
`define CHAR_CODE_UPPER_WIDTH 8
`define CHAR_CODE_LOWER_WIDTH 8
`define RED_FEILD_WIDTH 4
`define GREEN_FEILD_WIDTH 4
`define BLUE_FEILD_WIDTH 4
`define MAGNIFICATION_WIDTH 5
`define VRAM_START_ADDRESS_WIDTH 32
`define FIFO_COUNT_WIDTH 5
parameter RED_FEILD_WIDTH = `RED_FEILD_WIDTH;
parameter GREEN_FEILD_WIDTH = `GREEN_FEILD_WIDTH;
parameter BLUE_FEILD_WIDTH = `BLUE_FEILD_WIDTH;


  1. 2010年02月03日 06:14 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:11

キャラクタ描画テスト回路の構成

頑張って作ってきたキャラクタ描画テスト回路もだいぶ出来てきた。今はトップモジュールを作っている。
ここで、キャラクタ描画テスト回路の構成図を作ったので、下に示す。
Char_Draw_Test_1_100201.png

以前との違いは、CPUがキャラクタを書きまくるステートマシンに変わったことだ。これで一旦、テストしてみることにする。白い四角の中は、矢印元のファイルの内部のVerilogファイル構成を示している。現状では、トップモジュールのChar_Draw_Test_Top.v 以外は書けている。トップモジュールを書いて、テストベンチを書けばシミュレーションをすることができる。テストベンチは、クロックを生成して、リセットの処理、DDR2 SDRAMモデルとの接続程度でかけるはず。やっとゴールが近くなってきたが、全くコンパイルしていないので、エラーがぼろぼろ出そうだ。

X-festでSecureIPをシミュレーションするのにISimが重要だとわかったので、後でもう少し使ってみたいと思っている。
  1. 2010年02月01日 06:08 |
  2. VGAコントローラ
  3. | トラックバック:0
  4. | コメント:0