FPGAの部屋 2012年02月
FC2ブログ

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

FPGAの部屋

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

2012/02/29の日記

今日は2月29日で、今年はうるう年です。うるう年には夏季オリンピックが開催されますが、今年はロンドンオリンピックですね。楽しみです。

さて、CDC_axi_slave.vhd のシンタックス・チェックは終了しました。次は、AXIバスのマスタの代わりになるテストベンチをVerilogで書いています。ツイッターで呟きながら書いています。下にツイッターのつぶやきの抜粋を書いておきます。最初のは、Arduinoのクランプ・センサによる電流測定シールドの話題です。次が、AXIバスのスレーブ・モジュールのシミュレーション用テストベンチのつぶやきです。

galileo7のWattmeter2の平均値と実効値を評価した。平均値はシリコンブリッジのロス?があり、低い電流では特に誤差が大きい。ただし、10Aの出力電圧を見るとリニアであれば50Aくらいまで測れそう。 http://ow.ly/9kANV

実効値は低い電流から10Aぐらいまで誤差が本当に少なく(クランプメーターと比べて)測ることができるみたいだ。ただし、出力は交流をサンプリングしているせいもあり、付いている抵抗だと15Aがmaxっぽい。

抵抗を110Ωに下げて、(元は330Ω)スケッチをそれなりに変更すると、やはり50Aくらいまで測れそうな波形になる。低い電流も結構行けそうだ。クランプセンサのデータシートを調べて、これで行ければ、これで行こうと思う。

Arduinoのシールドのお話でした。

Digilentのdigilentライブラリが面倒なので、workライブラリに修正してしまった。

さて、AXIバス・スレーブはインターコネクトを通して、マスタにつながるが、テストベンチとして仮マスタをtaskで作って、スレーブ回路をテストする。

完全にtaskで作ると、トランザクションをオーバラップできない(実は書けるのだろうか?)ので、always文と組み合わせて構築中。


  1. 2012年02月29日 05:24 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:2

近況報告(2012/02/28)

キャラクタ・ディスプレイ・コントローラのAXI4スレーブ版をVHDLで書いてましたが、書き上がりました。VHDLで556行です。まだ全くエラーチェックしていません。
このまま、XPSに入れてもエラー出まくりだと思うので、Project Navigator のプロジェクトを作成してバグ出ししようと思っています。
その際に、AXI4バスの簡単なバス・ファンクション・モデルをVerilog(たぶん、VHDLでも良いのですが。。。)で書いて検証してみようと思っています。
本当は、VHDL, Verilog, SystemVerilog 混在可能なシミュレータでDPI-Cで書ければ良いのでしょうが、それも望めないので、Verilogでテストベンチを書こうと思います。
  1. 2012年02月28日 05:49 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

てんくうらぁーめんを食べてきました

日曜日にラーメンを食べてきました。日曜日に食べてきたので、日曜日の日付にしておきます。あしからず。。。
常陽リビングという情報誌に、ラーメン総選挙というのが載ってまして、それにつられて家族でラーメンを食べに行こうという話で盛り上がりました。どうしても食べに行こうということで、麺処てんくうのてんくうらぁーめん (750円) を食べてきました。てんくうらぁーめんは、とんこつ醤油に、煮干のだしが強力に効いています。麺を食べている時は良いですが、スープを飲むと塩辛いです。少し煮干も効きすぎているような。。。美味しかったのですが、いまいちかな???
tenkuu_ramen_120226.jpg

上の写真で、海苔に隠れていますが、煮玉子はトッピングを頼みました。本当は半分2個で1個分ついてきますが、うちの奥さんと半分にしました。

餃子も頼んだのですが、生姜が効いていて、肉汁たっぷり。美味しかったです。これはうまかった。餃子、お勧めです。

今度、食べに行きたいのは、麺や 小五郎の白味噌ラーメンだそうです。
  1. 2012年02月26日 21:46 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする2(Pcoreテンプレート生成)

ar37425のAXI4 Masterサンプルを試す1(AXI_Master IPの登録、接続)”で作成したプロジェクトをコピーして、キャラクタ・ディスプレイ・コントローラのAXI4スレーブ・デバイスを作成することにした。

1.最初に、Add IPしたaxi_master_0 をDelete Instance した。
CDC_axi_slave_1_120225.png

2.Atlys_XPS_CDC_SVGA_134\pcores フォルダで、axi_slave_v1_00_a フォルダをコピーして、CDC_axi_slave_v1_00_a と名前を変更した。
CDC_axi_slave_2_120225.png

3.Atlys_XPS_CDC_SVGA_134\pcores\CDC_axi_slave_v1_00_a\data の下のファイル名を変更した。

4.CDC_axi_slave_v2_1_0.mpd の 46行目の BEGIN axi_slave を BEGIN CDC_axi_slave に変更した。

4A.CDC_axi_slave_v2_1_0.mpd の 52,53行目を以下のように変更した。

OPTION DESC = CDC_AXI Slave
OPTION LONG_DESC = CDC_AXI Slave


5.CDC_axi_slave_v2_1_0.pao の 50行目の lib axi_slave_v1_00_a axi_slave.vhd vhdl を lib CDC_axi_slave_v1_00_a CDC_axi_slave.vhd vhdl に変更した。

6.Atlys_XPS_CDC_SVGA_134\pcores\CDC_axi_slave_v1_00_a\hdl\vhdl の axi_slave.vhd を CDC_axi_slave.vhd に変更して、ファイルの中の axi_slave も CDC_axi_slave に変更した。

7.この状態で、XPSのPoject メニューからRescan User Repositoriesを選択し、リポジトリを更新した。

8.IP CatalogウインドウのProject Local PCores のUSER の下に、CDC_AXI Slaveが入った。
CDC_axi_slave_3_120225.png

*これで、IPコア名を変えて、Pcoreとして生成する目処が付いた。ここから、HDLファイルを追加して、CDC_axi_slave.vhd や.mpd, .paoファイルを修正する。現在修正中だ。
  1. 2012年02月25日 12:18 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:6

キャラクタ・ディスプレイ・コントローラをAXI4スレーブにする1(仕様の検討)

キャラクタ・ディスプレイ・コントローラの仕様の変更”で作ったキャラクタ・ディスプレイ・コントローラをAXI4スレーブ・デバイスとして、MicroBlaze のシステムに接続しようと思う。つまり、AXI4バスのスレーブ・デバイス用のラッパーを作ろうと思っている。今回は仕様の検討を行う。

・キャラクタ・ディスプレイ・コントローラの使用できるポートは1つだけだ。AXI4バスはWrite, Read それぞれ独立にアクセスされる可能性があるが、1度に実行できるのはどちらかの転送となる。よって、アービタを作ってラウンドロビンでアービトレーションを行う。(ただし、MicroBlaze では、X1倍動作なので、IOバッファ(あるとすれば?)に溜まったRead, Writeが同時に発行されることはないと思われる)(追加:やはり、同じクロックでARVALIDとAWVALIDがアサートされる確率は少ないと思うので、Write優先ということにする)

・オーバーラップしてRead 及び Write 要求が来る可能性があるが、現在処理中のトランザクションがあったら、AWREADY または、ARREADYを0にしておいて要求を受け付けない。

・AXI4バスのビット幅は32ビット幅とする。その内の下16ビットだけをキャラクタ・ディスプレイ・コントローラのデータとして使用する。上の16ビットは、MicroBlaze からのRead時には0を返す。Writeは書き捨てとする。

・基本的に32ビット幅のアクセスを考えている。つまり、ソフトウェアではunsigned int かint でのRead, Writeとする。

・AXI4バスからのWrite はそのままキャラクタ・ディスプレイ・コントローラのバスへのWriteとする。Waitしても、1クロックごとにリアルタイムに書き込みができるからだ。

・AXI4バスからのRead は、分散RAMによるFWFTのFIFOを間に挟む。BlockRAMからのReadは1クロック遅延するため、AXI4バス・マスタ・デバイスからのRREAYがディアサートされて、ReadがWaitされた時にキャラクタ・ディスプレイ・コントローラ側もアドレスを戻すために1クロックWaitする必要があるからだ。

・上記の機能を、AXIバスのクロックに同期して、キャラクタ・ディスプレイ・コントローラが行えるようにプロセッサ側の動作クロックと描画側の動作クロックを分離する。

AXI4バス・サンプルのシミュレーション結果は、”ar37425のAXI4 Masterサンプルを試す6(シミュレーション3)”を参照のこと。

(2012/02/25:追加)
下に概念図を追加する。
CDC_axi_slave_4_120226.png

上の図で、制御部のWrite Transaction State Machine とRead Transaction State Machine は協調動作して、一方がアクティブの場合は、片方は動作しない。同時にアクティブになろうとした場合にはWriteの方が優先される。
データパスではWriteは直結だが、Write Transaction State Machine がアクティブの場合のみ直結される。その以外はWREADYはディアサートされる。
ReadはFIFOが間に入る。このFIFOは分散RAMを使用した16深度、32ビット幅のFIFOだ。これにより、Waitが入るとバーストすることができない(というか1つお休みする必要がある)BlockRAMのReadをバースト可能にする。
  1. 2012年02月25日 04:27 |
  2. AXI4 Slave IPの作製
  3. | トラックバック:0
  4. | コメント:0

キャラクタ・ディスプレイ・コントローラの仕様の変更

DVI、HDMIの勉強5(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編2)”で完成したキャラクタ・ディスプレイ・コントローラをAXI4スレーブとして、XPSプロジェクトに加える前に、仕様の変更をすることにした。

AXI4バスはデータ幅32ビットとして実装するので、現在のキャラクタコード7ビット、R, G, Bのカラー情報1ビットずつ、計3ビットの合計10ビットでは、色ももっと出るのにもったいない。(”キャラクタ・ディスプレイ・コントローラの構成”参照)
これを16ビットに変更する。赤 (R) の色情報は 15~13ビット目の3ビット、緑 (R) の色情報は 12~10ビット目の3ビット、青 (B) の色情報は 9~7ビット目の3ビットとする。6~0ビット目はキャラクタコードとする。
これで16ビットになったので、32ビット幅に設定したAXI4バスのデータに2つのキャラクタがちょうど収まるようになる。
修正してインプリメントを行った。表示結果を下に示す。
DVI_HDMI_14_120224.jpg

全体に輝度が下がって、いろいろな色が表示されるようになった。

  1. 2012年02月24日 05:55 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強7(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編2)

”DVI、HDMIの勉強4(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編1)”の続き。

今回は、SVGA(800x600)とXGA(1024x768) 解像度が表示できるかどうかを確かめてみた。おまけでSXGA(1280x1024)もやってみた。

・SVGA解像度
まずは、SVGAから。
修正部分を示す。画像のパラメータを記述してあるdisp_timing_parameters.vh をSVGA用に変更した。

// SVGA 解像度
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;


次に、キャラクタを表示するCharDispCtrlerTest.vhd のアドレスをSVGA用に増やした。

    process(clk) begin -- キャラクタコードを+1して表示
        if clk'event and clk='1' then
            if reset='1' then
                processor_addr <= (others => '0');
            else
                if ena='1' then
                    -- if processor_addr=CONV_STD_LOGIC_VECTOR(4799, 13) then -- 終了(VGA)
                    if processor_addr=CONV_STD_LOGIC_VECTOR(7499, 13) then -- 終了(SVGA)
                        processor_addr <= (others => '0');
                    else
                        processor_addr <= processor_addr + 1;
                    end if;
                end if;
            end if;
        end if;
    end process;
    


最後に、pixclk_gen のCLK_OUT2 を40MHz に変更した。
これでインプリメントしたらSVGA解像度で動作した。
DVI_HDMI_11_120223.jpg

・XGA解像度
次に、XGAでやってみた。
修正部分を示す。画像のパラメータを記述してあるdisp_timing_parameters.vh をXGA用に変更した。

parameter H_ACTIVE_VIDEO= 1024;
parameter H_FRONT_PORCH = 24;
parameter H_SYNC_PULSE = 136;
parameter H_BACK_PORCH = 160;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

parameter V_ACTIVE_VIDEO = 768;
parameter V_FRONT_PORCH = 2;
parameter V_SYNC_PULSE = 6;
parameter V_BACK_PORCH = 29;
parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;


キャラクタを表示するCharDispCtrlerTest.vhd のアドレスをXGA用に増やそうとしたが、足りなかった。仕方がないので、最大の8191に変更した。XGA用には12,287に設定したいところだ。これで画面の下は、フレーム・バッファが足りずにミラー・イメージが出てしまう。

    process(clk) begin -- キャラクタコードを+1して表示
        if clk'event and clk='1' then
            if reset='1' then
                processor_addr <= (others => '0');
            else
                if ena='1' then
                    -- if processor_addr=CONV_STD_LOGIC_VECTOR(4799, 13) then -- 終了(VGA)
                    -- if processor_addr=CONV_STD_LOGIC_VECTOR(7499, 13) then -- 終了(SVGA)
                    if processor_addr=CONV_STD_LOGIC_VECTOR(8191, 13) then -- 足りないが終了(XGA)
                        processor_addr <= (others => '0');
                    else
                        processor_addr <= processor_addr + 1;
                    end if;
                end if;
            end if;
        end if;
    end process;


pixclk_gen のCLK_OUT2 を65MHz に変更した。この変更により、CharDispCtrlerTest_HDMI.vhdのdvi_disp.vhd のgeneric map の値を変更した。65MHzを20倍すると1000MHzを超えてしまうので、PLL_CLKFBOUT_MULTを10倍に変更した。それに応じて他のパラメータも変更した。

    dvi_disp_inst : dvi_disp generic map (

        PLL_CLKFBOUT_MULT    => 10,    -- XGA
        PLL_CLKIN_PERIOD    => 15.4,
        PLL_CLKOUT0_DIVIDE    => 1,
        PLL_CLKOUT1_DIVIDE    => 10,
        PLL_CLKOUT2_DIVIDE    => 5
    ) port map (


これでインプリメントしたらXGA解像度で動作した。
DVI_HDMI_12_120223.jpg


SVGAでもXGAでも問題なく表示できるようだ。
これでHDMIコネクタからDVI出力することができたので、SVGA解像度に戻して、キャラクタ・ディスプレイ・コントローラとして、AXI4バスにラッパーを作って接続してみようと思う。

(追加)
・SXGA解像度
SXGAはピクセルクロックが108MHzで10倍すると1080MHzなので、Spartan-6の-2スピードグレードだと、インプリメントでエラーになるが、-3スピードグレードに設定すると、インプリメントが通る。-2スピードグレードのFPGAを-3スピードグレードに偽って設定しているため、その他のタイミングでミスる可能性もあるが、やってみた。

画像のパラメータを記述してあるdisp_timing_parameters.vh をSXGA用に変更した。

// SXGA 解像度
parameter H_ACTIVE_VIDEO= 1280;
parameter H_FRONT_PORCH = 48;
parameter H_SYNC_PULSE = 112;
parameter H_BACK_PORCH = 248;
parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

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


キャラクタを表示するCharDispCtrlerTest.vhd のアドレスはXGAと同一だ。

CharDispCtrlerTest_HDMI.vhdのdvi_disp.vhd のgeneric map の値はXGAと同様に、PLL_CLKFBOUT_MULTを10倍に変更して、それに応じて他のパラメータも変更した。

pixclk_gen のCLK_OUT2 を108MHz に変更した。

インプリメントすると動作した。2時間くらい連続運転しているが大丈夫のようだ。案外行けるのかも?でも、ボード個体によってはダメかも知れないし、もっとリソースを使ってくるとだめになるかもしれない。いずれにせよリスキーだ。
下に、SXGA解像度の画面を貼っておく。
DVI_HDMI_13_120223.jpg

SXGAになると、本当に字が細かいですね。見を凝らさないと見えません。(老眼です)

  1. 2012年02月23日 04:49 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強6(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編1)

今回は、VHDLでキャラクタ・ディスプレイ・コントローラをAtlysボードのHDMIコネクタからDVI信号で出力してみた。VmodCAMのサンプルのVmodCAM_Ref_VGA Demo_13.zip を参照している。

VmodCAM_Ref_VGA Demo_13.zipを参照して、dvi_disp.vhd を作成して、VmodCAM_Ref_VGA Demo_13.zipの DVITransmittter.vhd, TMDSEncoder.vhd, SerializerN_1.vhd, Video.vhd を使用した。
CharDispCtler.v 以下はVerilog を使用している。VHDLも出来ているし、動作も確認してあるのだが、都合があるので公表していない。
下にProject Navigator の画面を示す。
DVI_HDMI_6_120221.png

インプリメントが成功したので、Atlysボードにダウンロードして試してみたところ、問題なく動作した。
DVI_HDMI_5_120218.jpg

まずは、dvi_disp.vhd を下に貼る。このVHDLファイルを作成するにあたっては、VmodCAM_Ref_VGA Demo_13.zipを参照させて頂いてるが、自分で作りなおした。

-- dvi_disp.vhd
-- Verilog版とは違ってDigilent 社のDVITransmitter.vhd を使用する

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity dvi_disp is
    generic (
        PLL_CLKFBOUT_MULT : integer := 20;    -- VGA解像度 PLL VCO Freq 400MHz ~ 1000MHz
        PLL_CLKIN_PERIOD : real := 40.0;    -- VGA ピクセルクロック周期
        PLL_CLKOUT0_DIVIDE : integer := 2;    -- ピクセルクロックX10
        PLL_CLKOUT1_DIVIDE : integer := 20;    -- ピクセルクロック
        PLL_CLKOUT2_DIVIDE : integer := 10    -- ピクセルクロックX2
    );
    port (
        pixclk    :    in    std_logic;            -- pixel clock
        reset_in :    in     std_logic;            -- active high
        red_in :    in    std_logic_vector(7 downto 0);    -- RED入力
        green_in :    in    std_logic_vector(7 downto 0);    -- GREEN入力
        blue_in :    in    std_logic_vector(7 downto 0);    -- BLUE入力
        hsync :        in    std_logic;
        vsync :        in    std_logic;
        display_enable :    in std_logic;                -- 表示が有効
        TMDS_tx_clk_p :    out    std_logic;                    -- Clock
        TMDS_tx_clk_n :    out    std_logic;
        TMDS_tx_2_G_p :    out    std_logic;                    -- Green
        TMDS_tx_2_G_n :    out    std_logic;
        TMDS_tx_1_R_p :    out    std_logic;                    -- Red
        TMDS_tx_1_R_n :    out    std_logic;
        TMDS_tx_0_B_p :    out    std_logic;                    -- Blue
        TMDS_tx_0_B_n :    out    std_logic
    );
end dvi_disp;

architecture RTL of dvi_disp is
component PLL_BASE
  generic (
     BANDWIDTH : string := "OPTIMIZED";
     CLKFBOUT_MULT : integer := 1;
     CLKFBOUT_PHASE : real := 0.0;
     CLKIN_PERIOD : real := 0.000;
     CLKOUT0_DIVIDE : integer := 1;
     CLKOUT0_DUTY_CYCLE : real := 0.5;
     CLKOUT0_PHASE : real := 0.0;
     CLKOUT1_DIVIDE : integer := 1;
     CLKOUT1_DUTY_CYCLE : real := 0.5;
     CLKOUT1_PHASE : real := 0.0;
     CLKOUT2_DIVIDE : integer := 1;
     CLKOUT2_DUTY_CYCLE : real := 0.5;
     CLKOUT2_PHASE : real := 0.0;
     CLKOUT3_DIVIDE : integer := 1;
     CLKOUT3_DUTY_CYCLE : real := 0.5;
     CLKOUT3_PHASE : real := 0.0;
     CLKOUT4_DIVIDE : integer := 1;
     CLKOUT4_DUTY_CYCLE : real := 0.5;
     CLKOUT4_PHASE : real := 0.0;
     CLKOUT5_DIVIDE : integer := 1;
     CLKOUT5_DUTY_CYCLE : real := 0.5;
     CLKOUT5_PHASE : real := 0.0;
     CLK_FEEDBACK : string := "CLKFBOUT";
     COMPENSATION : string := "SYSTEM_SYNCHRONOUS";
     DIVCLK_DIVIDE : integer := 1;
     REF_JITTER : real := 0.100;
     RESET_ON_LOSS_OF_LOCK : boolean := FALSE
  );
  port (
     CLKFBOUT : out std_ulogic;
     CLKOUT0 : out std_ulogic;
     CLKOUT1 : out std_ulogic;
     CLKOUT2 : out std_ulogic;
     CLKOUT3 : out std_ulogic;
     CLKOUT4 : out std_ulogic;
     CLKOUT5 : out std_ulogic;
     LOCKED : out std_ulogic;
     CLKFBIN : in std_ulogic;
     CLKIN : in std_ulogic;
     RST : in std_ulogic
  );
end component;

component BUFPLL
  generic (
     DIVIDE : integer := 1;
     ENABLE_SYNC : boolean := TRUE
  );
  port (
     IOCLK : out std_ulogic;
     LOCK : out std_ulogic;
     SERDESSTROBE : out std_ulogic;
     GCLK : in std_ulogic;
     LOCKED : in std_ulogic;
     PLLIN : in std_ulogic
  );
end component;

component DVITransmitter
    port ( 
        RED_I : in  STD_LOGIC_VECTOR (7 downto 0);
        GREEN_I : in  STD_LOGIC_VECTOR (7 downto 0);
        BLUE_I : in  STD_LOGIC_VECTOR (7 downto 0);
        HS_I : in  STD_LOGIC;
        VS_I : in  STD_LOGIC;
        VDE_I : in  STD_LOGIC;
        PCLK_I : in  STD_LOGIC;
        PCLK_X2_I : in  STD_LOGIC;
        SERCLK_I : in  STD_LOGIC;
        SERSTB_I : in  STD_LOGIC;
        TMDS_TX_CLK_P : out  STD_LOGIC;
        TMDS_TX_CLK_N : out  STD_LOGIC;
        TMDS_TX_2_P : out  STD_LOGIC;
        TMDS_TX_2_N : out  STD_LOGIC;
        TMDS_TX_1_P : out  STD_LOGIC;
        TMDS_TX_1_N : out  STD_LOGIC;
        TMDS_TX_0_P : out  STD_LOGIC;
        TMDS_TX_0_N : out  STD_LOGIC
    );
end component;

component BUFG
  port (
     O : out std_ulogic;
     I : in std_ulogic
  );
end component;

signal pll_clkfg : std_logic;
signal pixel_clk, pixel_clkx10, pixel_clkx2 : std_logic;
signal pll_locked : std_logic;
signal pclk_bufg, pclkx2_bufg : std_logic;
signal bufpll_locked : std_logic;
signal serdes_strobe : std_logic;
signal pixel_clkio : std_logic;

begin
    PLL_BASE_PIXEL : PLL_BASE generic map (
        CLKFBOUT_MULT    => PLL_CLKFBOUT_MULT,
        COMPENSATION    => "INTERNAL",
        CLKIN_PERIOD    => PLL_CLKIN_PERIOD,
        CLKOUT0_DIVIDE    => PLL_CLKOUT0_DIVIDE,
        CLKOUT1_DIVIDE    => PLL_CLKOUT1_DIVIDE,
        CLKOUT2_DIVIDE    => PLL_CLKOUT2_DIVIDE
    ) port map (
        CLKFBOUT    => pll_clkfg,
        CLKOUT0        => pixel_clkx10,
        CLKOUT1        => pixel_clk,
        CLKOUT2        => pixel_clkx2,
        LOCKED        => pll_locked,
        CLKFBIN        => pll_clkfg,
        CLKIN        => pixclk,
        RST            => reset_in
    );
    
    BUFG_pixel_clk : BUFG port map (
        O    => pclk_bufg,
        I    => pixel_clk
    );
    
    BUFG_pixel_clkx2 : BUFG port map (
        O    => pclkx2_bufg,
        I    => pixel_clkx2
    );
    
    BUFPLL_pixel : BUFPLL generic map (
        DIVIDE    => 5,
        ENABLE_SYNC    => TRUE
    ) port map (
        IOCLK    => pixel_clkio,
        LOCK    => bufpll_locked,
        SERDESSTROBE    => serdes_strobe,
        GCLK    => pclkx2_bufg,
        LOCKED    => pll_locked,
        PLLIN    => pixel_clkx10
    );
    
    DVI_TX : DVITransmitter port map (
        RED_I        => red_in,
        GREEN_I        => green_in,
        BLUE_I        => blue_in,
        HS_I        => hsync,
        VS_I        => vsync,
        VDE_I        => display_enable,
        PCLK_I        => pclk_bufg,
        PCLK_X2_I    => pclkx2_bufg,
        SERCLK_I    => pixel_clkio,
        SERSTB_I    => serdes_strobe,
        TMDS_TX_CLK_P    => TMDS_tx_clk_p,
        TMDS_TX_CLK_N    => TMDS_tx_clk_n,
        TMDS_TX_2_P        => TMDS_tx_2_G_p,
        TMDS_TX_2_N        => TMDS_tx_2_G_n,
        TMDS_TX_1_P        => TMDS_tx_1_R_p,
        TMDS_TX_1_N        => TMDS_tx_1_R_n,
        TMDS_TX_0_P        => TMDS_tx_0_B_p,
        TMDS_TX_0_N        => TMDS_tx_0_B_n
    );
end RTL;


pixclk(ピクセルクロック)をもらって、PLL_BASEで、1倍、2倍、10倍のクロックを作り、2倍のクロックをBUFPLLに入れて、SERDES用のStrobeを作っている。OSERDES2は5ビットをシリアライズする。5ビットなので、Master-Slaveモードで使用している。10倍のクロックでシリアルデータを出し、2倍のクロックで動作させて、つまり10ビットをシリアライズしている。なぜ10ビットかというと、8B10Bエンコーダを使用しているからだ。
(参考文献:Spartan-6 FPGA クロック リソース ユーザー ガイド v1.3 (日本語版)(PDF, ver 1.6, 3.55 MB )、
        Spartan-6 FPGA SelectIO リソース ユーザー ガイド v1.3 (日本語版)(PDF, ver 1.4, 3.34 MB ))

次に、CharDispCtrlerTest.vhd を下に貼っておく。

-- CharDispCtrlerTest.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;

entity CharDispCtrlerTest is
    generic(
        ENABLE_COUNT    :    integer    :=    250000
    );
    port (
        clk            :    in    std_logic;
        reset        :    in    std_logic;
        VGA_RED        :    out    std_logic;
        VGA_GREEN    :    out    std_logic;
        VGA_BLUE    :    out    std_logic;
        VGA_HSYNC    :    out    std_logic;
        VGA_VSYNC    :    out    std_logic;
        display_enable : out std_logic
    );
end CharDispCtrlerTest;

architecture RTL of CharDispCtrlerTest is
component CharDispCtrler
    port(
        clk : in std_logic;
        reset : in std_logic;
        
        processor_addr : in std_logic_vector(12 downto 0);
        processor_din : in std_logic_vector(9 downto 0);
        processor_dout : out std_logic_vector(9 downto 0);
        processor_we : in std_logic;
        
        VGA_RED : out std_logic;
        VGA_GREEN : out std_logic;
        VGA_BLUE : out std_logic;
        VGA_HSYNC : out std_logic;
        VGA_VSYNC : out std_logic;
        display_enable : out std_logic
    );
end component;

signal processor_addr    :    std_logic_vector(12 downto 0);
signal processor_din    :     std_logic_vector(9 downto 0);
signal processor_dout    :    std_logic_vector(9 downto 0);
signal processor_we        :    std_logic;
signal count    :     std_logic_vector(22 downto 0);
signal ena        :    std_logic;
signal char_code    :    std_logic_vector(6 downto 0);
signal color_data    :    std_logic_vector(2 downto 0);

begin
    CharDispCtrler_inst : CharDispCtrler port map(
        clk        => clk,
        reset    => reset,
        processor_addr    => processor_addr,
        processor_din    => processor_din,
        processor_dout    => processor_dout,
        processor_we    => processor_we,
        VGA_RED            => VGA_RED,
        VGA_GREEN        => VGA_GREEN,
        VGA_BLUE        => VGA_BLUE,
        VGA_HSYNC        => VGA_HSYNC,
        VGA_VSYNC        => VGA_VSYNC,
        display_enable    => display_enable
    );
    
    process(clk) begin
        if clk'event and clk='1' then
            if reset='1' then
                count <= (others => '0');
                ena <= '0';
            else
                if count = ENABLE_COUNT then
                    count <= (others => '0');
                    ena <= '1';
                else
                    count <= count + 1;
                    ena <= '0';
                end if;
            end if;
        end if;
    end process;
    
    process(clk) begin -- キャラクタコードを+1して表示
        if clk'event and clk='1' then
            if reset='1' then
                processor_addr <= (others => '0');
            else
                if ena='1' then
                    if processor_addr=CONV_STD_LOGIC_VECTOR(4799, 13) then -- 終了
                        processor_addr <= (others => '0');
                    else
                        processor_addr <= processor_addr + 1;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    process(clk) begin -- キャラクタコードを+1して表示
        if clk'event and clk='1' then
            if reset='1' then
                char_code <= "0100001"; -- キャラクタの!
            else
                if ena='1' then
                    if char_code="1111110" then -- キャラクタの~
                        char_code <= "0100001"; -- キャラクタの!
                    else
                        char_code <= char_code + 1;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    process(clk) begin -- 色を+1しながら表示
        if clk'event and clk='1' then
            if reset='1' then
                color_data <= "001";
            else
                if ena='1' then
                    if color_data="111" then
                        color_data <= "001"; -- 0 は非表示
                    else
                        color_data <= color_data + 1;
                    end if;
                end if;
            end if;
        end if;
    end process;
    
    processor_din <= color_data & char_code;
    processor_we <= ena;
    
end RTL;


CharDispCtrlerTest_HDMI.vhd を貼っておく。

-- CharDispCtrlerTest_HDMI.vhd

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
library digilent;
use digilent.Video.ALL;

entity CharDispCtrlerTest_HDMI is
    generic(
        ENABLE_COUNT    :    integer    :=    250000
    );
    port(
        sysclk :    in    std_logic;
        reset_sw :    in    std_logic;
        TMDS_tx_clk_p :    out    std_logic;    -- Clock
        TMDS_tx_clk_n :    out    std_logic;
        TMDS_tx_2_G_p :    out    std_logic;    -- Green
        TMDS_tx_2_G_n :    out    std_logic;
        TMDS_tx_1_R_p :    out    std_logic;    -- Red
        TMDS_tx_1_R_n :    out    std_logic;
        TMDS_tx_0_B_p :    out    std_logic;    -- Blue
        TMDS_tx_0_B_n :    out    std_logic
    );
end CharDispCtrlerTest_HDMI;

architecture RTL of CharDispCtrlerTest_HDMI is
component pixclk_gen
    port (-- Clock in ports
        CLK_IN1           : in     std_logic;
        -- Clock out ports
        CLK_OUT1          : out    std_logic;
        CLK_OUT2          : out    std_logic;
        -- Status and control signals
        RESET             : in     std_logic;
        LOCKED            : out    std_logic
    );
end component;

component CharDispCtrlerTest
    generic(
        ENABLE_COUNT    :    integer    :=    250000
    );
    port (
        clk            :    in    std_logic;
        reset        :    in    std_logic;
        VGA_RED        :    out    std_logic;
        VGA_GREEN    :    out    std_logic;
        VGA_BLUE    :    out    std_logic;
        VGA_HSYNC    :    out    std_logic;
        VGA_VSYNC    :    out    std_logic;
        display_enable : out std_logic
    );
end component;

component dvi_disp 
    generic (
        PLL_CLKFBOUT_MULT : integer := 20;    -- VGA解像度 PLL VCO Freq 400MHz ~ 1000MHz
        PLL_CLKIN_PERIOD : real := 40.0;    -- VGA ピクセルクロック周期
        PLL_CLKOUT0_DIVIDE : integer := 2;    -- ピクセルクロックX10
        PLL_CLKOUT1_DIVIDE : integer := 20;    -- ピクセルクロック
        PLL_CLKOUT2_DIVIDE : integer := 10    -- ピクセルクロックX2
    );
    port (
        pixclk    :    in    std_logic;            -- pixel clock
        reset_in :    in     std_logic;            -- active high
        red_in :    in    std_logic_vector(7 downto 0);    -- RED入力
        green_in :    in    std_logic_vector(7 downto 0);    -- GREEN入力
        blue_in :    in    std_logic_vector(7 downto 0);    -- BLUE入力
        hsync :        in    std_logic;
        vsync :        in    std_logic;
        display_enable :    in std_logic;                -- 表示が有効
        TMDS_tx_clk_p :    out    std_logic;                    -- Clock
        TMDS_tx_clk_n :    out    std_logic;
        TMDS_tx_2_G_p :    out    std_logic;                    -- Green
        TMDS_tx_2_G_n :    out    std_logic;
        TMDS_tx_1_R_p :    out    std_logic;                    -- Red
        TMDS_tx_1_R_n :    out    std_logic;
        TMDS_tx_0_B_p :    out    std_logic;                    -- Blue
        TMDS_tx_0_B_n :    out    std_logic
    );
end component;

signal clk_100 : std_logic;
signal pixclk : std_logic;
signal reset : std_logic;
signal locked : std_logic;
signal vga_red, vga_green, vga_blue : std_logic;
signal vga_hsync, vga_vsync : std_logic;
signal display_enable : std_logic;
signal vga_r8, vga_g8, vga_b8 : std_logic_vector(7 downto 0);

begin
    pixclk_gen_inst : pixclk_gen port map (
        CLK_IN1        => sysclk,
        CLK_OUT1    => clk_100,
        CLK_OUT2    => pixclk,
        RESET        => reset_sw,
        LOCKED        => locked
    );
    reset <= not locked;
    
    CharDispCtrlerTest_inst : CharDispCtrlerTest generic map (
        ENABLE_COUNT => ENABLE_COUNT
    ) port map (
        clk            => pixclk,
        reset        => reset,
        VGA_RED        => vga_red,
        VGA_GREEN    => vga_green,
        VGA_BLUE    => vga_blue,
        VGA_HSYNC    => vga_hsync,
        VGA_VSYNC    => vga_vsync,
        display_enable    => display_enable
    );
    vga_r8 <= x"FF" when VGA_RED='1' else x"00";
    vga_g8 <= x"FF" when VGA_GREEN='1' else x"00";
    vga_b8 <= x"FF" when VGA_BLUE='1' else x"00";
    
    -- VGA解像度 PLL VCO Freq=400MHz ~ 1000MHz なので、25MHz入力クロックだと最初に20倍する必要がある。
    dvi_disp_inst : dvi_disp generic map (
        PLL_CLKFBOUT_MULT    => 20,
        PLL_CLKIN_PERIOD    => 40.0,
        PLL_CLKOUT0_DIVIDE    => 2,
        PLL_CLKOUT1_DIVIDE    => 20,
        PLL_CLKOUT2_DIVIDE    => 10
    ) port map (
        pixclk        => pixclk,
        reset_in    => reset,
        red_in        => vga_r8,
        green_in    => vga_g8,
        blue_in        => vga_b8,
        hsync        => vga_hsync,
        vsync        => vga_vsync,
        display_enable    => display_enable,
        TMDS_tx_clk_p    => TMDS_tx_clk_p,
        TMDS_tx_clk_n    => TMDS_tx_clk_n,
        TMDS_tx_2_G_p    => TMDS_tx_2_G_p,
        TMDS_tx_2_G_n    => TMDS_tx_2_G_n,
        TMDS_tx_1_R_p    => TMDS_tx_1_R_p,
        TMDS_tx_1_R_n    => TMDS_tx_1_R_n,
        TMDS_tx_0_B_p    => TMDS_tx_0_B_p,
        TMDS_tx_0_B_n    => TMDS_tx_0_B_n
    );
end RTL;


次に、CharDispCtrlerTest_HDMI.ucf を下に貼っておく。

NET "sysclk" LOC = L15;
NET "reset_sw" LOC = P3;
# Blue
NET "TMDS_tx_0_B_p" IOSTANDARD = TMDS_33;
NET "TMDS_tx_0_B_p" LOC = D8;
NET "TMDS_tx_0_B_n" IOSTANDARD = TMDS_33;
NET "TMDS_tx_0_B_n" LOC = C8;
# Red
NET "TMDS_tx_1_R_p" IOSTANDARD = TMDS_33;
NET "TMDS_tx_1_R_p" LOC = C7;
NET "TMDS_tx_1_R_n" IOSTANDARD = TMDS_33;
NET "TMDS_tx_1_R_n" LOC = A7;
# Green
NET "TMDS_tx_2_G_p" IOSTANDARD = TMDS_33;
NET "TMDS_tx_2_G_p" LOC = B8;
NET "TMDS_tx_2_G_n" IOSTANDARD = TMDS_33;
NET "TMDS_tx_2_G_n" LOC = A8;
# Clock
NET "TMDS_tx_clk_p" IOSTANDARD = TMDS_33;
NET "TMDS_tx_clk_p" LOC = B6;
NET "TMDS_tx_clk_n" IOSTANDARD = TMDS_33;
NET "TMDS_tx_clk_n" LOC = A6;

NET "sysclk" TNM_NET = "TNM_SYSCLK";
TIMESPEC TS_SYSCLK = PERIOD "TNM_SYSCLK" 100 MHz HIGH 50 % PRIORITY 0;


# PlanAhead Generated IO constraints

NET "reset_sw" IOSTANDARD = LVCMOS18;
NET "sysclk" IOSTANDARD = LVCMOS33;


プロジェクト中のpixclk_gen は100MHzのクロックを入力して、100MHzと25MHzを出力するようにClocking Wizard で作成した。
DVI_HDMI_7_120222.png

DVI_HDMI_8_120222.png

DVI_HDMI_9_120222.png

後のファイルは、”キャラクタ・ディスプレイ・コントローラのまとめ”からダウンロードすることができる。

(注)Digilent社の使用したVHDLファイルはdigilentライブラリを使用する。そのため、Project Navigator にAdd Source... で入れる時に、Library のところにdigilent と入れて、digilentライブラリを作成してVHDLファイルをプロジェクトに入れる必要があった。
DVI_HDMI_10_120222.png
  1. 2012年02月22日 04:52 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強5(キャラクタ・ディスプレイ・コントローラをDVI出力にする Verilog編2)

現在、VHDL版を作成中だが、”DVI、HDMIの勉強4(キャラクタ・ディスプレイ・コントローラをDVI出力にする Verilog編)”のポートをVHDL版に合わせて変更した。TMDS信号の配列だけで、どのポートがどの色に対応するという情報があったほうが良いと思った。

インプリメントして、動作チェックをしたら問題なく動作した。

まずは、dvi_disp.v のポートマップから下に貼っておく。

// dvi_disp.v 
// DVI表示ユニット
// 

`default_nettype none

module dvi_disp #(
    parameter PLL_CLKFBOUT_MULT    = 20,    // VGA解像度 PLL VCO Freq=400MHz ~ 1000MHz
    parameter PLL_CLKIN_PERIOD     = 40.0,    // VGA ピクセルクロック周期
    parameter PLL_CLKOUT0_DIVIDE    = 2,    // ピクセルクロックX10
    parameter PLL_CLKOUT1_DIVIDE    = 20,    // ピクセルクロック
    parameter PLL_CLKOUT2_DIVIDE    = 10)    // ピクセルクロックX2
(
    input    wire    pixclk,                // pixel clock
    input    wire    reset_in,            // active high
    input    wire    [7:0]    red_in,        // RED入力
    input    wire    [7:0]    green_in,    // GREEN入力
    input    wire    [7:0]    blue_in,    // BLUE入力
    input    wire    hsync,
    input    wire    vsync,
    input    wire    display_enable,        // 表示が有効
    output    wire    TMDS_tx_clk_p,        // Clock
    output    wire    TMDS_tx_clk_n,
    output    wire    TMDS_tx_2_G_p,        // Green
    output    wire    TMDS_tx_2_G_n,
    output    wire    TMDS_tx_1_R_p,        // Red
    output    wire    TMDS_tx_1_R_n,
    output    wire    TMDS_tx_0_B_p,        // Blue
    output    wire    TMDS_tx_0_B_n
);


次に、CharDispCtrlerTest_HDMI.v を下に示す。
PLLのVCOの動作周波数は、Spartan-6の-2デバイスでは400MHz~1000MHzであるので、25MHzを10倍しても250MHzにしかならない。よって、最低動作周波数を下回ってしまう。そのため、PLLのVCOの動作周波数は、20倍して500MHzとしている。PLLのVCOの動作周波数範囲からSpartan-6の-2デバイスではSXGA(ピクセルクロック108MHz)の出力は難しいことがわかる。10倍すると1080MHzとなり、規格を超過してしまう。Spartan-6の通常の入出力ポートを使用したDVI出力でSXGAを出力するためには、-3のスピードグレードのSpartan-6が必要となる。(参考文献:Spartan-6 FPGA データシート : DC 特性およびスイッチ特性 v3.0 (日本語版)(PDF, ver 3.0, 2.09 MB )、58ページの表52 PLL仕様(続き))

// CharDispCtrlerTest_HDMI.v
// CharDispCtrlerTest.vのHDMI用のラッパー、HDMIコネクタから出力する

`default_nettype none

module CharDispCtrlerTest_HDMI (
    input    wire    sysclk,
    input    wire    reset_sw,
    output    wire    TMDS_tx_clk_p,        // Clock
    output    wire    TMDS_tx_clk_n,
    output    wire    TMDS_tx_2_G_p,        // Green
    output    wire    TMDS_tx_2_G_n,
    output    wire    TMDS_tx_1_R_p,        // Red
    output    wire    TMDS_tx_1_R_n,
    output    wire    TMDS_tx_0_B_p,        // Blue
    output    wire    TMDS_tx_0_B_n
);
    wire clk_100;
    wire pixclk;
    wire reset;
    wire locked;
    wire vga_red, vga_green, vga_blue;
    wire vga_hsync, vga_vsync;
    wire display_enable;
    
    pixclk_gen pixclk_gen_inst
    (// Clock in ports
        .CLK_IN1(sysclk),      // IN
        // Clock out ports
        .CLK_OUT1(clk_100),     // OUT
        .CLK_OUT2(pixclk),     // OUT
        // Status and control signals
        .RESET(reset_sw),// IN
        .LOCKED(locked)      // OUT
    );
    
    assign reset = !locked;
    
    CharDispCtrlerTest CharDispCtrlerTest_inst (
        .clk(pixclk),
        .reset(reset),
        .VGA_RED(vga_red),        // 1bit
        .VGA_GREEN(vga_green),    // 1bit
        .VGA_BLUE(vga_blue),    // 1bit
        .VGA_HSYNC(vga_hsync),
        .VGA_VSYNC(vga_vsync),
        .display_enable(display_enable)
    );

    // VGA解像度 PLL VCO Freq=400MHz ~ 1000MHz なので、25MHz入力クロックだと最初に20倍する必要がある。
    dvi_disp #(
        .PLL_CLKFBOUT_MULT(20),
        .PLL_CLKIN_PERIOD(40.0),
        .PLL_CLKOUT0_DIVIDE(2),
        .PLL_CLKOUT1_DIVIDE(20),
        .PLL_CLKOUT2_DIVIDE(10))
    dvi_disp_inst (
        .pixclk(pixclk),
        .reset_in(reset),
        .red_in({8{vga_red}}),
        .green_in({8{vga_green}}),
        .blue_in({8{vga_blue}}),
        .hsync(vga_hsync),
        .vsync(vga_vsync),
        .display_enable(display_enable),
        .TMDS_tx_clk_p(TMDS_tx_clk_p),
        .TMDS_tx_clk_n(TMDS_tx_clk_n),
        .TMDS_tx_2_G_p(TMDS_tx_2_G_p),
        .TMDS_tx_2_G_n(TMDS_tx_2_G_n),
        .TMDS_tx_1_R_p(TMDS_tx_1_R_p),
        .TMDS_tx_1_R_n(TMDS_tx_1_R_n),
        .TMDS_tx_0_B_p(TMDS_tx_0_B_p),
        .TMDS_tx_0_B_n(TMDS_tx_0_B_n)
    );
endmodule    

`default_nettype wire


CharDispCtrlerTest_HDMI_tb.v を下に貼っておく。

module CharDispCtrlerTest_HDMI_tb;

    // Inputs
    reg sysclk;
    reg reset_sw;

    // Outputs
    wire    TMDS_tx_clk_p;        // Clock
    wire    TMDS_tx_clk_n;
    wire    TMDS_tx_2_G_p;        // Green
    wire    TMDS_tx_2_G_n;
    wire    TMDS_tx_1_R_p;        // Red
    wire    TMDS_tx_1_R_n;
    wire    TMDS_tx_0_B_p;        // Blue
    wire    TMDS_tx_0_B_n;

    // Instantiate the Unit Under Test (UUT)
    CharDispCtrlerTest_HDMI uut (
        .sysclk(sysclk), 
        .reset_sw(reset_sw), 
        .TMDS_tx_clk_p(TMDS_tx_clk_p),
        .TMDS_tx_clk_n(TMDS_tx_clk_n),
        .TMDS_tx_2_G_p(TMDS_tx_2_G_p),
        .TMDS_tx_2_G_n(TMDS_tx_2_G_n),
        .TMDS_tx_1_R_p(TMDS_tx_1_R_p),
        .TMDS_tx_1_R_n(TMDS_tx_1_R_n),
        .TMDS_tx_0_B_p(TMDS_tx_0_B_p),
        .TMDS_tx_0_B_n(TMDS_tx_0_B_n)
    );

    parameter PERIOD = 10;
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for clk
    begin
        #OFFSET;
        forever
        begin
            sysclk = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) sysclk = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end

    // Instantiate the Unit Under Test (UUT)
    defparam uut.CharDispCtrlerTest_inst.ENABLE_COUNT = 23'd000004; // シミュレーション

    initial begin
        // Initialize Inputs
        reset_sw = 1'b1;

        // Wait 100 ns for global reset to finish
        #100;
        reset_sw = 1'b0;
        
        // Add stimulus here
        #20000000    $stop;
    end
      
endmodule

  1. 2012年02月20日 04:49 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強4(キャラクタ・ディスプレイ・コントローラをDVI出力にする Verilog編)

DVI、HDMIの勉強3(XAPP495のvtc_demo.v を試す2)”の続き。

前回までで、vtc_demo.v を試すのは終了した。今回は、キャラクタ・ディスプレイ・コントローラをDVI出力にしてHDMIコネクタから画像を出力する。

まずは、vtc_demo.v を参考にして、R, G, Bとhsync, vsync を入れれば、TMDS信号(DVIやHDMIの信号)を出力する dvi_disp.v を作成した。Xilinxのライセンスの関係で、残念ながらソースは公開できない。ポートマップだけ下に公開する。

// dvi_disp.v 
// DVI表示ユニット
// 

`default_nettype none

module dvi_disp #(parameter CLKIN_PERIOD = 40.0) // VGA解像度
(
    input    wire    pixclk,                // pixel clock
    input    wire    reset_in,            // active high
    input    wire    [7:0]    red_in,        // RED入力
    input    wire    [7:0]    green_in,    // GREEN入力
    input    wire    [7:0]    blue_in,    // BLUE入力
    input    wire    hsync,
    input    wire    vsync,
    input    wire    display_enable,        // 表示が有効
    output    wire    [3:0]    TMDS,
    output    wire    [3:0]    TMDSB
);


これをキャラクタ・ディスプレイ・コントローラと合わせて、トップのファイルを作った。CharDispCtrlerTest_HDMI.v を下に示す。

// CharDispCtrlerTest_HDMI.v
// CharDispCtrlerTest.vのHDMI用のラッパー、HDMIコネクタから出力する

`default_nettype none

module CharDispCtrlerTest_HDMI (
    input    wire            sysclk,
    input    wire            reset_sw,
    output    wire    [3:0]    TMDS,
    output    wire    [3:0]    TMDSB
);
    wire clk_100;
    wire pixclk;
    wire reset;
    wire locked;
    wire vga_red, vga_green, vga_blue;
    wire vga_hsync, vga_vsync;
    wire display_enable;
    
    pixclk_gen pixclk_gen_inst
    (// Clock in ports
        .CLK_IN1(sysclk),      // IN
        // Clock out ports
        .CLK_OUT1(clk_100),     // OUT
        .CLK_OUT2(pixclk),     // OUT
        // Status and control signals
        .RESET(reset_sw),// IN
        .LOCKED(locked)      // OUT
    );
    
    assign reset = !locked;
    
    CharDispCtrlerTest CharDispCtrlerTest_inst (
        .clk(pixclk),
        .reset(reset),
        .VGA_RED(vga_red),        // 1bit
        .VGA_GREEN(vga_green),    // 1bit
        .VGA_BLUE(vga_blue),    // 1bit
        .VGA_HSYNC(vga_hsync),
        .VGA_VSYNC(vga_vsync),
        .display_enable(display_enable)
    );
    
    dvi_disp #(
        .CLKIN_PERIOD(40.0))
    dvi_disp_inst (
        .pixclk(pixclk),
        .reset_in(reset),
        .red_in({8{vga_red}}),
        .green_in({8{vga_green}}),
        .blue_in({8{vga_blue}}),
        .hsync(vga_hsync),
        .vsync(vga_vsync),
        .display_enable(display_enable),
        .TMDS(TMDS),
        .TMDSB(TMDSB)
    );
endmodule    

`default_nettype wire


pixclk_gen のCLK_OUT1は入力クロックそのままの100MHz、CLK_OUT2はピクセルクロックの25MHz(VGA解像度)を出力する。

更に、テストベンチ CharDispCtrlerTest_HDMI_tb.v も下に示す。”defparam uut.CharDispCtrlerTest_inst.ENABLE_COUNT = 23'd000004;”は、キャラクタを描画するタイミングを取るためのカウンタを階層をまたいで変更している。これは、通常ではシミュレーション時にキャラクタが表示されるのがとっても遅いため、カウンタ値を変更して表示を早めるために使用している。これが出来るのがVerilogの良い所でもあり、怖い所でもある。

module CharDispCtrlerTest_HDMI_tb;

    // Inputs
    reg sysclk;
    reg reset_sw;

    // Outputs
    wire [3:0] TMDS;
    wire [3:0] TMDSB;

    // Instantiate the Unit Under Test (UUT)
    CharDispCtrlerTest_HDMI uut (
        .sysclk(sysclk), 
        .reset_sw(reset_sw), 
        .TMDS(TMDS), 
        .TMDSB(TMDSB)
    );

    parameter PERIOD = 10;
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for clk
    begin
        #OFFSET;
        forever
        begin
            sysclk = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) sysclk = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end

    // Instantiate the Unit Under Test (UUT)
    defparam uut.CharDispCtrlerTest_inst.ENABLE_COUNT = 23'd000004; // シミュレーション

    initial begin
        // Initialize Inputs
        reset_sw = 1'b1;

        // Wait 100 ns for global reset to finish
        #100;
        reset_sw = 1'b0;
        
        // Add stimulus here
        #20000000    $stop;
    end
      
endmodule


下に100usec までのシミュレーション結果を示す。
DVI_HDMI_3_120218.png

あえて論評しない。

今度は、インプリメントしてみた。その結果を下に示す。
DVI_HDMI_4_120218.png

うまくインプリメントできたので、Atlysボードにダウンロードしたら、キャラクタ・ディスプレイ・コントローラが動作した。
DVI_HDMI_5_120218.jpg

うまく行きました。
今回はVerilogだったので、Digilent社のVmodCAMのサンプルを参考にVHDLで書いてみようと思う。こっちはもう少しブログに書けるかと思う。
  1. 2012年02月18日 07:47 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:2

特殊電子回路株式会社から基板チョコレートが届きました

今日、家に帰ったら、特殊電子回路株式会社から基板チョコレートが届いていました。
kiban_tyoko_1_120216.jpg

中を開けると神戸のお菓子メーカーのタグが付いていました。更に丁寧なお手紙も入っていました。大したお金も払っていないのに申し訳ありません。
kiban_tyoko_2_120216.jpg

中を開けると基板チョコレートが入っていました。基板がくっきり印刷されています。こんなに綺麗に印刷されているとは知りませんでした。
kiban_tyoko_3_120216.jpg

後で、ありがたくいただこうと思います。

  1. 2012年02月16日 20:17 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:2

DVI、HDMIの勉強3(XAPP495のvtc_demo.v を試す2)

DVI、HDMIの勉強2(XAPP495のvtc_demo.v を試す1)”の続き。

前回はインプリメントして、表示してみたので、今回はシミュレーションを行った。

テストベンチをvtc_demo_tb.v という名前で作成した。Verilog ソースを下に示す。

`timescale 1ns / 1ps

////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer:
//
// Create Date:   05:06:11 02/15/2012
// Design Name:   vtc_demo
// Module Name:   H:/HDL/FndtnISEWork/Spartan6/Atlys/xapp495/dvi_demo/vtc_demo/vtc_deom_tb.v
// Project Name:  vtc_demo
// Target Device:  
// Tool versions:  
// Description: 
//
// Verilog Test Fixture created by ISE for module: vtc_demo
//
// Dependencies:
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
////////////////////////////////////////////////////////////////////////////////

module vtc_deom_tb;

    // Inputs
    reg RSTBTN;
    reg SYS_CLK;
    reg [3:0] SW;

    // Outputs
    wire [3:0] TMDS;
    wire [3:0] TMDSB;
    wire [3:0] LED;
    wire [1:0] DEBUG;

    // Instantiate the Unit Under Test (UUT)
    vtc_demo uut (
        .RSTBTN(RSTBTN), 
        .SYS_CLK(SYS_CLK), 
        .SW(SW), 
        .TMDS(TMDS), 
        .TMDSB(TMDSB), 
        .LED(LED), 
        .DEBUG(DEBUG)
    );

    parameter PERIOD = 10; // 100MHz clock
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for SYS_CLK
        begin
        SYS_CLK = 1'b0;
        #OFFSET;
        forever begin
            SYS_CLK = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) SYS_CLK = 1'b1;
            #(PERIOD*DUTY_CYCLE);
        end
    end
     
    initial begin
        // Initialize Inputs
        RSTBTN = 1'b1;
        SW = 0;

        // Wait 100 ns for global reset to finish
        #100;
        
        // Add stimulus here
        RSTBTN = 1'b0;

    end
      
endmodule



これで、100usec シミュレーションした結果を下に示す。
DVI_HDMI_3_120216.png

ソースを読んでみると、面白い機能があった。DCM_CLKGEN プリミティブだ。DCM_CLKGEN プリミティブを使用してスイッチの設定によってダイナミックにクロック周波数を変更することができた。動作中にスイッチの設定で、画面の解像度をVGA, SVGA, XGA, SXGA, HDTV720P に変更できる。

DCM_CLKGENの情報は、Spartan-6 FPGA クロック リソース ユーザー ガイド v1.3 (日本語版)の63ページに書いてある。それによると、PROGDATA入力からDCMの M および D 値のプログラミングのシリアルデータを入れるそうだ。これでダイナミックに出力周波数を変更することが出来る。

だいたい、vtc_demo.v の内容がわかったので、これを変更して、キャラクタ・ディスプレイ・コントローラを載せてみることにする。
  1. 2012年02月16日 05:13 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強2(XAPP495のvtc_demo.v を試す1)

DVI、HDMIの勉強1”の続き。

XAPP495のvtc_demo.v をAtlysボードで試してみようと思う。
なお、xapp495.zipをダウンロードするにあったって、いろいろな事項が書いてあるライセンスをaccept したので、余り書かない方針で行こうと思う。

vtc_demo.v をトップファイルとして、階層化にverilogファイルを入れていった。ucfファイルはxapp495\dvi_demo\ucf\vtc_demo.ucf だ。
vtc_demo.ucf のLEDのLOC制約が間違っていたので、下のように修正した。

NET "LED<0>" LOC = "U18";
NET "LED<1>" LOC = "M14";
NET "LED<2>" LOC = "N14";
NET "LED<3>" LOC = "L14";


これでAtlysボード用のProject Navigator のプロジェクトを作成して、インプリメントを行った。終了後の画面を下に示す。
DVI_HDMI_1_120215.png

インプリメントは成功したので、iMPACTでAtlysボードをコンフィギュレーションした。
AtlysボードにHDMIケーブルを接続し、DVI-HDMI変換ケーブルで液晶ディスプレイに接続して映してみたところ、下のようなカラーバーが表示された。
DVI_HDMI_2_120215.jpg

なお、中央に画像のサイズをみるためにメニュー画面を表示している。640X480画素のVGAでフレーム周波数は60Hzだった。スイッチを変えることにより、SVGAやXGAなどの解像度に変化した。

うまくカラーバーが表示できたので、次はシミュレーションを行う。
  1. 2012年02月15日 05:47 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

DVI、HDMIの勉強1

DVIやHDMIの勉強をしようと思う。AXI4バスのマスタを作るにしても、その先のデバイスが無くては確認できないからだ。
AtlysはHDMI画像出力なので、HDMIで出力する必要がある。DVIもDVI-HDMI変換ケーブルがあることでわかるようにHDMIと規格はほとんど同じはずだ。

Xilinx社のDVI, HDMIの資料としては、XAPP460 Video Connectivity Using TMDS I/O in Spartan-3A FPGAsXAPP495 Implementing a TMDS Video Interface in the Spartan-6 FPGA がある。
XAPP460 はSpartan-3A用だが、TMDS (Transition Minimized Differential Signaling)を使用するDVI (Digital Visual Interface) と HDMI (High-Definition Multimedia Interface) のことについて書いてある。
下に列挙すると。

・出力の信号線は4本で、R, G, Bとクロックがある。信号規格はTMDSで差動信号となっている。
・出力する信号はRGB 4:4:4がデフォルトで、YCrCb 4:4:4 and YCrCb 4:2:2にも対応する。
・R, G, Bそれぞれ8ビット幅でそれを8B10Bで10ビットにエンコードする。
・10ビットデータを10:1のシアライザでシリアルデータにして、ピクセルクロックの10倍で伝送する。
・HDMIの場合は音声信号もあるので、4ビットのAUX0, AUX1, AUX2 が入る。これは、R, G, Bの映像信号の代わりに送られる。
・映像信号のブランキングの間は4種類のコントロール・トークンが送られる。
・コントロール・トークンには、video line scan (HSYNC) や frame update (VSYNC) information がある。
・HDMIは映像のブランキングの間、映像信号の代わりにオーディオ信号 (AUX0, AUX1, AUX2) を送るが、DVIは送らないということだ。
・ブランキングの時に2ビットのコントロール信号を送る。
・エンコーダーはR, G, Bの8B10Bエンコーダ、オーディオ信号の4B10Bエンコーダ、ブランキング時のコントロール信号用に2B10Bエンコーダが必要となる。


音声信号は必要無いので、DVI信号でHDMIコネクタに出力するようにしようと思う。
そのサンプルのダウンロード・リンクがXAPP495にあるので、xapp495.zip をダウンロードした。これをやってみようと思う。Vmod CAMのサンプルもあるので、比べて使いやすい方を使おう。
  1. 2012年02月14日 05:46 |
  2. DVI, HDMI
  3. | トラックバック:0
  4. | コメント:0

映画『はやぶさ 遥かなる帰還』を見てきました

今日は、映画『はやぶさ 遥かなる帰還』を見てきました。去年の10月に見たはやぶさの映画よりも、よりドラマ仕立てになっていた気がします。どっちも良かったです。
そうだ、今回の映画は登場人物の名前が変わっていました。川口先生が山口先生に、國中先生が藤中先生になっていました。

  1. 2012年02月12日 19:34 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Altium Designer でIntegrated Library を作る3(PCBライブラリ編2)

Altium Designer でIntegrated Library を作る2(PCBライブラリ編1)”の続き。

前回は自分でパッドを置いって行ってPCBシンボルを作成したが、今回はウィザードを使用して、SO16 (SOP16?) パッケージのPCBシンボルを作成する。M74HC4518のデータシートを参考にした。PCBパッドについては、ここを参考にした。

・ツールメニューからコンポーネント作成ウィザードを選択する。

・PCB コンポーネント ウィザードが立ち上がる。次へ(N)> をクリックする。
Altium_Desiger2_51_120212.png

・Small Outline Packages (SOP) を選択して、指定単位として、Metric(mm) を指定する。
Altium_Desiger2_52_120212.png

・パッドのサイズを指定する。縦 0.8mm 横 1.6mm に指定した。(公差が大きいのでパッドに余裕をみた)
Altium_Desiger2_53_120212.png

・パッド相互の間隔を指定する。パッド間のピッチは縦 1.27mm 横 6.0mm とした。
Altium_Desiger2_54_120212.png

・シルクのライン幅を指定する。デフォルト値の 0.2mm とした。
Altium_Desiger2_55_120212.png

・SOPのピン数を指定する。16 に指定した。
Altium_Desiger2_56_120212.png

・フットプリント名を指定する。SO16-M74HC4518 と指定した。
Altium_Desiger2_57_120212.png

・ウィザードが終了した。終了ボタンをクリックする。
Altium_Desiger2_58_120212.png

・SO16 のPCBシンボルが出来上がった。
Altium_Desiger2_59_120212.png

・PCBライブラリファイルをセーブしておく。

・回路図ライブラリのSchlib1.ScLib をクリックして、回路図ライブラリへ戻る。真ん中下のウインドウのAdd Footprintの右の下向き三角をクリックし、Footprintを選択する。現在、表示されている回路図シンボルは74HC4511だ。
Altium_Desiger2_60_120212.png

・PCBモデル・ダイアログが開く。ブラウズ...ボタンをクリックする。
Altium_Desiger2_61_120212.png

・ブラウズ ライブラリ・ダイアログが表示される。DIP16marsee を選択して、OKボタンをクリックする。
Altium_Desiger2_62_120212.png

・PCBモデル・ダイアログに選択フットプリントが表示される。OKボタンをクリックする。
Altium_Desiger2_63_120212.png

・74HC4511の回路図シンボルにDIP16marsee のPCBシンボルが関連付けられた。
Altium_Desiger2_64_120212.png

・同様に74HC4518にも SO16-M74HC4518 を関連付けた。
Altium_Desiger2_65_120212.png

・回路図ライブラリSchlib1.ScLib をセーブしておく。

・プロジェクトメニューからCompile Integrated Library Integrated_Library_Test2.LibPkg を選択してコンパイルする。

これでAltium Designer でIntegrated Libraryの作成方法のチュートリアルを終了する。
  1. 2012年02月12日 07:17 |
  2. Altium Designer
  3. | トラックバック:0
  4. | コメント:0

MicroBlaze MCSをISE WebPACKから使用する6(割り込み)

今回は、また例によって、、”iso.enat.jp さんのブログ”の”MicroBlaze MCSで割り込みを使う”を参考にさせて頂いてやってみた。(microblaze_enable_interrupts とmicroblaze_disable_interrupts を引用させて頂いた)

結果は、うまく割り込みで動作した。mb-gcc のオプションが-O2 でも -O0 でも同様に割り込みで動作した。

Cソース (Atlys_LED_int.c) を下に貼っておく。

// 
// Atlys_LED_int.c
//
// AltysボードのLEDを1秒ごとに+1するソフトウェア
// FITの割り込みを使用する
//

#define    GPO1_ADDR            0x80000010
#define GPI1_ADDR            0x80000020

#define IRQ_ENABLE            0x80000038
#define IRQ_ACK                0x8000003C
#define    FIT1_INTERRUPT_BIT    0x80        // FIT1の割り込みビット位置

volatile int interrupt = 0;

//割り込み処理
void interrupt_handler()    __attribute__ ((interrupt_handler));
void interrupt_handler() {
    interrupt = 1;
    *(volatile unsigned int *)(IRQ_ACK) = FIT1_INTERRUPT_BIT;
}

//割り込み許可
void microblaze_enable_interrupts()

    __asm__(
    "mfs    r12, rmsr\n\t"        //Read the MSR register
    "ori    r12, r12, 2\n\t"    //Set the interrupt enable bit
    "mts    rmsr, r12\n\t"        //Save the MSR register
    );
}
//割り込み禁止
void microblaze_disable_interrupts()
{
    __asm__(
    "mfs    r12, rmsr\n\t"        //Read the MSR register
    "andi    r12, r12, ~2\n\t"    //Clear the interrupt enable bit
    "mts    rmsr, r12\n\t"        //Save the MSR register
    );
}

int main()
{
    unsigned int led = 0x55;
    
    *(volatile unsigned int *)(GPO1_ADDR) = led;
    
    microblaze_enable_interrupts();
    *(volatile unsigned int *)(IRQ_ENABLE) = FIT1_INTERRUPT_BIT;
    
    while(1){
        // FIT割り込み待ち
        interrupt = 0;
        while(interrupt==0);
        *(volatile unsigned int *)(GPO1_ADDR) = led++;
    }
}



Makefile を下に貼っておく。

TARGET=Atlys_LED_int.elf
TARGET_DEBUG=Atlys_LED_int_debug.elf
SRCDIR=./
OBJDIR=./

SRCS=            $(SRCDIR)Atlys_LED_int.c
OBJS=            $(OBJDIR)Atlys_LED_int.o
OBJS_DEBUG=        $(OBJDIR)Atlys_LED_int_debug.o

CC=mb-gcc
CFLAGS=-O2 -mlittle-endian -Wl,-Map=Atlys_LED_int.map
CFLAGS_DEBUG=-O0 -g -mlittle-endian -Wl,-Map=Atlys_LED_int_debug.map
LDFLAGS1=-Wl,-s

$(TARGET) : $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS1) $(OBJS) -o $(OBJDIR)$(TARGET) $(LDFLAGS2)

$(OBJDIR)Atlys_LED_int.o: $(SRCDIR)Atlys_LED_int.c $(INCS)
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f $(OBJDIR)*.elf $(OBJDIR)*.o $(OBJDIR)*.map 

debug: $(TARGET_DEBUG)

$(TARGET_DEBUG) : $(OBJS_DEBUG)
    $(CC) $(CFLAGS_DEBUG) $(OBJS_DEBUG) -o $(OBJDIR)$(TARGET_DEBUG) $(LDFLAGS2)

$(OBJDIR)Atlys_LED_int_debug.o: $(SRCDIR)Atlys_LED_int.c $(INCS)
    $(CC) $(CFLAGS_DEBUG) -c $< -o $@


  1. 2012年02月11日 07:27 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:0

MicroBlaze MCSをISE WebPACKから使用する5(gdb編)

MicroBlaze MCSをISE WebPACKから使用する4(XMD編)”の続き。

今回は、”iso.enat.jp さんのブログ”の”MicroBlaze MCS でgdbを使う”を参考にさせていただいて、ISE WebPACKでも使えるgdbでデバックしてみることにした。

最初に、デバック情報付きのELFファイルを作る必要がある。前回のMakefileでLDFLAGS1 の -Wl,-s は ld で全てのシンボル情報を出力ファイルから落すというオプションだった。これが付いているとmb-gcc で-g オプションを付けても、デバック情報が追加されない。ということで、Makefile を作りなおした。

TARGET=Atlys_LED_test.elf
TARGET_DEBUG=Atlys_LED_test_debug.elf
SRCDIR=./
OBJDIR=./

SRCS=            $(SRCDIR)Atlys_LED_test.c
OBJS=            $(OBJDIR)Atlys_LED_test.o
OBJS_DEBUG=        $(OBJDIR)Atlys_LED_test_debug.o

CC=mb-gcc
CFLAGS=-O2 -mlittle-endian -Wl,-Map=Atlys_LED_test.map
CFLAGS_DEBUG=-O0 -g -mlittle-endian -Wl,-Map=Atlys_LED_test_debug.map
LDFLAGS1=-Wl,-s

$(TARGET) : $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS1) $(OBJS) -o $(OBJDIR)$(TARGET) $(LDFLAGS2)

$(OBJDIR)Atlys_LED_test.o: $(SRCDIR)Atlys_LED_test.c $(INCS)
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f $(OBJDIR)*.elf $(OBJDIR)*.o $(OBJDIR)*.map 

debug: $(TARGET_DEBUG)

$(TARGET_DEBUG) : $(OBJS_DEBUG)
    $(CC) $(CFLAGS_DEBUG) $(OBJS_DEBUG) -o $(OBJDIR)$(TARGET_DEBUG) $(LDFLAGS2)

$(OBJDIR)Atlys_LED_test_debug.o: $(SRCDIR)Atlys_LED_test.c $(INCS)
    $(CC) $(CFLAGS_DEBUG) -c $< -o $@


(2012/02/10:修正)上のMakefileの CFLAGS_DEBUG=-O2 -g -mlittle-endian -Wl,-Map=Atlys_LED_test_debug.map から CFLAGS_DEBUG=-O0 -g -mlittle-endian -Wl,-Map=Atlys_LED_test_debug.map に修正しました。


これで、Cygwin を立ち上げて、make すると、今までと同じで、make debug するとAtlys_LED_test_debug.elf が出力される。
MB_MCS_90_120209.png


最初に、iMPACTでAtlys_LED_test.bit をダウンロードする。
(注)必ずその都度、できたELFファイルを、microblaze_mcs_data2mem TCLコマンドでビットファイルに入れておく。

次に、XMDを前回同様に立ち上げる。その手順をもう一度下に示す。

・コマンドプロンプトを立ち上げて、ISE13.4のインストール・フォルダに行って、setting32.bat (64ビットWindowsの方はsetting64.bat) を実行する。

・Atlys_LED_test.elf のあるフォルダに移動してXMDを起動する。
MB_MCS_84_120208.png

・MicroBlazeのMDMペリフェラルに、XilinxのUSBダウンロードケーブルで、USB2ポートで接続する。(connect mb mdm -cable type xilinx_platformusb port USB2) (追加:connect mb mdm のみでOKのようです)
MB_MCS_85_120208.png


次に、Cygwin上で、gdbを立ち上げる。

・”mb-gdb”コマンドを入力する。
MB_MCS_91_120209.png

・”load Atlys_LED_test_debug.elf"コマンドを入力したら、”You can't do that when your target is `None'”という表示が出た。

・”file Atlys_LED_test_debug.elf"コマンドを入力したら、elfファイルが読めたようだ。
MB_MCS_92_120209.png

・”list”コマンドを入力した。
MB_MCS_93_120209.png

・”b 22”コマンドを入力して、”*(volatile unsigned int *)(PIT1_PRELOAD_ADDR) = COUNT_VALUE; // 100MHzで1秒”でブレークする。(Cソースは、”MicroBlaze MCSをISE WebPACKから使用する3”の最後を参照のこと)
MB_MCS_94_120209.png

・”target remote localhost:1234 id 0”コマンドを入力して、XMDと接続した。id 0 を入れないとXMDとの接続ができなかった
MB_MCS_95_120209.png

・Cygwin側で”Ignoring packet error, continuing...”が出て、XMDで”Error: No Data on the Socket”のエラーが出たら、XMDでexit を入力して、XMDを終了する。
MB_MCS_96_120209.png
MB_MCS_97_120209.png

・XMDをもう一度立ち上げ、MicroBlazeのMDMペリフェラルに、XilinxのUSBダウンロードケーブルで、USB2ポートで接続する。(connect mb mdm -cable type xilinx_platformusb port USB2)

・もう一度、Cygwinで、”target remote localhost:1234 id 0”コマンドを入力して、XMDと接続する。

・Cygwin に”main () at Atlys_LED_test.c:28”と出て、正常にgdb が起動した。
MB_MCS_98_120209.png
MB_MCS_99_120209.png

GDBコマンドサイトを見ながらコマンドを入れていく。

・まずはp (print)コマンドで led 変数を見てみた。p/x にすると16進になる。(フリーランしてしまった時は、gdb側で止まらないので、XMDの方で stop コマンドを入力すると停止する)
MB_MCS_100_120209.png

・cont コマンドを入力して、次のブレークポイントまで進めた。次のブレークポイントは、現在の行なので、カウントが進んでいるはず。同様に、p (print)コマンドで led 変数を見てみたが、変化がなかった。もう一度、cont コマンドを入れて、led 変数を見てみたら変化している。ボードのLED表示も変化していた。
MB_MCS_101_120209.png

・ブレークポイントで止まるとXMDの方にも表示が出る。
MB_MCS_102_120209.png

・gdb で s や n を押すと1行進む。s はStep in で、n はStep overだ。
MB_MCS_103_120209.png

・最後に、Cygwin に q を、XMD に exit をいれると終了する。

エラーが出た時に、XMDを再起動すればうまくいくのを見つけるのが大変だった。半日、ブログを書くのが遅れてしまった。でも、無事にまとまってよかったと思う。
これで、ISE WebPACKのみでデバックも出来る。

(2010/02/10:追記)
mb-gcc で最初に -O2 オプションを入れないほうが良いとのご指摘を頂いた。確かにそうだと思うので、debug の方だけ、-O0 にしてやってみた。

オプティマイズされている弊害ではないか?という現象も見えていた。下の図で s コマンドで進んでいって30行から25行に戻るのはおかしい。28行に戻るべきだと思う。更に、”b_GPI1 = c_GPI1;”の行が抜けてしまった。これはコンパイラでオプティマイズされているからではないかと推測していた。
MB_MCS_103_120209.png

下にAtlys_LED_test.c のソースコードをもう一度貼っておく。

// 
// Atlys_LED_test.c
//
// AltysボードのLEDを1秒ごとに+1するソフトウェア
// 初めは割り込みを使わないで実行する
//

#define    GPO1_ADDR            0x80000010
#define GPI1_ADDR            0x80000020
#define PIT1_PRELOAD_ADDR    0x80000040
#define PIT1_COUNTER_ADDR    0x80000044
#define PIT1_CONTROL_ADDR    0x80000048

#define COUNT_VALUE            100

int main()
{
    unsigned int b_GPI1 = 0;
    unsigned int c_GPI1 = 0;
    unsigned int led = 0x55;
    
    *(volatile unsigned int *)(PIT1_PRELOAD_ADDR) = COUNT_VALUE; // 100MHzで1秒
    *(volatile unsigned int *)(PIT1_CONTROL_ADDR) = 0x3// Timer Enable, Auto Reload
    
    *(volatile unsigned int *)(GPO1_ADDR) = led;
    
    while(1){
        c_GPI1 = 0x2 & (*(volatile unsigned int *)(GPI1_ADDR));
        if (c_GPI1 != b_GPI1){
            *(volatile unsigned int *)(GPO1_ADDR) = led++;
        }
        b_GPI1 = c_GPI1;
    }
}



最初に、-O2 の場合と、-O0 の場合のAtlys_LED_test_debug.elf の大きさの差だが、どちらも9,357バイトで差がなかった。差分をとって見ると違っているようだ。

実際にmb-gdb を起動してステップ実行してみると、確実にCソースの行で停止した。下図に示す。
MB_MCS_104_120209.png

やはり、磯村さんが指摘されたように、mb-gcc の -O オプションは、少なくともデバック時は -O0 の方が良いようだ。上のMakefile を修正しました。
  1. 2012年02月09日 20:47 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:4

MicroBlaze MCSをISE WebPACKから使用する4(XMD編)

@Vengineerさんから教えていただいた”iso.enat.jp さんのブログ”の”MicroBlaze MCS でXMDを使う”でXMDの使い方が載っていた。許可を頂いたので、自分でもやってみることにした。なお、”iso.enat.jp さんのブログ”は、MicroBlaze MCSについて詳しく書いてあって、とてもためになるブログだと思う。ぜひ、ご一読されることをお勧めする。


XMDのコマンドについては、”Embedded System Tools Reference Manual UG111 (v13.4) January 18, 2012”の135ページからの”Xilinx Microprocessor Debugger (XMD)”を参照した。

(2011/02/09:追加)最初に、iMPACTで、ビットファイルをFPGAボードにダウンロードする必要があります。

・まずはコマンドプロンプトを立ち上げて、ISE13.4のインストール・フォルダに行って、setting32.bat (64ビットWindowsの方はsetting64.bat) を実行する。

・Atlys_LED_test.elf のあるフォルダに移動してXMDを起動する。
MB_MCS_84_120208.png

・MicroBlazeのMDMペリフェラルに、XilinxのUSBダウンロードケーブルで、USB2ポートで接続する。(connect mb mdm -cable type xilinx_platformusb port USB2) (追加:connect mb mdm のみでOKのようです)
MB_MCS_85_120208.png

・Atlys_LED_test.elf をダウンロードする。
MB_MCS_86_120208.png

・run するとAtlys_LED_test.elf が動作した。

・mrd 0x80000044 でPITのカウント・レジスタの値を確認しようとしたら、エラーだった。ラン状態ではみえないようだ。

・stop して、mrd 0x80000044 と0であるのが見えた。

・exit した。
MB_MCS_87_120208.png
  1. 2012年02月08日 05:23 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:0

MicroBlaze MCSをISE WebPACKから使用する3

今回は前回までと異なり、ISE12.4にインストールされてるmb-gcc を使ってMicroBlaze のソフトウェアをコンパイルする。cygwinからmb-gccを起動してMicroBlaze MCSを動作することができた。
ISEのgccソフトウェアをコピーして使っている。”カスタム設計の MicroBlaze”さんか”ISE WebPACKでも使用できるMicroBlazeコアとGCCコンパイラ”辺りを参照。

ポイントは mb-gcc のオプションに -mlittle-endian を付けることだった。ビッグエンディアンだと思っていたのだが、リトルエンディアンだったのかな?AXI4はリトルエンディアンと教えてもらった。Spartan-6なので、AXI4バスでリトルエンディアンなのか?
LogiCORE IP MicroBlaze Micro Controller System (v1.0) の21ページ Table 6: Internal MicroBlaze Parameters Settings によると、C_ENDIANNESSパラメータはデフォルト1で、Select endianness (1 = Little endian)だそうだ。ビッグエンディアンにも出来るということだろう。C_I_AXIはデフォルト0でPLBバスのようだ)

・Cygwinでの実行例。Makefile は、”ひでみのアイデア帳”のMakefileを参考にさせていただいた。
MB_MCS_79_120206.png

(追加)Makefile を貼っておきます。

# PROJECT: Build New MicroBlaze
# ----------------------------------------------------------------------
#
# Copyright (C) 2011-2012 H.Ishihara, http://www.aquaxis.com/
#
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# For further information please contact.
#   http://www.aquaxis.com/
#   info(at)aquaxis.com or hidemi(at)sweetcafe.jp

TARGET=Atlys_LED_test.elf
SRCDIR=./
OBJDIR=./

SRCS=    $(SRCDIR)Atlys_LED_test.c
OBJS=    $(OBJDIR)Atlys_LED_test.o

CC=mb-gcc
CFLAGS=-O2 -mlittle-endian -Wl,-Map=Atlys_LED_test.map
LDFLAGS1=-Wl,-s

$(TARGET) : $(OBJS)
    $(CC) $(CFLAGS) $(LDFLAGS1) $(OBJS) -o $(OBJDIR)$(TARGET) $(LDFLAGS2)

$(OBJDIR)Atlys_LED_test.o: $(SRCDIR)Atlys_LED_test.c $(INCS)
    $(CC) $(CFLAGS) -c $< -o $@

clean:
    rm -f Atlys_LED_test.elf $(OBJDIR)*.o Atlys_LED_test.map


・Atlys_LED_test.elf が出来ていた。
MB_MCS_80_120206.png

・Atlys_LED_test.elf を MB_MCS_led_test2フォルダの下にコピーして、Project Navigator のTCL ConsoleタブのCommand> で”microblaze_mcs_data2mem Atlys_LED_Test.elf”を実行する。
MB_MCS_82_120206.png

・これでISimを起動して、シミュレーションを行うとLED_out[7:0] の途中で 55 に変化したので、動作している。前回のシミュレーション結果と異なるのは、FITのカウント値に100000000をセットしてあるからだ。
MB_MCS_81_120206.png

・ビットファイルをAtlysにダウンロードしたら、LED+1が表示された。。。成功。。。

(2012/02/07:追加)
PITのPIT_InterruptとPIT_Toggleも動いていました。カウンタの値は読めないようです。
MB_MCS_83_120207.png

この時のソフトウェアのAltys_LED_Test.cを下に貼っておきます。

// 
// Atlys_LED_test.c
//
// AltysボードのLEDを1秒ごとに+1するソフトウェア
// 初めは割り込みを使わないで実行する
//

#define    GPO1_ADDR            0x80000010
#define GPI1_ADDR            0x80000020
#define PIT1_PRELOAD_ADDR    0x80000040
#define PIT1_COUNTER_ADDR    0x80000044
#define PIT1_CONTROL_ADDR    0x80000048

#define COUNT_VALUE            100

int main()
{
    unsigned int b_GPI1 = 0;
    unsigned int c_GPI1 = 0;
    unsigned int led = 0x55;
    
    *(volatile unsigned int *)(PIT1_PRELOAD_ADDR) = COUNT_VALUE; // 100MHzで1秒
    *(volatile unsigned int *)(PIT1_CONTROL_ADDR) = 0x3// Timer Enable, Auto Reload
    
    *(volatile unsigned int *)(GPO1_ADDR) = led;
    
    while(1){
        c_GPI1 = 0x2 & (*(volatile unsigned int *)(GPI1_ADDR));
        if (c_GPI1 != b_GPI1){
            *(volatile unsigned int *)(GPO1_ADDR) = led++;
        }
        b_GPI1 = c_GPI1;
    }
}


  1. 2012年02月06日 21:06 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:0

Altium Designer でIntegrated Library を作る2(PCBライブラリ編1)

Altium Designer でIntegrated Library を作る1(回路図ライブラリ編)”の続き。

前回は回路図ライブラリを作成したので、今回はPCBのライブラリを作成する。1つはウィザードを使わないで、自分でパッドを貼ってDIP16パッケージを作成する。もう1つはウィザードを使用して、SO16 (SOP16?) パッケージを作成する。
それでは、DIP16パッケージから作成する。

・ProjectsタブのIntegrated_Libraryプロジェクトで右クリックして、右クリックメニューから、新規ドキュメントをプロジェクトに追加 -> PCBライブラリを選択する。
Altium_Desiger2_43_120205.png

・PcbLib1.PcbLib ができた。ここで、Gキーを押して、グリッドを20milに設定する。

Qキーを押して、単位をmm に変更した。

・配置メニューからパッドを選択する。原点に配置する。

・クリックしないまま、TABキーを押して、デジグネータを1に設定する。
Altium_Desiger2_44_120205.png

・OKボタンをクリックする。Top Layerにパッドを配置した。次々をパッドを配置する。パッドの番号は自動的にインクリメントされる。16個のパッドを置いたところ。
Altium_Desiger2_45_120205.png

*今おいたパッドはスルーホールだが、パッドのダイアログで、配置レイヤをTop Layer にすると表面実装用のパッドになる。サイズと形状の形状をRoundからRectangular とかに変更して、パッドのサイズを変えれば、表面実装用のパッドになる。
Altium_Desiger2_46_120205.png

・Top Overlayタブを選択して、シルクを描く。配置メニューからラインを選択して、箱を書いた。
Altium_Desiger2_47_120206.png

・配置メニューから円を選んで、1番ピンマークを書く。Gキーでグリットを一時的に10mil に変更して、円を描き、またグリットを20mil に戻した。
Altium_Desiger2_48_120206.png

・コンポーネントの名前をDIP16marseeに変更する。左のコンポーネントのPCBCOMPONENT_1をダブルクリックする。

・PCBライブラリ コンポーネント・ダイアログが開く。名称にDIP16marsee、部品高に5.3mm、内容説明を入力する。
Altium_Desiger2_49_120206.png

・DIP16MARSEEのPCBシンボルができた。セーブしておく。
Altium_Desiger2_50_120206.png

Altium Designer でIntegrated Library を作る3(PCBライブラリ編2)”に続く。

  1. 2012年02月06日 04:48 |
  2. Altium Designer
  3. | トラックバック:0
  4. | コメント:0

MicroBlaze MCSをテストする6(FITを使用する)

MicroBlaze MCSをテストする5(Project Navigatorでシミュレーション編)”の続き。

前回、GPOは動いているということがわかった。PITはその後のシミュレーションでも動作させることができなかった。
そこで、FITを使用することにした。今回もProject Navigator 13.4 でテストを行った。

・MicroBlaze MCSのIPをダブルクリックして、設定用のダイアログを出して、FITタブをクリックする。Use Timerをチェックして、Number of Clocks Between Strobes をシミュレーションのために100をセットする。Generate Interruptにチェックを入れた。
MB_MCS_76_120204.png

・これでもう一度、MicroBlaze MCSを生成した。結構長い時間が掛かる。30分くらいかかる感じ?

・FITが入っていたので、トップのVerilogファイル (MicroBlaze_MCS_Test.v) を書き換えた。下にソースを示す。

module MicroBlaze_MCS_Test(
    input     wire clk,
    input    wire reset,
//     input    wire UART_Rx,
//     output    wire UART_Tx,
    output    wire [7:0] LED_out
    );
    
    wire PIT1_Interrupt;
    wire PIT1_Toggle;
    wire INTC_IRQ;
     wire [7:0]    GPI1;
     wire FIT1_Interrupt;
     wire FIT1_Toggle;
    
    assign GPI1 = {6'd0, FIT1_Toggle, PIT1_Toggle};
    
    MB_MCS mcs_0 (
      .Clk(clk), // input Clk
      .Reset(reset), // input Reset
//        .UART_Rx(UART_Rx), // input UART_Rx
//        .UART_Tx(UART_Tx), // output UART_Tx
      .FIT1_Interrupt(FIT1_Interrupt), // output FIT1_Interrupt
      .FIT1_Toggle(FIT1_Toggle), // output FIT1_Toggle
      .PIT1_Enable(1'b1), // input PIT1_Enable
      .PIT1_Interrupt(PIT1_Interrupt), // output PIT1_Interrupt
      .PIT1_Toggle(PIT1_Toggle), // output PIT1_Toggle
      .GPO1(LED_out), // output [7 : 0] GPO1
        .GPI1(GPI1), // input [7 : 0] GPI1
      .INTC_IRQ(INTC_IRQ) // output INTC_IRQ
    );
endmodule


・これで、インプリメントを行った。なお、”source ipcore_dir/microblaze_mcs_setup.tcl”は、BMMファイルのマージとngdbuild "-bm" option の付加を行うようだ。今回のBMMファイルは1つだけなので、最初に一回やれば良いようだ。(コメントで教えて頂きました)ただ、MicroBlaze MCS IPを2つ入れていて、少なくともその内の1つの内蔵のRAM領域を変更した場合には(8Kバイトから16Kバイトとか)、BMMファイルを再度マージするために、もう一度、実行する必要があると思う。

#インプリメント後のFF使用数は728 out of 54,576、LUT使用数は944 out of 27,288、RAMB16BWERs使用数は4 out of 116だった。

・”microblaze_mcs_data2mem SDK/Atlys_LED_Test/Debug/Atlys_LED_Test.elf”を実行して、ソフトウェアをビットファイルやシミュレーション用の記述に入れた。

・ISimでシミュレーションを行った。その際のソフトウェアを下に示す。GPI1の2ビット目の反転を見てLED+1するソフトウェアだ。GPI1の2ビット目はFIT1_Toggle だ。

#define    GPO1_ADDR            0x80000010
#define GPI1_ADDR            0x80000020
#define COUNT_VALUE            100

int main()
{
    unsigned int b_GPI1 = 0;
    unsigned int c_GPI1 = 0;
    unsigned int led = 0x55;
    
    *(volatile unsigned int *)(GPO1_ADDR) = led;
    
    while(1){
        c_GPI1 = 0x2 & (*(volatile unsigned int *)(GPI1_ADDR));
        if (c_GPI1 != b_GPI1){
            *(volatile unsigned int *)(GPO1_ADDR) = led++;
        }
        b_GPI1 = c_GPI1;
    }
}


・ISimのシミュレーション結果を下に示す。FITは動作している。
MB_MCS_78_120205.png

・今度は実機でLEDの動作を見るために、正規の状態にMicroBlaze MCSの設定を戻した。MicroBlaze MCSのIPをダブルクリックして、設定用のダイアログを出して、FITタブをクリックする。Number of Clocks Between Strobesに100000000をセットした。
MB_MCS_77_120204.png

すると、LEDが1秒ごとに+1されて動作した。やっと動いた。。。それにしてもPITは動かないのだろうか?どなたかPITが動いた方がいらしたらお知らせ下さい。よろしくお願いします。

(2011/02/05:追記)どうやら、カウンタの値はリードできないけれど、トグル出力と割り込み出力は皆さん、出ているようです。もう一度確かめてみます。。
  1. 2012年02月05日 05:20 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:4

Altium Designer でIntegrated Library を作る1(回路図ライブラリ編)

Altium Desiger でIntegarated Library を作成する方法を書いておこうと思う。

2つのパーツライブラリを作成する。1つは74HC4518で、1このパッケージに2つのBCDカウンタが入っているICだ。もう1つは74HC4511で7セグメントLEDのデコーダだ。

それでは、Integarated Library を新規作成するところから。

・ファイルメニューから新規 -> プロジェクト -> 統合ライブラリを選択する。

・Integrated Library1.LibPkg というプロジェクトができる。そこで右クリックメニューからプロジェクトの保存を選択して、Integrated_Library_Test2.LibPkg という名前で保存した。
Altium_Desiger2_22_120203.png

・ファイルメニューから新規 -> ライブラリ -> 回路図ライブラリを選択して、回路図ライブラリを作成する。
Altium_Desiger2_23_120203.png

*まずは74HC4518から作成する。最初にピンを置いていく。

・配置メニューからピンを選択する。

・ピンが表示されたら、TABキーを押して、ピン プロパティを表示させる。表示名をCLK_A に、デジグネータを1 に、電気的タイプをInput に、シンボルのエッジの内側をClock に変更する。OKボタンをクリックする。
Altium_Desiger2_24_120203.png

SPACEキーで回転させて、クリックして適当な位置に配置する。
Altium_Desiger2_25_120203.png

・ピンの配置モードにまだなっているので、ピンの番号が2になっている。ここでまた、TABキーを押して、ピン プロパティを表示させる。表示名をEN Aに、エッジの内側をNo Symbol に変更する。
Altium_Desiger2_26_120203.png

・RST Aも置いた。

・次に出力ピンを置く。やはり、TABキーを押して、ピン プロパティを表示させる。表示名をQ0A に、デジグネータを3に、電気的タイプをOutput に変更する。OKボタンをクリックする。
Altium_Desiger2_27_120203.png

・同様に、Q1A, Q2A, Q3A も作った。
Altium_Desiger2_28_120203.png

・VCCとGNDピンを書くが、74HC4518は2つのBCDカウンタがあるので、VCCとGNDピンはハイドしておく。TABキーを押して、ピン プロパティを表示させる。表示名をVCCに、デジグネータを16に、ヒドゥンピンをチェックして、接続ネットをVCCにする。これで、VCCの名前のついたネットに、16番ピンが接続される。
Altium_Desiger2_30_120203.png

・GNDも同様に作成した。8番ピンと、ヒドゥンピンをチェックして、接続ネットをGNDにした。

・回路図シンボルの四角い箱を書く。配置メニューから四角形を選んで、ICの外形を書く。
Altium_Desiger2_29_120203.png

・箱がピン名の上にかぶってしまっているので背面に移動する。編集メニューから移動 -> 後面へ(Mキー -> 後面へ)を選択して、黄色の四角い箱をクリックして、後面へ移動する。
Altium_Desiger2_31_120204.png

・原点位置に合わせて移動した。これで、1つ目のBCDカウンタは完成だが、もう1つ追加する。
Altium_Desiger2_32_120204.png

・ツールメニューからパートの追加を選択する。

・左のコンポーネント・ウインドウのComponent_1にPart AとPart Bが出来る。Part Aは今まで作ってきた回路図シンボルが入っているが、Part Bの方は何も無い。
Altium_Desiger2_33_120204.png

・Part Aの回路図シンボルをPart Bにコピーする。

・ピン番号を変えるために、ピンをダブルクリックして、ピン プロパティを表示させて、デジグネータを変更した。
Altium_Desiger2_34_120204.png

・Part Bのピン番号を全部修正できたのが下の図だ。
Altium_Desiger2_35_120204.png

・左のコンポーネント・ウインドウのComponent_1をダブルクリックして、名前を74HC4518に変更する。
Altium_Desiger2_36_120204.png

・回路図ライブラリをセーブした。
Altium_Desiger2_37_120204.png

・コンポーネント・ウインドウの追加ボタンをクリックして、コンポーネントを追加する。
Altium_Desiger2_38_120204.png

・New Component Name ダイアログが開くので、74HC4511と入力した。
Altium_Desiger2_39_120204.png

・74HC4511のコンポーネントができたので、回路図ライブラリを作成する。

・ピン名にバーを付けたい場合には\を文字の後ろにつける。下に例を示す。
Altium_Desiger2_40_120204.png

・表示は下のようになる。
Altium_Desiger2_41_120204.png

・74HC4511のコンポーネントが完成した。
Altium_Desiger2_42_120204.png

・これで回路図ライブラリは完成だ。

  1. 2012年02月03日 05:56 |
  2. Altium Designer
  3. | トラックバック:0
  4. | コメント:0

MicroBlaze MCSをテストする5(Project Navigatorでシミュレーション編)

”MicroBlaze MCSをテストする4(SDK編2)”の続き。

MicroBlaze MCSでは、正規の手順でSDKを使ってソフトウェアを作るという手順とWebPACKでも出来るように、独自にMicroBlaze のクロスコンパイラをビルドして独自にソフトウェアを作るという手順の2つを試している。今回はその内の前者だ。

今回はProject Navigatorでの手順を説明する。前回のMicroBlaze MCSの設定からPITの設定のDefine Prescaler の設定をNoneからExternalに変更した。

・Project Navigator で論理合成を行う。
MB_MCS_53_120128.png

・ViewメニューからPanels -> TCL Consoleを選択して、TCL Consoleを表示する。

・TCL CosoleのCommand> 行に以下のTCLコマンドを入力した。このTCLスクリプトはBMMファイルのマージとツールのアップデートを行う。

source ipcore_dir/microblaze_mcs_setup.tcl


MB_MCS_54_120128.png

・Project Navigator のProcessesウインドウでGenerate Programming Fies をダブルクリックして、ビットファイルの生成を行う。

・TCL CosoleのCommand> 行に以下のTCLコマンドを入力した。このTCLスクリプトは、SDKのELFバイナリをビットファイルに入れたり、シミュレーションのためにメモリイメージを生成する。

microblaze_mcs_data2mem SDK/Atlys_LED_Test/Debug/Atlys_LED_Test.elf


MB_MCS_55_120128.png

・シミュレーションのためのメモリイメージが生成された。(手動のISimシミュレーションについては、”SMMのシミュレーション(NetGenとData2MEMを使用する)”を参照)
MB_MCS_71_120202.png

・テストベンチファイルを生成して、ISimでシミュレーションを行った。その結果、2usec手前で、LED_outが55になったので、MicroBlaze MCSが動作していることが確認できた。
MB_MCS_72_120202.png

・今度はビットファイルを実機にダウンロードしてみたが、動作しなかった。

・良くUCFファイルを見なおしてみると、clkのピンアサインが違っていた(面目ない!)。これを修正したら、LEDが点灯した。動作したようだが、カウントダウンしない。
MB_MCS_73_120202.png

・PIT1のCounter Register、0x80000044番地の値が常に0のようだ。プリスケーラのせいか?一度プリスケーラを削除してみようか?その前にソフトウェアのカウント値を10程度にして、シミュレーションをしてみる。現在は100MHzで1秒間隔でカウントダウンして欲しいので、100000000にしてある。

・やはりカウントは変わらず0だった。

・今度は、+1カウントとPIT1のCounter Registerの値を交互にGPO1に表示した。やはり、PIT1のCounter Registerの値は0のようだ。なぜだろうか?
MB_MCS_74_120202.png

2010/02/07 追記:Counter Registerの値は0だけど、PIT自体は動いているようです。PIT_InterruptとPIT_Toggle は動作しています。”MicroBlaze MCSをISE WebPACKから使用する3”参照)

現在のソフトウェアを下に貼っておく。

// 
// Atlys_LED_test.c
//
// AltysボードのLEDを1秒ごとに+1するソフトウェア
// 初めは割り込みを使わないで実行する
//

#define    GPIO1_ADDR            0x80000010
#define PIT1_PRELOAD_ADDR    0x80000040
#define PIT1_COUNTER_ADDR    0x80000044
#define PIT1_CONTROL_ADDR    0x80000048

unsigned int read_counter(){
    return(*(volatile unsigned int *)(PIT1_COUNTER_ADDR));
}

int main()
{
    unsigned int b_count = 0;
    unsigned int c_count = 0;
    unsigned int led = 0x55;
    
    *(volatile unsigned int *)(PIT1_PRELOAD_ADDR) = 10// 100MHzで1秒
    *(volatile unsigned int *)(PIT1_CONTROL_ADDR) = 0x3// Timer Enable, Auto load
    
    *(volatile unsigned int *)(GPIO1_ADDR) = led;
    
    while(1){
        c_count = read_counter();
        *(volatile unsigned int *)(GPIO1_ADDR) = c_count;
        if (c_count > b_count){    // 現在の値のほうが大きいのでオートロードした
            *(volatile unsigned int *)(GPIO1_ADDR) = led++;
        }
        *(volatile unsigned int *)(GPIO1_ADDR) = led++;
        b_count = c_count;
    }
}


トップのVerilogファイル。

module MicroBlaze_MCS_Test(
    input     wire clk,
    input    wire reset,
    output    wire [7:0] LED_out
    );
    
    wire PIT1_Interrupt;
    wire PIT1_Toggle;
    wire INTC_IRQ;
    
    assign reset_n = ! reset;
    
    MB_MCS mcs_0 (
      .Clk(clk), // input Clk
      .Reset(reset), // input Reset
      .PIT1_Enable(1'b1), // input PIT1_Enable
      .PIT1_Interrupt(PIT1_Interrupt), // output PIT1_Interrupt
      .PIT1_Toggle(PIT1_Toggle), // output PIT1_Toggle
      .GPO1(LED_out), // output [7 : 0] GPO1
      .INTC_IRQ(INTC_IRQ) // output INTC_IRQ
    );
endmodule


シミュレーション用テストベンチ。

`timescale 1ns / 1ps

module MicroBlaze_MCS_Test_tb;

    // Inputs
    reg clk;
    reg reset;

    // Outputs
    wire [7:0] LED_out;

    // Instantiate the Unit Under Test (UUT)
    MicroBlaze_MCS_Test uut (
        .clk(clk), 
        .reset(reset), 
        .LED_out(LED_out)
    );
    
    parameter PERIOD = 10; // 100MHz clock
    parameter real DUTY_CYCLE = 0.5;
    parameter OFFSET = 0;

    initial    // Clock process for clk
    begin
      clk = 1'b0;
      #OFFSET;
      forever begin
            clk = 1'b0;
            #(PERIOD-(PERIOD*DUTY_CYCLE)) clk = 1'b1;
            #(PERIOD*DUTY_CYCLE);
      end
    end
    
    initial begin
        // Initialize Inputs
        reset = 1'b1;

        // Wait 100 ns for global reset to finish
        #100;
        
        // Add stimulus here
        reset = 1'b0;

    end
      
endmodule


UCFファイル。

NET "LED_out[0]" LOC = U18;
NET "LED_out[1]" LOC = M14;
NET "LED_out[2]" LOC = N14;
NET "LED_out[3]" LOC = L14;
NET "LED_out[4]" LOC = M13;
NET "LED_out[5]" LOC = D4;
NET "LED_out[6]" LOC = P16;
NET "LED_out[7]" LOC = N12;
NET "clk" LOC = L15;
NET "reset" LOC = P3;
NET "LED_out[0]" IOSTANDARD = LVCMOS33;
NET "LED_out[1]" IOSTANDARD = LVCMOS33;
NET "LED_out[2]" IOSTANDARD = LVCMOS33;
NET "LED_out[3]" IOSTANDARD = LVCMOS33;
NET "LED_out[4]" IOSTANDARD = LVCMOS33;
NET "LED_out[5]" IOSTANDARD = LVCMOS33;
NET "LED_out[6]" IOSTANDARD = LVCMOS33;
NET "clk" IOSTANDARD = LVCMOS33;
NET "reset" IOSTANDARD = LVCMOS18;

NET "clk" TNM_NET = "clk";
TIMESPEC TS_sysclk = PERIOD "clk" 10 ns HIGH 50 %;


  1. 2012年02月02日 05:59 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:3

MicroBlaze MCSをISE WebPACKから使用する2

MicroBlaze MCSをISE WebPACKから使用する1”の続き。

ひでみのアイデア帳(SweetCafe)さんの”MicroBlaze MCSで遊ぶ手順”の記事の通りにMicroBlaze MCSを試してみようと思う。

・まずは、生成してあったMicroBlaze MCS IPを記事の指定通りに変更する。
MB_MCS_64_120201.png

・”mb_mcsのスクリプトをgithubにアップ”の記事のgithubからaquaxis-aquaxis-58dbd58.zip をダウンロードした。

・適当なところに解凍した。

・ipcore_dirフォルダの下からMB_MCS.v をコピーして、aquaxis-aquaxis-58dbd58\MicroBlaze\MicroBlazeMCS フォルダにコピーした。

・MB_MCS.v を小文字のmb_mcs.v に変更した。
MB_MCS_65_120201.png

・私のWindows XPにはActivePerlが入っているので、make_mb_mcs.plをダブルクリックした。

・mb_mcs_new.v, mb_mcs_ram.bmm, mb_mcs_ram.v が生成された。
MB_MCS_66_120201.png

・”MicroBlaze MCSをISE WebPACKから使用する1”で生成したHelloWorld をHelloWorld.elf と名前を変更してコピーした。

・cygwin を起動して、make を実行したが、glbl.v がないと言われてエラーだった。ここは変更する必要がある。
MB_MCS_67_120201.png

・glbl.v をコピーしてきて、tb_mb_mcs.prj のglbl.v のパスをカレントフォルダに変更した。

・もういちどmake した。mb_mcsがUNKNOWN moduleになってしまった。
MB_MCS_68_120201.png

・今度は、コマンドプロンプトでやってみる。コマンドプロンプトを立ち上げて、Xilinx\13.4\ISE_DSフォルダのsettings32.bat を実行する。

・aquaxis-aquaxis-58dbd58\MicroBlaze\MicroBlazeMCS フォルダに移動して、”fuse -incremental -lib unisims_ver -lib unimacro_ver -lib xilinxcorelib_ver -o tb_mb_mcs -prj tb_mb_mcs.prj work.tb_mb_mcs work.glbl”を実行したが、同様のエラーだった。

・そういえば、MB_MCB.v からmb_mcb.v に変更した時に、ファイル内のmodule名などのMB_MCS をmb_mcs に変更した。

・もう一度、make_mb_mcs.pl を実行した。これで、mb_mcs_new.v に正しく、mb_mcs.vのコードが反映されたようだ。

・Cygwinでmake を実行した。成功したようだ。
MB_MCS_69_120201.png

・tb_mb_mcs.exe ができたので、これをCygwinで実行したがISimのバージョンが古かった。setting32.bat を実行してあるコマンドプロンプトで -gui オプション付きで実行した。

・ISimが起動した。mb_mcsの信号線をWaveウインドウに追加して、100 msecシミュレーションすると、動いているようです。
MB_MCS_70_120201.png

HelloWorldのHだけConsole に表示されている。

今度は、MicroBlaze MCSのSDKを使う手順をシミュレーションしてなかったので、シミュレーションを試みようと思う。
  1. 2012年02月01日 05:46 |
  2. MicroBlaze MCS
  3. | トラックバック:0
  4. | コメント:0