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

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

FPGAの部屋

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

WebPACK14.2でZedBoardのHello Worldチュートリアルをやってみた1(エラー発生)

ZedBoradを使えるようになったので、ISE WebPACK14.2でHello Worldチュートリアルをやってみた。参考にしたのは、ZedBoard: Zynq-7000 AP SoC Concepts, Tools, and Techniques A Hands-On Guide to Effective Embedded System Design 8/22/2012 だ。これを元に、PlanAheadを使用してHello Worldチュートリアルを行う。
ISE WebPACKもZynqの下から3つまでのデバイスでは、Platform Studioが使えるようになっている。使用するOSはWindows 7 64ビット版とした。

1.最初にPlanAhead 14.2 を立ち上げた。Create New Project をクリックした。
ZedBoard_HW_1_120831.png

2.New Projectダイアログが開く。Next > ボタンをクリックした。
ZedBoard_HW_2_120831.png

3.Project Name とProject location を入力した。Next > ボタンをクリックした。
ZedBoard_HW_3_120831.png

4.RTL Projectを選択した。Next > ボタンをクリックした。
ZedBoard_HW_4_120831.png

5.Add Sources は何も入力しなかった。Next > ボタンをクリックした。
ZedBoard_HW_5_120831.png

6.Add Existing IPも何も入力しなかった。Next > ボタンをクリックした。
ZedBoard_HW_6_120831.png

7.Add Constraints も何も入力しなかった。Next > ボタンをクリックした。
ZedBoard_HW_7_120831.png

8.FPGAを選択した。Zynq-7000, CLG484, -1, C を選択した。Next > ボタンをクリックした。
ZedBoard_HW_8_120831.png

9.Summary が表示された。Finish ボタンをクリックした。
ZedBoard_HW_9_120831.png

10.PlanAheadプロジェクトが表示された。
ZedBoard_HW_10_120831.png

11.Sourcesウインドウで右クリックメニューからAdd Sourcres... を選択した。
ZedBoard_HW_11_120831.png

12.Add or Create Embedded Sources のラジオボタンをクリックした。Next > ボタンをクリックした。
ZedBoard_HW_12_120831.png

13.Create Sub-Design... ボタンをクリックした。
ZedBoard_HW_13_120831.png

14.XPSのプロジェクト名をsystem にした。OK ボタンをクリックした。
ZedBoard_HW_14_120831.png

15.system.xmp が入っているのが見える。Finish ボタンをクリックした。
ZedBoard_HW_15_120831.png

16.Xilinx Platform Studio (XPS) が立ち上がるが、ライセンスが見つからずにエラーとなった。
ZedBoard_HW_16_120831.png

XPSを起動するところでライセンス違反で怒られた。ツイッターで@crazy_diver さんに教えて頂いた(ありがとうございました)のだが、”14.1 - ISE インストール - 「ERROR:EDK - Invalid architecture 'zynq' specified」というエラー メッセージが表示される”があった。ISE14.2ではZynqデバイスはインストールされているようだ。
ISE 14.1 WebPACK install work-arounds”にもあるので、ISE14.2 WebPACKをアンイストールして、Logic Edition をインストールしてみようと思う。ISE14.2 Logic Edition をWebPACKライセンスで使用する。

WebPACK14.2でZedBoardのHello Worldチュートリアルをやってみた2(Logic EditionでXPS)”に続く。

  1. 2012年08月31日 05:44 |
  2. ZedBoard
  3. | トラックバック:0
  4. | コメント:0

AtlysボードのXPSプロジェクトでのMCBの使用

ビットマップ・ディスプレイ・コントローラの作製21(PlanAheadプロジェクトで画面にキャラクタを描画)”からの続きだけれど、AXI Master IPの作製からは離れて、XPSプロジェクトでのMCBの使用の話なので、カテゴリを変更した。

さて、PlanAheadプロジェクト内のXPSプロジェクトでaxi_s6_ddrx IPをAdd IPしてもDDR2 SDRAMにアクセスすることができなかった。今度はISEプロジェクト内のXPSプロジェクトででaxi_s6_ddrx IPをAdd IPしてDDR2 SDRAMにアクセスしてみることにした。
ISEプロジェクトを作成して、XPSプロジェクトを新規作成した。BSBウィザートでおおまかに作って、axi_s6_ddrx をAdd IPした。その際の設定は動作しているプロジェクトの設定をみながらMIGの設定を行った。
インプリメント終了後のISEプロジェクトを下に示す。
BitMapDispCont_137_120830.png

MCBの入出力ポートはUCFには書いていないが、Project Navigator のPinout Report を見ると正常に配置されているようだ。
BitMapDispCont_138_120830.png

これで、SDKにハードウェアをエクスポートして、デバックモードにしてからXMDでDDR2 SDRAMのアドレスの0x20000000 をReadしてみたがReadすることができなかった。
BitMapDispCont_139_120830.png

BitMapDispCont_140_120830.png

という訳で、自分でAdd IPしたaxi_s6_ddrx が動作した試しがない!困った。何か情報がある方はお知らせください。
結局、Digilent社のWebサイトにあるProject Peripheral Repositoryサンプルを使用すれば、問題なくaxi_s6_ddrx (MCB) が使用出来る。(”AtlysボードでXPSプロジェクトを試す1(XPSのプロジェクト作成、インプリメント)”参照、現在はAtlys_BSB_Support_v_3_4 だった)とりあえず、これを使ったほうが良さそうだ。
なお、Atlys_BSB_Support_v_3_4では、axi_hdmi も付いていた。Supported Interface はAXI4-Lite, AXI4-Stream だそうだ。その他、全部で11個のIPコアが付いている。
  1. 2012年08月30日 04:43 |
  2. Atlysボード
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製21(PlanAheadプロジェクトで画面にキャラクタを描画)

ビットマップ・ディスプレイ・コントローラの作製21(画面にキャラクタを描画)”でISEプロジェクト中にXPSプロジェクトを作って、MCBでDDR2を制御した。また、ビットマップ・ディスプレイ・コントローラ IPとキャラクタROM IPを追加し、MicroBlazeでキャラクタROMのラスタデータをReadして、DDR2 SDRAMフレームバッファに書くこむことによってキャラクタを表示することができた。だが、PlanAheadプロジェクトを使用して、MCBの設定を自分で行ったXPSプロジェクトでは、動作していない。ISEプロジェクトのXPSプロジェクトは、”AtlysボードでXPSプロジェクトを試す1(XPSのプロジェクト作成、インプリメント)”で使用したDigilent社のBSBサポート・パッケージを使用している。つまりMIGの設定はおまかせでXPSプロジェクトを作成した時点で設定されていた。(注:現在は、Atlys_BSB_Support_v_3_4でAXIバスのHDMI IPが入っていた。まだ動作は未確認)
そこで、ISEプロジェクトでうまく行ったXPSプロジェクトをPlanAheadプロジェクトで使用したら、うまくいくかどうか確かめてみた。
最初にPlanAheadプロジェクトを生成する場合にISEプロジェクトをインポートしたところ、XPSプロジェクトが無いと言われてエラーになってしまった。そこで、新規のPlanAheadプロジェクトを作成して、XPSプロジェクトをコピーしてみたところ、うまく論理合成、インプリメントが終了してビットストリームを出力することができた。
BitMapDispCont_135_120828.png

SDKにエクスポートして、drawn_disp.cをコンパイルして実行してみたところ、前回同様にキャラクタが並んだ画面が表示された。
BitMapDispCont_136_120828.png

BitMapDispCont_134_120826.png

となると、XPSプロジェクトにMCB (axi_s6_ddrx) をAdd IPする時のMIGの設定が悪いのか?自分でMCBを構築して動作できないと良くないので、設定値を比べてみたい。

(2012/08/29:追加)
axi_s6_ddrx の設定値は一緒にしましたが、自分でIPを追加した方はまだ動作しません。データバスを32ビットにしてMicroBlazeにつないでみることにします。
  1. 2012年08月28日 08:17 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2012/08/27)

FPGAの部屋のまとめサイトを更新しました。

2012年5月3日までの記事を記事のリンクを追加し、VivadoZynqAXIバスについてAXI Lite Slave IPコアの作製マイコン関連のページを追加しました。その他、他のページもアップデートしました。
  1. 2012年08月27日 05:37 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製21(画面にキャラクタを描画)

ビットマップ・ディスプレイ・コントローラの作製20(DDR2をMicroBlazeと接続)”の続き。

XPSプロジェクトには、キャラクタROMのAXI4 Lite IPが入っている。実は今回のビットマップ・ディスプレイ・コントローラをMircoBlazeからテストするためにキャラクタROMのAXI4 Lite IPを作った。(”AXI4 Lite Slave IPの作製”を参照のこと)
これをMicroBlazeから読みだして、MicroBlazeでDDR2 SDRAMのビデオ・フレームバッファに書き込めば、キャラクタを表示することが出来る。
SDKでソフトウェアを書いてやってみたらディスプレイにキャラクタを書くことに成功した。下にCのソフトウェアを示す。なお、xparameters.hのアドレス定義を使うとなぜか?うまくいかないので、アドレスは直書きしている。

/* * drawn_disp.c * *  Created on: 2012/08/23 *      Author: Masaaki */

// char_draw: アドレスとキャラクタコードを受け取ってそのキャラクタを描画する
// addr : 描画するキャラクタのスタートアドレス
// char_code : 描画するキャラクタのコード
// char_color : 描画するキャラクタのカラー、32ビットで表される、0RGBと8ビットずつで表す
// 戻り値:次のキャラクタの描画先頭アドレスを示す。
unsigned int *char_draw(unsigned int *addr, unsigned char char_code, unsigned int char_color){
    int i,j;
    unsigned int char_pattern;
    unsigned int char_code_int;
    unsigned int *cal_char_addr;
    unsigned int *return_addr;

    char_code_int = (unsigned int)(char_code);
    return_addr = addr + 8;
    cal_char_addr = 0x7f800000+((char_code_int<<3)<<2); // キャラジェネROMのデータは32ビット幅で下の8ビットだけ有効
    for(i=0; i<8; i++){
        char_pattern = *(volatile unsigned int *)(cal_char_addr); // キャラクタのパターンを読み出し
        for(j=0; j<8; j++){
            if(char_pattern & 0x1// 7ビット目が1の時はドットを描画
                *(volatile unsigned int *)((unsigned int)addr ^ 4) = char_color;
            else
                *(volatile unsigned int *)((unsigned int)addr ^ 4) = 0// 黒を描画
            addr++;
            char_pattern >>= 1// キャラクタのパターンを1ビット右シフト
        }
        addr -= 8// 行の最初のアドレスに戻す
        addr += 640// アドレスを1行下にする
        cal_char_addr++;
    }

    return return_addr;
}

int main()
{
    unsigned char char_code;
    unsigned int * ddr2_addr;
    unsigned int coler_code;
    unsigned int char_cnt;
    int i, j;

    for (ddr2_addr=0x20000000; ddr2_addr<0x2012C000; ddr2_addr++){
        *(volatile unsigned int *)((unsigned int)ddr2_addr ^ 4) = 0;
    }
    
    ddr2_addr = 0x20000000;
    char_cnt = 0;
    for(j=0; j<8; j++){
        for(i=1; i<8; i++){
            switch(i){
                case 1 :
                    coler_code = 0xff;
                    break;
                case 2 :
                    coler_code = 0xff00;
                    break;
                case 3 :
                    coler_code = 0xffff;
                    break;
                case 4 :
                    coler_code = 0xff0000;
                    break;
                case 5 :
                    coler_code = 0xff00ff;
                    break;
                case 6 :
                    coler_code = 0xffff00;
                    break;
                case 7 :
                    coler_code = 0xffffff;
            }
            
            for(char_code=0x21; char_code<0x80; char_code++){
                if(char_code >= 0x80// キャラクタコードが上限に達したら、一番下に戻す
                    char_code = 0x21;
                if (char_cnt!=0 && char_cnt%80==0)
                    ddr2_addr = (unsigned int)ddr2_addr + 640*4*7// 1行書き終わったので、下の行に、アドレスは640ドットx1ピクセル4バイトx7行
                ddr2_addr = char_draw(ddr2_addr, char_code, coler_code); // キャラクタを描画
                char_cnt++;
            }
        }
    }

    return 0;
}


このソフトウェアを実行した後のディスプレイの写真を下に示す。
BitMapDispCont_134_120826.png

(2012/08/28:追記)
なぜ、DDR2 SDRAMにデータを書く時に、4とXORを取っているかだが( *(volatile unsigned int *)((unsigned int)addr ^ 4) )、それは、AXI4バスはリトル・エンディアンだが、WriteとReadのデータバス幅が異なるFIFOのデータの出てくる順番はビック・エンディアンだからだ。(”Write側とRead側のデータ幅の異なるFIFOのシミュレーション2”を参照のこと)
MicroBlazeのデータバス幅は32ビット、ビットマップ・ディスプレイ・コントローラとMCBの接続されているAXI4バスのデータバス幅は64ビットで、その間をaxi2axi_connector で接続している。32ビット・データバスのMicroBlazeからDDR2 SDRAMにWriteする時に、Writeデータは64ビットの半分の32ビットで、リトル・エンディアンであるため、低いアドレスのデータはMSBの方の32ビットにWriteされる。ビットマップ・ディスプレイ・コントローラは64ビット・データバスでそのデータをReadして、ビック・エンディアンのWriteとReadのデータバス幅が異なるFIFOのデータでとり出すので、4バイト境界でアドレスが反対になる(MicroBlazeのデータWriteは4バイト長のみとする)。そこで、4とXORを取って4バイト境界のアドレスを反転して、MicroBlazeからデータをWriteしている。こうしないとキャラクタがうまく描画できないのだ。
  1. 2012年08月26日 06:10 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ZedBoardでLinuxが動作した

ZedBoardでLinuxを起動してみた。すでにSDカードが付属していてLinuxのブートイメージが書いてあったので、電源ONしただけで行けると思ったのだが、そのままではLinuxをブートすることができなかった。
下はSDカードの内容。
ZedBoard_2_120824.png

READMEを開くと設定の方法が書いてあった。その通りに設定して、MicroUSBケーブルをパソコンに接続してTeraTermを起動すると、シリアルポートが見えなかった。Cypress社のUSB-UART ICのドライバが入ってないようだった。ドライバを探したが、Degilient社にも、ZedBoard.orgにもドライバがない?検索するとCypress社のUSB-UARTのMicrosoft Certified USB UART Driverが見つかった。ここからドライバをダウンロードしてインストールしたところ使えるようになった。
USB-UARTのドライバをインストールしてTeraTermを開くと、COM9が見えてZedBoardのLinuxの起動メッセージを見ることができた。
ZedBoard_1_120824.png

下の写真がZedBoard の様子だ。128x32 OLEDには、Digilent社のロゴが表示されている。
ZedBoard_3_120824.jpg

なお、私が購入したZedBoardは、付属の電源が日本の規格マークが付いていないということで外されていた。そこで秋月電子の12V電源を購入したが、DCプラグの寸法が合わなかったので、変換コネクタを購入した。今のところ問題なく使えている。(動作保証はしません。自分の責任でご使用ください)
下に購入した秋月電子の12V電源と変換コネクタの型番を示す。
45W級スリムACアダプター12V3.8A(入力AC100~240V) LTE(GFP)451DA-1238
DCプラグ変換プラグ(2.1mm[メス]⇒2.5mm[オス]変換)
  1. 2012年08月24日 17:16 |
  2. ZedBoard
  3. | トラックバック:0
  4. | コメント:9

ビットマップ・ディスプレイ・コントローラの作製20(DDR2をMicroBlazeと接続)

ビットマップ・ディスプレイ・コントローラの作製19(HDLソースの公開)”の続き。

今回はXPSのaxi2axi_connector IPを使って、MicroBlazeとaxi_s6_ddrx_0(MCB)を接続して、MicroBlazeからDDR2 SDRAMのデータをRead/Writeしてみた。

axi2axi_connector の追加の仕方については、”AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製7(MCBインプリメント4)”を参照のこと。
今までのXPSのプロジェクトにaxi2axi_connector を追加した。
BitMapDispCont_131_120823.png

アドレスはaxi2axi_connector_0 が0x20000000 ~ 0x2FFFFFFF で、MCB_DDR2が0x20000000 ~ 0x27FFFFFF でアドレスがかぶっている。つまり、MicroBlaze のアクセスをaxi2axi_connector_0が中継することで、MicroBlazeがMCB_DDR2 にアクセスできるようになる。
BitMapDispCont_132_120823.png

・ISEでExport Hardware Design To SDK with Bitstream を選んで、SDKを立ち上げた。

・SDKでデバックモードにして、XMDで0x20000000にRead/Writeしてみたところ問題なくRead/Writeすることが出来た。
BitMapDispCont_130_120823.png

・SDKでプログラムを作って動作させてみたところ、HDMIの表示画面を書き換えることが出来た。
下図にSDKの画面を示す。
BitMapDispCont_133_120823.png

下にプログラムを示す。

/* * drawn_disp.c * *  Created on: 2012/08/23 *      Author: Masaaki */

int main()
{
    unsigned int * ddr2_addr;
    unsigned int pixel_data;

    pixel_data=0x0;
    for (ddr2_addr=0x20000000; ddr2_addr<0x20010000; ddr2_addr++){
        *(volatile unsigned int *)(ddr2_addr) = pixel_data++;
    }
    return 0;
}



HDMIの画面を下に示す。
BitMapDispCont_134_120823.jpg

以前の画面と比べると上の方が青くなっているのが見えるはずだ。以前の画面を下に示す。
BitMapDispCont_121_120821.jpg

これで、HDMI画面のフレームバッファとして使用しているDDR2 SDRAMにMicroBlazeからデータを書くことが出来た。とっても嬉しい。。。
32ビット幅のAXI4Liteバスと64ビット幅のAXI4バスがaxi2axi_connectorで接続できたことになる。まだChipScopeでプロトコルを確認してはいないが、XMDでアドレスを+4するとデータが+1されているのは確認した。
  1. 2012年08月23日 06:03 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製19(HDLソースの公開)

ビットマップ・ディスプレイ・コントローラの作製18(動作した?)”の続き。

一応動作したと思われるので、HDLソースを公開します。無保証ですので、ご了承ください。後でバグがあった場合は修正します。また、バグを見つけた方はコメント欄でお知らせください。長いです。
まずは、画像の表示タイミングを定義する disp_timing_parameters.vh から。
(2012/12/13:修正、(誤)disp_timing_parameter.vh (正)disp_timing_parameters.vh)

//  表示タイミングの定義
    
    // VGA 解像度 pixel clock = 25MHz
    parameter H_ACTIVE_VIDEO= 640;
    parameter H_FRONT_PORCH = 16;
    parameter H_SYNC_PULSE = 96;
    parameter H_BACK_PORCH = 48;
    parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

    parameter V_ACTIVE_VIDEO = 480;
    parameter V_FRONT_PORCH = 11;
    parameter V_SYNC_PULSE = 2;
    parameter V_BACK_PORCH = 31;
    parameter V_SUM = V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH;

    // SVGA 解像度 pixel clock = 40MHz
    // parameter H_ACTIVE_VIDEO= 800;
    // parameter H_FRONT_PORCH = 40;
    // parameter H_SYNC_PULSE = 128;
    // parameter H_BACK_PORCH = 88;
    // parameter H_SUM = H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH;

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

    // XGA 解像度 pixel clock = 65MHz
    // 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;

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

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

    
    parameter H_DISPLAY_SIZE = H_ACTIVE_VIDEO/8; // 横80桁
    parameter V_DISPLAY_SIZE = V_ACTIVE_VIDEO/8; // 縦60行
    
    parameter RED_DOT_POS = 15; // 15~13ビット目がRED
    parameter GREEN_DOT_POS = 12; // 12~10ビット目がGREEN
    parameter BLUE_DOT_POS = 9; // 9~7ビット目がBLUE
    parameter COLOR_ATTRIB_WIDHT = 3;    // 色情報のビット幅


次に、XPSのpcore のトップの bitmap_disp_cntrler_axi_master.v

// bitmap_disp_cntrler_axi_master.v 
//
// Read Only IP, 64 bit bus
//
// 2012/06/28

`default_nettype none

module bitmap_disp_cntrler_axi_master #
  (
        parameter integer C_INTERCONNECT_M_AXI_WRITE_ISSUING = 8,
        parameter integer C_M_AXI_THREAD_ID_WIDTH       = 1,
        parameter integer C_M_AXI_ADDR_WIDTH            = 32,
        parameter integer C_M_AXI_DATA_WIDTH            = 64,
        parameter integer C_M_AXI_AWUSER_WIDTH          = 1,
        parameter integer C_M_AXI_ARUSER_WIDTH          = 1,
        parameter integer C_M_AXI_WUSER_WIDTH           = 1,
        parameter integer C_M_AXI_RUSER_WIDTH           = 1,
        parameter integer C_M_AXI_BUSER_WIDTH           = 1,
        parameter [31:0]  C_M_AXI_TARGET                 = 32'h00000000,
        parameter integer C_M_AXI_BURST_LEN                = 256,
        parameter integer C_OFFSET_WIDTH                = 32,
        
        /* Disabling these parameters will remove any throttling.
        The resulting ERROR flag will not be useful */ 
        parameter integer C_M_AXI_SUPPORTS_WRITE         = 0,
        parameter integer C_M_AXI_SUPPORTS_READ         = 1
    )
    (
        // System Signals
        input wire           ACLK,
        input wire           ARESETN,

        // Master Interface Write Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID,
        output wire [C_M_AXI_ADDR_WIDTH-1:0]      M_AXI_AWADDR,
        output wire [8-1:0]              M_AXI_AWLEN,
        output wire [3-1:0]              M_AXI_AWSIZE,
        output wire [2-1:0]              M_AXI_AWBURST,
        output wire                  M_AXI_AWLOCK,
        output wire [4-1:0]              M_AXI_AWCACHE,
        output wire [3-1:0]              M_AXI_AWPROT,
        // AXI3 output wire [4-1:0]                  M_AXI_AWREGION,
        output wire [4-1:0]              M_AXI_AWQOS,
        output wire [C_M_AXI_AWUSER_WIDTH-1:0]      M_AXI_AWUSER,
        output wire                  M_AXI_AWVALID,
        input  wire                  M_AXI_AWREADY,

        // Master Interface Write Data
        // AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_WID,
        output wire [C_M_AXI_DATA_WIDTH-1:0]      M_AXI_WDATA,
        output wire [C_M_AXI_DATA_WIDTH/8-1:0]      M_AXI_WSTRB,
        output wire                  M_AXI_WLAST,
        output wire [C_M_AXI_WUSER_WIDTH-1:0]      M_AXI_WUSER,
        output wire                  M_AXI_WVALID,
        input  wire                  M_AXI_WREADY,

        // Master Interface Write Response
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_BID,
        input  wire [2-1:0]              M_AXI_BRESP,
        input  wire [C_M_AXI_BUSER_WIDTH-1:0]      M_AXI_BUSER,
        input  wire                  M_AXI_BVALID,
        output wire                  M_AXI_BREADY,

        // Master Interface Read Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_ARID,
        output wire [C_M_AXI_ADDR_WIDTH-1:0]      M_AXI_ARADDR,
        output wire [8-1:0]              M_AXI_ARLEN,
        output wire [3-1:0]              M_AXI_ARSIZE,
        output wire [2-1:0]              M_AXI_ARBURST,
        output wire [2-1:0]              M_AXI_ARLOCK,
        output wire [4-1:0]              M_AXI_ARCACHE,
        output wire [3-1:0]              M_AXI_ARPROT,
        // AXI3 output wire [4-1:0]          M_AXI_ARREGION,
        output wire [4-1:0]              M_AXI_ARQOS,
        output wire [C_M_AXI_ARUSER_WIDTH-1:0]      M_AXI_ARUSER,
        output wire                  M_AXI_ARVALID,
        input  wire                  M_AXI_ARREADY,

        // Master Interface Read Data 
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_RID,
        input  wire [C_M_AXI_DATA_WIDTH-1:0]      M_AXI_RDATA,
        input  wire [2-1:0]              M_AXI_RRESP,
        input  wire                  M_AXI_RLAST,
        input  wire [C_M_AXI_RUSER_WIDTH-1:0]      M_AXI_RUSER,
        input  wire                  M_AXI_RVALID,
        output wire                  M_AXI_RREADY,
        
        // User Ports
        input    wire    pixclk,
        
        output    wire    TMDS_tx_clk_p,
        output    wire    TMDS_tx_clk_n,
        output    wire    TMDS_tx_2_G_p,
        output    wire    TMDS_tx_2_G_n,
        output    wire    TMDS_tx_1_R_p,
        output    wire    TMDS_tx_1_R_n,
        output    wire    TMDS_tx_0_B_p,
        output    wire    TMDS_tx_0_B_n,
        
        input    wire    ddr_cont_init_done
    );
    
    wire    [7:0]    red, green, blue;
    wire    hsyncx, vsyncx;
    wire    display_enable;
    wire    bde_req, bde_ack;
    wire    [7:0]    bde_arlen;
    wire    [31:0]    bde_address;
    wire    [63:0]    bde_data;
    wire    bde_data_valid;
    reg        reset_disp_2b, reset_disp_1b;
    wire    reset_disp;
    wire    afifo_overflow, afifo_underflow;
    wire    addr_is_zero, h_v_is_zero;
    
    axi_master_interface #(
        .C_M_AXI_THREAD_ID_WIDTH(C_M_AXI_THREAD_ID_WIDTH),
        .C_M_AXI_ADDR_WIDTH(C_M_AXI_ADDR_WIDTH),
        .C_M_AXI_DATA_WIDTH(C_M_AXI_DATA_WIDTH),
        .C_M_AXI_AWUSER_WIDTH(C_M_AXI_AWUSER_WIDTH),
        .C_M_AXI_ARUSER_WIDTH(C_M_AXI_ARUSER_WIDTH),
        .C_M_AXI_WUSER_WIDTH(C_M_AXI_WUSER_WIDTH),
        .C_M_AXI_RUSER_WIDTH(C_M_AXI_RUSER_WIDTH),
        .C_M_AXI_BUSER_WIDTH(C_M_AXI_BUSER_WIDTH),
        .C_M_AXI_SUPPORTS_WRITE(C_M_AXI_SUPPORTS_WRITE),
        .C_M_AXI_SUPPORTS_READ(C_M_AXI_SUPPORTS_READ)
    ) axi_master_inf_inst
    (
        .ACLK(ACLK), 
        .ARESETN(ARESETN), 
        .M_AXI_AWID(M_AXI_AWID), 
        .M_AXI_AWADDR(M_AXI_AWADDR), 
        .M_AXI_AWLEN(M_AXI_AWLEN), 
        .M_AXI_AWSIZE(M_AXI_AWSIZE), 
        .M_AXI_AWBURST(M_AXI_AWBURST), 
        .M_AXI_AWLOCK(M_AXI_AWLOCK), 
        .M_AXI_AWCACHE(M_AXI_AWCACHE), 
        .M_AXI_AWPROT(M_AXI_AWPROT), 
        .M_AXI_AWQOS(M_AXI_AWQOS), 
        .M_AXI_AWUSER(M_AXI_AWUSER), 
        .M_AXI_AWVALID(M_AXI_AWVALID), 
        .M_AXI_AWREADY(M_AXI_AWREADY), 
        .M_AXI_WDATA(M_AXI_WDATA), 
        .M_AXI_WSTRB(M_AXI_WSTRB), 
        .M_AXI_WLAST(M_AXI_WLAST), 
        .M_AXI_WUSER(M_AXI_WUSER), 
        .M_AXI_WVALID(M_AXI_WVALID), 
        .M_AXI_WREADY(M_AXI_WREADY), 
        .M_AXI_BID(M_AXI_BID), 
        .M_AXI_BRESP(M_AXI_BRESP), 
        .M_AXI_BUSER(M_AXI_BUSER), 
        .M_AXI_BVALID(M_AXI_BVALID), 
        .M_AXI_BREADY(M_AXI_BREADY), 
        .M_AXI_ARID(M_AXI_ARID), 
        .M_AXI_ARADDR(M_AXI_ARADDR), 
        .M_AXI_ARLEN(M_AXI_ARLEN), 
        .M_AXI_ARSIZE(M_AXI_ARSIZE), 
        .M_AXI_ARBURST(M_AXI_ARBURST), 
        .M_AXI_ARLOCK(M_AXI_ARLOCK), 
        .M_AXI_ARCACHE(M_AXI_ARCACHE), 
        .M_AXI_ARPROT(M_AXI_ARPROT), 
        .M_AXI_ARQOS(M_AXI_ARQOS), 
        .M_AXI_ARUSER(M_AXI_ARUSER), 
        .M_AXI_ARVALID(M_AXI_ARVALID), 
        .M_AXI_ARREADY(M_AXI_ARREADY), 
        .M_AXI_RID(M_AXI_RID), 
        .M_AXI_RDATA(M_AXI_RDATA), 
        .M_AXI_RRESP(M_AXI_RRESP), 
        .M_AXI_RLAST(M_AXI_RLAST), 
        .M_AXI_RUSER(M_AXI_RUSER), 
        .M_AXI_RVALID(M_AXI_RVALID), 
        .M_AXI_RREADY(M_AXI_RREADY), 
        
        .bde_req(bde_req),
        .bde_ack(bde_ack),
        .bde_arlen(bde_arlen),
        .bde_address(bde_address),
        .bde_data_out(bde_data),
        .bde_data_valid(bde_data_valid)
    );
    
    bitmap_disp_engine bitmap_disp_eng_inst (
        .clk_disp(pixclk),
        .clk_axi(ACLK),
        .reset_disp(reset_disp),
        .reset_axi(~ARESETN),
        .req(bde_req),
        .ack(bde_ack),
        .ARLEN(bde_arlen),
        .address(bde_address),
        .data_in(bde_data),
        .data_valid(bde_data_valid),
        .red_out(red),
        .green_out(green),
        .blue_out(blue),
        .hsyncx(hsyncx),
        .vsyncx(vsyncx),
        .display_enable(display_enable),
        .ddr_cont_init_done(ddr_cont_init_done),
        .afifo_overflow(afifo_overflow),
        .afifo_underflow(afifo_underflow),
        .addr_is_zero(addr_is_zero),
        .h_v_is_zero(h_v_is_zero)
    );
    
    dvi_disp #(
        .PLL_CLKFBOUT_MULT(20),        // クロック倍率 PLL VCO Freq 400MHz ~ 1000MHz
        .PLL_CLKIN_PERIOD(40.0),    // 40 ns, VGA, 640x480
        .PLL_CLKOUT0_DIVIDE(2),        // ピクセルクロックX10
        .PLL_CLKOUT1_DIVIDE(20),    // ピクセルクロック
        .PLL_CLKOUT2_DIVIDE(10)        // ピクセルクロックX2
    ) dvi_disp_inst
    (
        .pixclk(pixclk),
        .reset_in(reset_disp),
        .red_in(red),
        .green_in(green),
        .blue_in(blue),
        .hsync(hsyncx),
        .vsync(vsyncx),
        .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)
    );
    
    always @(posedge pixclk) begin
        reset_disp_2b <= ~ARESETN;
        reset_disp_1b <= reset_disp_2b;
    end
    assign reset_disp = reset_disp_1b;
endmodule

`default_nettype wire


次に、AXI4バスとのインターフェースの axi_master_interface.v です。ビットマップ・ディスプレイ・コントローラはDDR2 SDRAMからReadするだけなので、Write側は実装していません。

// axi_master_interface.v
//
// Read Only IP, 64 bit bus
//
// 2012/06/28

`default_nettype none

module axi_master_interface #
  (
        parameter integer C_M_AXI_THREAD_ID_WIDTH       = 1,
        parameter integer C_M_AXI_ADDR_WIDTH            = 32,
        parameter integer C_M_AXI_DATA_WIDTH            = 64,
        parameter integer C_M_AXI_AWUSER_WIDTH          = 1,
        parameter integer C_M_AXI_ARUSER_WIDTH          = 1,
        parameter integer C_M_AXI_WUSER_WIDTH           = 1,
        parameter integer C_M_AXI_RUSER_WIDTH           = 1,
        parameter integer C_M_AXI_BUSER_WIDTH           = 1,

        /* Disabling these parameters will remove any throttling.
        The resulting ERROR flag will not be useful */ 
        parameter integer C_M_AXI_SUPPORTS_WRITE         = 0,
        parameter integer C_M_AXI_SUPPORTS_READ         = 1
    )
    (
        // System Signals
        input wire           ACLK,
        input wire           ARESETN,

        // Master Interface Write Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0] M_AXI_AWID,
        output wire [C_M_AXI_ADDR_WIDTH-1:0]      M_AXI_AWADDR,
        output wire [8-1:0]              M_AXI_AWLEN,
        output wire [3-1:0]              M_AXI_AWSIZE,
        output wire [2-1:0]              M_AXI_AWBURST,
        output wire                  M_AXI_AWLOCK,
        output wire [4-1:0]              M_AXI_AWCACHE,
        output wire [3-1:0]              M_AXI_AWPROT,
        // AXI3 output wire [4-1:0]                  M_AXI_AWREGION,
        output wire [4-1:0]              M_AXI_AWQOS,
        output wire [C_M_AXI_AWUSER_WIDTH-1:0]      M_AXI_AWUSER,
        output wire                  M_AXI_AWVALID,
        input  wire                  M_AXI_AWREADY,

        // Master Interface Write Data
        // AXI3 output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]     M_AXI_WID,
        output wire [C_M_AXI_DATA_WIDTH-1:0]      M_AXI_WDATA,
        output wire [C_M_AXI_DATA_WIDTH/8-1:0]      M_AXI_WSTRB,
        output wire                  M_AXI_WLAST,
        output wire [C_M_AXI_WUSER_WIDTH-1:0]      M_AXI_WUSER,
        output wire                  M_AXI_WVALID,
        input  wire                  M_AXI_WREADY,

        // Master Interface Write Response
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_BID,
        input  wire [2-1:0]              M_AXI_BRESP,
        input  wire [C_M_AXI_BUSER_WIDTH-1:0]      M_AXI_BUSER,
        input  wire                  M_AXI_BVALID,
        output wire                  M_AXI_BREADY,

        // Master Interface Read Address
        output wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_ARID,
        output reg  [C_M_AXI_ADDR_WIDTH-1:0]      M_AXI_ARADDR,
        output reg  [8-1:0]              M_AXI_ARLEN,
        output wire [3-1:0]              M_AXI_ARSIZE,
        output wire [2-1:0]              M_AXI_ARBURST,
        output wire [2-1:0]              M_AXI_ARLOCK,
        output wire [4-1:0]              M_AXI_ARCACHE,
        output wire [3-1:0]              M_AXI_ARPROT,
        // AXI3 output wire [4-1:0]          M_AXI_ARREGION,
        output wire [4-1:0]              M_AXI_ARQOS,
        output wire [C_M_AXI_ARUSER_WIDTH-1:0]      M_AXI_ARUSER,
        output wire                  M_AXI_ARVALID,
        input  wire                  M_AXI_ARREADY,

        // Master Interface Read Data 
        input  wire [C_M_AXI_THREAD_ID_WIDTH-1:0]      M_AXI_RID,
        input  wire [C_M_AXI_DATA_WIDTH-1:0]      M_AXI_RDATA,
        input  wire [2-1:0]              M_AXI_RRESP,
        input  wire                  M_AXI_RLAST,
        input  wire [C_M_AXI_RUSER_WIDTH-1:0]      M_AXI_RUSER,
        input  wire                  M_AXI_RVALID,
        output wire                  M_AXI_RREADY,
        
        // bitmap_disp_engine Interface
        input    wire    bde_req,
        output    reg    bde_ack,
        input    wire    [7:0]    bde_arlen,
        input    wire    [31:0]    bde_address,
        output    reg        [63:0]    bde_data_out,
        output    reg        bde_data_valid
    );
    
    parameter    RESP_OKAY =        2'b00,
                RESP_EXOKAY =    2'b01,
                RESP_SLVERR =    2'b10,
                RESP_DECERR =    2'b11;
    
    reg        reset_1d, reset;
    
    parameter    idle_rd =            4'b0001,
                arvalid_assert =    4'b0010,
                data_read =            4'b0100,
                rd_tran_end =        4'b1000;
    reg        [3:0]    rdt_cs;
    
    reg        arvalid;
    reg        [63:0]    read_data;
    reg        rready;
    
    // ARESETN をACLK で同期化
    always @(posedge ACLK) begin
        reset_1d <= ~ARESETN;
        reset <= reset_1d;
    end
    
    // Write は無し
    assign    M_AXI_AWID = 0;
    assign    M_AXI_AWADDR = 0;
    assign    M_AXI_AWLEN = 0;
    assign    M_AXI_AWSIZE = 0;
    assign    M_AXI_AWBURST = 0;
    assign    M_AXI_AWLOCK = 0;
    assign    M_AXI_AWCACHE = 0;
    assign    M_AXI_AWPROT = 0;
    assign    M_AXI_AWQOS = 0;
    assign    M_AXI_AWUSER = 0;
    assign    M_AXI_AWVALID = 0;
    assign    M_AXI_WDATA = 0;
    assign    M_AXI_WSTRB = 0;
    assign    M_AXI_WLAST = 0;
    assign    M_AXI_WUSER = 0;
    assign    M_AXI_WVALID = 0;
    assign    M_AXI_BREADY = 0;

    // Read
    
    // AXI4バス Read Transaction State Machine
    always @(posedge ACLK) begin
        if (reset) begin
            rdt_cs <= idle_rd;
            arvalid <= 1'b0;
            rready <= 1'b0;
        end else begin
            case (rdt_cs)
                idle_rd :
                    if (bde_req) begin
                        rdt_cs <= arvalid_assert;
                        arvalid <= 1'b1;
                    end
                arvalid_assert :
                    if (M_AXI_ARREADY) begin
                        rdt_cs <= data_read;
                        arvalid <= 1'b0;
                        rready <= 1'b1;
                    end
                data_read :
                    if (M_AXI_RLAST && M_AXI_RVALID) begin // 終了
                        rdt_cs <= rd_tran_end;
                        rready <= 1'b0;
                    end
                rd_tran_end :
                    rdt_cs <= idle_rd;
            endcase
        end
    end
    assign M_AXI_ARVALID = arvalid;
    assign M_AXI_RREADY = rready;
    
    assign M_AXI_ARID = 0;
    
    // M_AXI_ARADDR の処理
    always @(posedge ACLK) begin
        if (reset)
            M_AXI_ARADDR <= 0;
        else begin
            if (bde_req)
                M_AXI_ARADDR <= bde_address;
        end
    end
    
    // M_AXI_ARLEN の処理
    always @(posedge ACLK) begin
        M_AXI_ARLEN <= bde_arlen;
    end
    
    assign M_AXI_ARSIZE = 3'b011;        // 8 Bytes in Transfer
    assign M_AXI_ARBURST = 2'b01;        // INCR
    assign M_AXI_ARLOCK = 2'b00;        // Normal Access
    assign M_AXI_ARCACHE = 4'b0010;    // Normal Non-cacheable Non-bufferable
    assign M_AXI_ARPROT = 3'b000;        // Data access, Secure access, Unprivileged access
    assign M_AXI_ARQOS = 4'b0000;        // default
    assign M_AXI_ARUSER = 1'b0;
    
    // bde_ack の処理
    always @(posedge ACLK) begin
        if (arvalid && M_AXI_ARREADY)
            bde_ack <= 1'b1;
        else
            bde_ack <= 1'b0;
    end
    
    // bde_data_out の処理
    always @(posedge ACLK) begin
        bde_data_out <= M_AXI_RDATA;
    end
    
    // bde_data_valid の処理
    always @(posedge ACLK) begin
        if (rready && M_AXI_RVALID)
            bde_data_valid <= 1'b1;
        else
            bde_data_valid <= 1'b0;
    end
    
endmodule


ビットマップ・ディスプレイ・コントローラの中核部で、水平同期、垂直同期を作ったり、DDR2 SDRAMからピクセルデータを読んでくるように指示する bitmap_disp_engine.v です。

// BitMap Display Controller
// bitmap_disp_engine.v
// AXI4バス用

`default_nettype none

// synthesis translate_off
// `include "std_ovl_defines.h"
// synthesis translate_on

module bitmap_disp_engine (    
    input    wire    clk_disp,            // ディスプレイ表示用クロック
    input    wire    clk_axi,            // AXI4バスクロック
    input    wire    reset_disp,            // clk_disp 用リセット
    input    wire    reset_axi,            // clk_axi 用リセット
    output    reg        req,                // Read Address転送のrequest
    input    wire    ack,                // Read Address転送のacknowlege 
    output    reg        [7:0]    ARLEN,        // Read Address転送のバースト長-1
    output    wire    [31:0]    address,    // AXI4 Busのアドレス
    input    wire    [63:0]    data_in,    // DDR2 SDRAMの画像データ(2つのRGB)
    input    wire    data_valid,
    output    reg        [7:0]    red_out,
    output    reg        [7:0]    green_out,
    output    reg      [7:0]    blue_out,
    output    reg     hsyncx,
    output    reg     vsyncx,
    output    reg        display_enable,
    input    wire    ddr_cont_init_done,    // DDR2 SDRAMコントローラの初期化終了
    output    wire    afifo_overflow, // 非同期FIFO のオーバーフロー・エラー
    output    wire    afifo_underflow,    // 非同期FIFO のアンダーフロー・エラー
    output    reg        addr_is_zero,    // for test
    output    reg        h_v_is_zero        // for test
);
    `include "./disp_timing_parameters.vh"
    
    parameter DDR2_SDRAM_START_ADDRESS = 32'h2000_0000;    // DDR2 SDRAMのスタートアドレス
    
    parameter AFIFO_FULL_VAL = 8'b1000_0000; // Write側の値。Write側は32ビットなので、128でRead側は256となる
    parameter AFIFO_HALF_FULL_VAL = 8'b0100_0000; // Write側の値。Write側は32ビットなので、64でRead側は128となる
    
    parameter [5:0]    idle_rdg=            6'b000001,
                    init_full_mode=        6'b000010,
                    wait_half_full=        6'b000100,
                    req_burst=            6'b001000,
                    frame_wait_state=    6'b010000,
                    frame_start_full=    6'b100000;
    reg    [5:0] cs_rdg;
    
    parameter [2:0]    IDLE_REQ =        3'b001,
                    REQ_ASSERT =    3'b010,
                    REQ_HOLD =        3'b100;
    reg [2:0]    cs_req;
    
    reg afifo_rd_en;
    wire [31:0] afifo_dout;
    wire afifo_full;
    wire afifo_empty;
    wire [7:0] wr_data_count;
    reg [31:0] addr_count;
    (* KEEP="TURE" *) wire hv_count_enable;
    reg [7:0] read_count;
    (* KEEP="TURE" *) reg hv_cnt_ena_d1;
    (* KEEP="TURE" *) reg hv_cnt_ena_d2;
    reg [11:0] h_count;
    reg [11:0] v_count;
    reg [7:0] red_node, green_node, blue_node;
    reg hsyncx_node, vsyncx_node;
    reg addr_is_zero_node, h_v_is_zero_node;
    reg vsync_axi, vsync_axi_b1;
    reg vsync_axi_1d;
    reg vsyncx_rise_pulse;

    // synthesis translate_off
    // wire [`OVL_FIRE_WIDTH-1:0] fire_overflow, fire_underflow;
    // synthesis translate_on
    
    // RGB保存用非同期FIFO, FWFT Wirte側64ビット幅128深度、Read側32ビット256深度とする
    bitmap_afifo bitmap_afifo_inst (
        .wr_rst(reset_axi | vsync_axi),
        .wr_clk(clk_axi),
        .rd_clk(clk_disp),
        .rd_rst(reset_disp | ~vsyncx_node),
        .din(data_in), // Bus [63 : 0] 
        .wr_en(data_valid),
        .rd_en(afifo_rd_en),
        .dout(afifo_dout), // Bus [31 : 0] 
        .full(afifo_full),
        .overflow(afifo_overflow),
        .empty(afifo_empty),
        .underflow(afifo_underflow),
        .wr_data_count(wr_data_count) // Bus [7 : 0] 
    );
    
    // AXI4 Busのアドレスカウンタ(AXI4クロックドメイン)カウンタの単位は1バイト
    always @(posedge clk_axi) begin
        if (reset_axi)
            addr_count <= DDR2_SDRAM_START_ADDRESS;
        else begin
            // if (addr_count>=(DDR2_SDRAM_START_ADDRESS + (H_ACTIVE_VIDEO * V_ACTIVE_VIDEO *4))) // 1フレーム分描画終了したのでクリアする(1ピクセルに3バイト使用する。つまり32ビット(4bytes)使用するので*4する)
            if (vsync_axi)
                addr_count <= DDR2_SDRAM_START_ADDRESS;
            else if (data_valid) // データが来たらカウントアップ
                addr_count <= addr_count + 32'd8; // 1回のデータは64ビット長(8バイト)
        end
    end
    assign address = addr_count;
    
    // Readデータ処理モジュール用ステートマシン
    always @(posedge clk_axi) begin
        if (reset_axi)
            cs_rdg <= idle_rdg;
        else begin
            case (cs_rdg)
                idle_rdg :
                    if (ddr_cont_init_done)
                        cs_rdg <= init_full_mode;
                init_full_mode : // 最初にcam_data_afifo をFULLにするステート、このステートではVGA信号は出力しないで、ひたすらcam_data_afifo がFULLになるのを待つ。
                    if (read_count==0)
                        cs_rdg <= wait_half_full;
                wait_half_full : // cam_data_afifo がHALF_FULLになるまでこのステートで待機
                    if (vsync_axi)
                        cs_rdg <= frame_wait_state;
                    else if (wr_data_count<=AFIFO_HALF_FULL_VAL)
                        cs_rdg <= req_burst;
                req_burst :
                    if (vsync_axi)
                        cs_rdg <= frame_wait_state;
                    else if (read_count==0) // データが全部来たら
                        cs_rdg <= wait_half_full;
                frame_wait_state : // 1フレーム終了後vsync の時にWaitする
                    if (vsyncx_rise_pulse) // vsyncx の立ち上がり
                        cs_rdg <= frame_start_full;
                frame_start_full : // 1フレームのスタートの時にFIFOをフルにする
                    if (read_count==0)
                        cs_rdg <= wait_half_full;
            endcase
        end
    end
    assign hv_count_enable = (cs_rdg==wait_half_full || cs_rdg==req_burst || cs_rdg==frame_wait_state || cs_rdg==frame_start_full) ? 1'b1 : 1'b0;
    
    // req の実装。VRAMのデータをReadしたいときにアクティベート。ackが帰ってきたら落とす
    always @(posedge clk_axi) begin
        if (reset_axi) begin
            cs_req <= IDLE_REQ;
            req <= 1'b0;
        end else begin
            case (cs_req)
                IDLE_REQ : 
                    if (cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full) begin
                        cs_req <= REQ_ASSERT;
                        req <= 1'b1;
                    end
                REQ_ASSERT :
                    if (ack) begin
                        cs_req <= REQ_HOLD;
                        req <= 1'b0;
                    end
                REQ_HOLD :
                    if (~(cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full))
                        cs_req <= IDLE_REQ;
            endcase
        end
    end
    
    // ARLEN, read_count の決定。 init_full_mode,frame_start_full  の時はAFIFO_FULL_VAL-1、それ以外はAFIFO_HALF_FULL_VAL-1
    always @(posedge clk_axi) begin
        if (reset_axi) begin
            ARLEN <= AFIFO_FULL_VAL-1;
            read_count <= AFIFO_FULL_VAL;
        end else begin
            if (cs_rdg==idle_rdg || cs_rdg==frame_wait_state) begin
                ARLEN <= AFIFO_FULL_VAL-1;
                read_count <= AFIFO_FULL_VAL;
            end else if (cs_rdg==wait_half_full) begin
                ARLEN <= AFIFO_HALF_FULL_VAL-1;
                read_count <= AFIFO_HALF_FULL_VAL;
            end else if (cs_rdg==req_burst || cs_rdg==init_full_mode || cs_rdg==frame_start_full) begin
                if (read_count!=0 && data_valid) // 0になるまで、データが来たらデクリメント
                    read_count <= read_count - 1;
            end
        end
    end
    
    // read_count の実装、AXI4 Bus Interface へのRead要求のカウントをする。
    // always @(posedge clk_axi) begin
        // if (reset_axi)
            // read_count <= ARLEN+1;
        // else begin
            // if (cs_rdg==wait_half_full || cs_rdg==idle_rdg)
                // read_count <= ARLEN+1;
            // else if (cs_rdg==req_burst || cs_rdg==init_full_mode) begin
                // if (read_count!=0 && data_valid) // 0になるまで、データが来たらデクリメント
                    // read_count <= read_count - 1;
            // end
        // end
    // end
    
    // ビットマップVGAコントローラのclk_disp 動作部
    
    // h_count、v_count用にclk_axi 動作のcs_rdg の値を使用するので2回clk_disp 動作のFFでラッチする
    always @(posedge clk_disp) begin
        if (reset_disp) begin
            hv_cnt_ena_d1 <= 1'b0;
            hv_cnt_ena_d2 <= 1'b0;
        end else begin
            hv_cnt_ena_d1 <= hv_count_enable;
            hv_cnt_ena_d2 <= hv_cnt_ena_d1;
        end
    end
    
    // h_countの実装(水平カウンタ)
    always @(posedge clk_disp) begin
        if (reset_disp)
            h_count <= 0;
        else if (h_count>=(H_SUM-1)) // h_count がH_SUM-1よりも大きければ0に戻す(mod H_SUM)
            h_count <= 0;
        else if (hv_cnt_ena_d2) // 最初に非同期FIFOをフルにするまではカウントしない
            h_count <= h_count + 11'd1;
    end
    
    // v_countの実装(垂直カウンタ)
    always @(posedge clk_disp) begin
        if (reset_disp)
            v_count <= 0;
        else if (h_count>=(H_SUM-1)) begin // 水平カウンタがクリアされるとき
            if (v_count>=(V_SUM-1)) // v_count がV_SUM-1よりも大きければ0に戻す(mode V_SUM)
                v_count <= 0;
            else if (hv_cnt_ena_d2) // 最初に非同期FIFOをフルにするまではカウントしない
                v_count <= v_count + 10'd1;
        end
    end
    
    // Red, Green, Blue出力
    always @(posedge clk_disp) begin
        if (reset_disp) begin
            red_node <= 0;
            green_node <= 0;
            blue_node <= 0;
        end else begin
            if (~hv_cnt_ena_d2) begin // 最初にpixel_async_fifo がフルになるまで画像データを出力しない。
                red_node <= 0;
                green_node <= 0;
                blue_node <= 0;
            end else if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) begin
                red_node <= afifo_dout[23:16];
                green_node <= afifo_dout[15:8];
                blue_node <= afifo_dout[7:0];
            end else begin
                red_node <= 0;
                green_node <= 0;
                blue_node <= 0;
            end 
                
        end
    end
    always @(posedge clk_disp) begin
        if (reset_disp) begin
            red_out <= 0;
            green_out <= 0;
            blue_out <= 0;
        end else begin
            red_out <= red_node;
            green_out <= green_node;
            blue_out <= blue_node;
        end
    end
    
    // hsyncx 出力(水平同期信号)
    always @(posedge clk_disp) begin
        if (reset_disp)
            hsyncx_node <= 1'b1;
        else
            if (h_count>(H_ACTIVE_VIDEO + H_FRONT_PORCH-1) && h_count<=(H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE-1)) // 水平同期期間
                hsyncx_node <= 1'b0;
            else
                hsyncx_node <= 1'b1;
    end
    always @(posedge clk_disp) begin
        if (reset_disp)
            hsyncx <= 1'b1;
        else
            hsyncx <= hsyncx_node;
    end
    
    // vsyncx 出力(水平同期信号)
    always @(posedge clk_disp) begin
        if (reset_disp)
            vsyncx_node <= 1'b1;
        else
            if (v_count>(V_ACTIVE_VIDEO + V_FRONT_PORCH-1) && v_count<=(V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE-1)) // 垂直同期期間
                vsyncx_node <= 1'b0;
            else
                vsyncx_node <= 1'b1;
    end
    always @(posedge clk_disp) begin
        if (reset_disp)
            vsyncx <= 1'b1;
        else
            vsyncx <= vsyncx_node;
    end

    // vsync をclk_axi で同期化
    always @(posedge clk_axi) begin
        if (reset_axi) begin
            vsync_axi        <= 1'b0;
            vsync_axi_b1    <= 1'b0;
            vsync_axi_1d    <= 1'b0;
        end else begin
            vsync_axi_b1     <= ~vsyncx_node;
            vsync_axi         <= vsync_axi_b1;
            vsync_axi_1d    <= vsync_axi;
        end
    end
    
    // vsyncx_rise_pulse の処理。vsyncx の立ち上がり時に1パルス出力する
    always @(posedge clk_axi) begin
        if (reset_axi)
            vsyncx_rise_pulse <= 1'b0;
        else begin
            if (vsync_axi==1'b0 && vsync_axi_1d==1'b1)
                vsyncx_rise_pulse <= 1'b1;
            else
                vsyncx_rise_pulse <= 1'b0;
        end
    end
    
    // display_enable 出力
    always @(posedge clk_disp) begin
        if (reset_disp)
            display_enable <= 1'b1;
        else begin
            if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO)
                display_enable <= 1'b1;
            else
                display_enable <= 1'b0;
        end
    end
    
    // afifo_rd_en の処理
    always @(posedge clk_disp) begin
        if (reset_disp)
            afifo_rd_en <= 1'b0;
        else begin
            if (~hv_cnt_ena_d2) // 初期化中
                afifo_rd_en <= 1'b0;
            else if (h_count<H_ACTIVE_VIDEO && v_count<V_ACTIVE_VIDEO) // 表示期間
                afifo_rd_en <= 1'b1;
            else
                afifo_rd_en <= 1'b0;
        end
    end

    
    // アサーション
    // synthesis translate_off
    always @ (posedge clk_axi) begin
        if (reset_axi)
            ;
        else begin
            if (afifo_overflow) begin 
                $display("%m: at time %t ERROR : FIFOがフルなのにライトした",$time);
                $stop;
            end
        end
    end
    always @(posedge clk_disp) begin
        if (reset_disp)
            ;
        else begin
            if (afifo_underflow) begin
                $display("%m: at time %t ERROR : FIFOが空なのにリードした",$time);
                $stop;
            end
        end
    end
    
    // ovl_never #(
        // `OVL_ERROR,            // severity_level
        // `OVL_ASSERT,        // property_type
        // "ERROR : FIFOがフルなのにライトした", // msg
        // `OVL_COVER_DEFAULT,    // coverage_level
        // `OVL_POSEDGE,        // clock_edge
        // `OVL_ACTIVE_HIGH,    // reset_polarity
        // `OVL_GATE_CLOCK    // gating_type
    // ) afifo_overflow_assertion (
        // clk_axi,
        // reset_axi,
        // 1'b1,
        // afifo_overflow,
        // fire_overflow
    // );
        
    // ovl_never #(
        // `OVL_ERROR,            // severity_level
        // `OVL_ASSERT,        // property_type
        // "ERROR : FIFOが空なのにリードした", // msg
        // `OVL_COVER_DEFAULT,    // coverage_level
        // `OVL_POSEDGE,        // clock_edge
        // `OVL_ACTIVE_HIGH,    // reset_polarity
        // `OVL_GATE_CLOCK    // gating_type
    // ) afifo_underflow_assertion (
        // clk_disp,
        // reset_disp,
        // 1'b1,
        // afifo_underflow,
        // fire_underflow
    // );
    // synthesis translate_on
    
    //  for test
    always @(posedge clk_axi) begin
        if (reset_axi) begin
            addr_is_zero_node <= 1'b0;
            addr_is_zero <= 1'b0;
        end else begin
            if (addr_count == 0)
                addr_is_zero_node <= 1'b1;
            else
                addr_is_zero_node <= 1'b0;
            addr_is_zero <= addr_is_zero_node;
        end
    end
    always @(posedge clk_disp) begin
        if (reset_disp) begin
            h_v_is_zero_node <= 1'b0;
            h_v_is_zero <= 1'b0;
        end else begin
            if (h_count==0 && v_count==0)
                h_v_is_zero_node <= 1'b1;
            else
                h_v_is_zero_node <= 1'b0;
            h_v_is_zero <= h_v_is_zero_node;
        end
    end
            
endmodule

`default_nettype wire


次に、bitmap_afifo.v だが、これは、IPとしてCoreGenで生成したので、ここには載せないことにします。代わりに、Fifo Generator の設定画面を載せておきます。
BitMapDispCont_122_120822.png

BitMapDispCont_123_120822.png

BitMapDispCont_124_120822.png

BitMapDispCont_125_120822.png

BitMapDispCont_126_120822.png

BitMapDispCont_127_120822.png

BitMapDispCont_128_120822.png

dvi_disp.vhd については、”DVI、HDMIの勉強6(キャラクタ・ディスプレイ・コントローラをDVI出力にする VHDL編1)”にVHDLソースコードを貼ってあります。

XPSにpcoreフォルダ関連のファイルやそのやり方については、以下のブログ記事を参考にしてください。
ビットマップ・ディスプレイ・コントローラの作製9(BitMapDCの接続1)
ビットマップ・ディスプレイ・コントローラの作製10(BitMapDCの接続2)
ビットマップ・ディスプレイ・コントローラの作製11(BitMapDCの接続3)
ビットマップ・ディスプレイ・コントローラの作製12(BitMapDCのインプリメント1)

最後にXPSの構成画面を下に貼っておきます。
BitMapDispCont_129_120822.png
  1. 2012年08月22日 04:51 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製18(動作した?)

ビットマップ・ディスプレイ・コントローラの作製17(動き出した)”の続き。タイトルの”動作した?”は、まだ画像が止まって見えるだけで、DDR2 SDRAMの電源ON時のデータを読みだして表示しているだけだからです。こっちの意図した画像を表示しているわけではないという理由で?を付けてあります。

前回は画面が流れていたので、回路がおかしかった。bitmap_disp_engine.v を修正して画面が流れないようになった。(VGAです)
BitMapDispCont_121_120821.jpg

ChipScopeでAXI4バス等の波形を観察してみた。data_valid が1になる間隔を観察してみた。これは、DDR2 SDRAMからデータをReadバーストする間隔だ。
BitMapDispCont_119_120821.png

間隔は514クロックだった。クロック周波数は100MHzなので、周期は10nsec なので、514クロックだと5.14usec となる。

data_valid が1になっている間隔は下の図から64クロックだった。
BitMapDispCont_120_120821.png

64クロックは640nsec となる。
AXI4バス帯域の占有率は 64/512x100≒12.5% となった。
AXI4バス帯域の占有率を計算で出してみて比べてみる。100MHzのAXI4バスでDDR2 SDRAMのデータをReadして、VGAのピクセルクロック25MHzでピクセルデータを読み出している。AXI4バスは64ビット幅で、ピクセルデータは32ビット幅なので、AXI4バスのデータ幅のほうがVGAのピクセルデータよりも2倍のデータを1クロックでReadすることが出来る。以上のことから式を立てると下のようになる。
AXI4バス帯域の占有率は (25/100x100)/2 = 12.5% となる。
よって、実際のAXI4バス帯域の占有率と計算値は、ほぼ等しい。

SVGAではピクセルクロックは40MHzなので、AXI4バス帯域の占有率の計算値は 20%
XGAではピクセルクロックは65MHzなので、AXI4バス帯域の占有率の計算値は 32.5%
SXGAではピクセルクロックは108MHzなので、AXI4バス帯域の占有率の計算値は 54%
HDではピクセルクロックは148.5MHzなので、AXI4バス帯域の占有率の計算値は 74.25% (注:AtlysボードではHDは出力できない)
になる予定だ。HDはバス帯域の占有率から言っても厳しいかもしれないが、Altysボードでは、PLLの最高周波数が対応していないので出力できない。
  1. 2012年08月21日 20:14 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

東京スカイツリータウンに行って来ました

今日は夏休みの最後に、奥さんと東京スカイツリータウンに行って来ました。残念ならが、スカイツリーには登って来ませんでした。(実は高所恐怖症気味なので、あまり登りたくない)
息子を高校においてTXのみどりの駅に車で行きました。車を1日300円の駐車場に置いてTXに乗車しました。その際に買った切符は、TX&東京スカイツリー周辺散策フリーきっぷです。これは奥さんが知っていたんですが、下のような特徴があります。

・TX線発売駅〜浅草駅もしくは北千住駅間は1往復乗車に限り有効
・TX線北千住駅〜浅草駅間が1日乗り降り自由
・東武線浅草駅〜北千住駅間、曳舟駅〜押上駅間および曳舟駅〜亀戸駅間が1日乗り降り自由
・東武バスセントラル線スカイツリーシャトル上野・浅草線が1日乗り降り自由


みどりの駅からの価格は2,140円でした。素敵なストラップももらえました。
SkyTreeTown_1_120821.jpg

上の切符は東武線の切符ですが、何度、東武線の改札の機械に入れても出てきます。当たり前ですが。下の切符がTXの切符です。
SkyTreeTown_2_120821.jpg

駅にもらったパンフレットにあった、おすすめコースBに従って東京の下町を散歩してみながら東京スカイツリーを目指すことにしました。TXの北千住駅で降りて東武線に乗り換え、東向島駅へ。降りてから、向島百花園に向かいました。その時に活躍したのがiPhone。やはり、GPS、コンパス付き地図は便利です。
向島百花園に着きました。大人料金は150円でした。
SkyTreeTown_3_120821.jpg

ここはいろんな植物があるこじんまりした植物園という雰囲気です。石碑がたくさんあって、いろんな文人たちの碑がありました。最初に見つけたのはかしわの木。柏餅を包んでいる葉っぱの木です。初めて見ました。
SkyTreeTown_4_120821.jpg

園内はこんな感じです。
SkyTreeTown_5_120821.jpg

散策路が迷路のように張り巡らせれています。いろんな草木を見てきました。
そろそろお昼時なので、食事をしようとしたら、豆腐料理店の看板が。美味しそうで料金も手頃です。向かったんですが、残念ながら月曜定休でした。ほんとうに美味しそうだったのに残念。。。
今度はおすすめコース通りに白鬚神社へ。ここからのスカイツリーの眺めは良いそうです。途中道路工事していましたが、近かったです。白鬚神社に到着して、お参りしてから、曳舟駅に向かおうとして道に出るとスカイツリーがよく見えました。
SkyTreeTown_6_120821.jpg

地蔵坂通り商店街を抜けて、曳舟駅に到着しました。途中で良さそうなお店があったら食事しようと思ったんですが、なかなかこれといったお店がなかったので、曳舟駅まで来ました。曳舟駅の線路下のい店に入りました。飲み屋+食事処という感じのお店でAランチ(生姜焼き+とんかつ+アジフライの3つが載ったプレートがついてました)を食べました。740円で満足です。ここ良かったです。名前を見てくるのを忘れたのが残念です。名前を知っている方は教えて下さい。
東武線でとうきょうスカイツリー駅へ。東京スカイツリータウンに行ったのですが、いろんなお店が凄くたくさんありました。
千葉工業大学東京スカイツリータウン®キャンパスがあって、レスキューロボや新しいUIのデモを見てきました。レスキューロボは階段をのぼるデモをしていましたが、最後の階段に上がった時はバランスが悪くて危なそうでした。その他はスムーズでしたね。階段では違う駆動機構のほうが良いかもです。
SkyTreeTown_7_120821.jpg

そこの階にガーデンテラスがあって、スカイツリーがよく見えました。絶好の撮影スポットです。
SkyTreeTown_9_120821.jpg
SkyTreeTown_8_120821.jpg

東京スカイツリータウンや東京ソラマチを堪能して帰って来ました。そうそう、銀座のジンジャーというお店で、フローズン マンゴーオレンジジンジャー?(名前はうろ覚えです)という飲み物を飲みました。ジンジャエール好きなので飲んでみたんですが、マンゴー オレンジジュースにジンジャーシロップが入っている飲み物でした。マンゴー オレンジジュースの味はするんですが、ジンジャーが少し遅れて効いてくる飲み物で、まずくはないのですが、不思議な感じでした。あまり量は飲みたくない感じです。皆さんも行かれた時は話の種にどうでしょうか?
  1. 2012年08月20日 20:26 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製17(動き出した)

ビットマップ・ディスプレイ・コントローラの作製16(全体シミュレーション)”の続き。

MCBにキャリブレーションが終了せずに(cal_doneが0) だいぶ苦労してしまった。今までの自分でaxi_s6_ddrx IP (DDR2 SDRAM Controller) を入れて作ったXPSプロジェクト入りのPlanAheadプロジェクトを使ってきたが、どうもaxi_s6_ddrx IP が動かない。そこで違うプロジェクトで確かめてみることにした。それは、”AtlysボードでXPSプロジェクトを試す1(XPSのプロジェクト作成、インプリメント)”で作成してあったXPSプロジェクト入りのISEプロジェクトをISE14.2に変換し、ビットマップ・ディスプレイ・コントローラを入れて使用することにした。下にそのプロジェクトを示す。
BitMapDispCont_117_120818.png

これだと初めからaxi_s6_ddrxのキャリブレーションが終了して、MCBが動作した。ピクセルクロックをつなぎ忘れもしたが、それは修正した。ChipScopeで確認すると、ビットマップ・ディスプレイ・コントローラは動作しているようだった。
BitMapDispCont_118_120818.png

ディスプレイに表示してみたが、まだ表示がおかしいようだ。
BitMapDispCont_119_120818.jpg

ちらついている。DDR2のReadデータとビットマップ・ディスプレイ・コントローラの同期がおかしいのかもしれない。
次回は、現在動作したXPSプロジェクトをPlanAhead にインポートして動くかどうか?を調べてみる。なぜ、自分でAdd IPしたaxi_s6_ddrxが動作しないのか?を調べてみようと思う。
  1. 2012年08月18日 04:47 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製16(全体シミュレーション)

ビットマップ・ディスプレイ・コントローラの作製15(デバック2)”の続き。

今回はだいぶ動かすにに苦労している。夏休みでお盆の行事をこなしながら、あいた時間にやっているが、なかなかうまく行かない。
今回はXPS全体でシミュレーションを行うことにした。PlanAheadでのシミュレーションのやり方は、”PlanAhead14.1でChipScope Proを試してみた1(ChipScope の設定)”、”PlanAhead14.1でChipScope Proを試してみた2(ChipScope Analyzer)”を参照。
早速、テストベンチを書いて、DDR2 SDRAMのモデルを接続した。DDR2 SDMRAMのモデルは以前使用したマイクロン社のモデルを借用した。

PlanAhead のシミュレーションの設定を下に示す。
BitMapDispCont_114_120816.png

VERILOG_DEFINE をsg25E; x16 に設定している。これはDDR2 SDRAMモデルのスピードグレードとデータバス幅の設定だ。DDR2 SDRAMのデータバス幅は16ビットに設定している。
テストベンチ (tb_system_stub.v) を下に示す。

//-----------------------------------------------------------------------------
// testbench.v
//-----------------------------------------------------------------------------

`timescale 1 ps / 100 fs

// START USER CODE (Do not remove this line)

// User: Put your directives here. Code in this
//       section will not be overwritten.

// END USER CODE (Do not remove this line)

module testbench
  (
  );

  `include "simulation/ddr2_parameters.vh";

  // START USER CODE (Do not remove this line)

  // User: Put your signals here. Code in this
  //       section will not be overwritten.

  // END USER CODE (Do not remove this line)

  real CLK_PERIOD = 10000.000000;
  real RESET_LENGTH = 160000;

  // Internal signals

  reg CLK;
  wire [0:7] Led;
  reg RESET;
    wire mcbx_dram_we_n;
    wire mcbx_dram_udm;
    wire mcbx_dram_ras_n;
    wire mcbx_dram_odt;
    wire mcbx_dram_ldm;
    wire mcbx_dram_clk_n;
    wire mcbx_dram_clk;
    wire mcbx_dram_cke;
    wire mcbx_dram_cas_n;
    wire [2:0] mcbx_dram_ba;
    wire [12:0] mcbx_dram_addr;
    reg axi_uartlite_0_RX_pin;
    wire axi_uartlite_0_TX_pin;
    wire zio;
    wire rzq;

    wire    [DQS_BITS-1:0] ddr2_dqs_fpga, ddr2_dqs_sdram;
    wire    [DQS_BITS-1:0] ddr2_dqs_n_fpga, ddr2_dqs_n_sdram;
    wire    [DQ_BITS-1:0] ddr2_dq_fpga, ddr2_dq_sdram;
    reg        [DQS_BITS-1:0] ddr2_dqs_fpgan, ddr2_dqs_sdramn;
    reg        [DQS_BITS-1:0] ddr2_dqs_n_fpgan, ddr2_dqs_n_sdramn;
    reg        [DQ_BITS-1:0] ddr2_dq_fpgan, ddr2_dq_sdramn;
    wire    [2:0] cmd;
    reg        sdram_clk;
    reg        sdram_clkb;
    reg        [12:0] sdram_address;
    reg        [2:0] sdram_ba;
    reg        sdram_cke;
    reg        sdram_rasb, sdram_casb, sdram_web;
    reg        [1:0] sdram_dmn;
    wire    [1:0] sdram_dm;
    reg        sdram_odt;
    wire        reset;
    reg        enable_o;

  system_stub
    dut (
      .RESET ( RESET ),
      .Led ( Led ),
      .CLK ( CLK ),
      .axi_uartlite_0_RX_pin ( axi_uartlite_0_RX_pin ),
      .axi_uartlite_0_TX_pin ( axi_uartlite_0_TX_pin ),
      .axi_s6_ddrx_0_mcbx_dram_addr ( mcbx_dram_addr ),
      .axi_s6_ddrx_0_mcbx_dram_ba ( mcbx_dram_ba ),
      .axi_s6_ddrx_0_mcbx_dram_ras_n ( mcbx_dram_ras_n ),
      .axi_s6_ddrx_0_mcbx_dram_cas_n ( mcbx_dram_cas_n ),
      .axi_s6_ddrx_0_mcbx_dram_we_n ( mcbx_dram_we_n ),
      .axi_s6_ddrx_0_mcbx_dram_cke ( mcbx_dram_cke ),
      .axi_s6_ddrx_0_mcbx_dram_clk ( mcbx_dram_clk ),
      .axi_s6_ddrx_0_mcbx_dram_clk_n ( mcbx_dram_clk_n ),
      .axi_s6_ddrx_0_mcbx_dram_dq ( ddr2_dq_fpga ),
      .axi_s6_ddrx_0_mcbx_dram_dqs ( ddr2_dqs_fpga[0] ),
      .axi_s6_ddrx_0_mcbx_dram_dqs_n ( ddr2_dqs_n_fpga[0] ),
      .axi_s6_ddrx_0_mcbx_dram_udqs ( ddr2_dqs_fpga[1] ),
      .axi_s6_ddrx_0_mcbx_dram_udqs_n ( ddr2_dqs_n_fpga[1] ),
      .axi_s6_ddrx_0_mcbx_dram_udm ( mcbx_dram_udm ),
      .axi_s6_ddrx_0_mcbx_dram_ldm ( mcbx_dram_ldm ),
      .axi_s6_ddrx_0_mcbx_dram_odt ( mcbx_dram_odt ),
      .axi_s6_ddrx_0_rzq ( rzq ),
      .axi_s6_ddrx_0_zio ( zio )
    );

  // Clock generator for CLK

  initial
    begin
      CLK = 1'b0;
      forever #(CLK_PERIOD/2.00)
        CLK = ~CLK;
    end

  // Reset Generator for RESET

  initial
    begin
      RESET = 1'b0;
      #(RESET_LENGTH) RESET = ~RESET;
    end

  // START USER CODE (Do not remove this line)

  // User: Put your stimulus here. Code in this
  //       section will not be overwritten.
    parameter DELAY_TIME = 2000; // 2nsec
    
    assign cmd = {mcbx_dram_ras_n, mcbx_dram_cas_n, mcbx_dram_we_n};
    
    assign reset = ~RESET;
    always @(posedge mcbx_dram_clk, posedge reset)
        if (reset)
            enable_o <= 1'b0;
        else
            if (cmd==3'b100)
                enable_o <= 1'b0;
            else if (cmd==3'b101)
                enable_o <= 1'b1;

    always @ *
        if (enable_o == 1'b1)
            ddr2_dqs_fpgan <= #DELAY_TIME ddr2_dqs_sdram;
        else
            ddr2_dqs_fpgan <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b1)
            ddr2_dqs_n_fpgan <= #DELAY_TIME ddr2_dqs_n_sdram;
        else
            ddr2_dqs_n_fpgan <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b1)
            ddr2_dq_fpgan <= #DELAY_TIME ddr2_dq_sdram;
        else
            ddr2_dq_fpgan <= #DELAY_TIME {DQ_BITS{1'bz}};

    always @ *
        if (enable_o == 1'b0)
            ddr2_dqs_sdramn <= #DELAY_TIME ddr2_dqs_fpga;
        else
            ddr2_dqs_sdramn <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b0)
            ddr2_dqs_n_sdramn <= #DELAY_TIME ddr2_dqs_n_fpga;
        else
            ddr2_dqs_n_sdramn <= #DELAY_TIME {DQS_BITS{1'bz}};
    
    always @ *
        if (enable_o == 1'b0)
            ddr2_dq_sdramn <= #DELAY_TIME ddr2_dq_fpga;
        else
            ddr2_dq_sdramn <= #DELAY_TIME {DQ_BITS{1'bz}};
    
    assign ddr2_dqs_fpga = ddr2_dqs_fpgan;
    assign ddr2_dqs_n_fpga = ddr2_dqs_n_fpgan;
    assign ddr2_dq_fpga = ddr2_dq_fpgan;
    assign ddr2_dqs_sdram = ddr2_dqs_sdramn;
    assign ddr2_dqs_n_sdram = ddr2_dqs_n_sdramn;
    assign ddr2_dq_sdram = ddr2_dq_sdramn;

    always @ * begin
        sdram_clk <= #DELAY_TIME mcbx_dram_clk;
        sdram_clkb <= #DELAY_TIME mcbx_dram_clk_n;
        sdram_address <= #DELAY_TIME mcbx_dram_addr;
        sdram_ba <= #DELAY_TIME mcbx_dram_ba;
        sdram_cke <= #DELAY_TIME mcbx_dram_cke;
        sdram_rasb <= #DELAY_TIME mcbx_dram_ras_n;
        sdram_casb <= #DELAY_TIME mcbx_dram_cas_n;
        sdram_web <= #DELAY_TIME mcbx_dram_we_n;
        sdram_dmn <= #DELAY_TIME {mcbx_dram_udm, mcbx_dram_ldm};
        sdram_odt <= #DELAY_TIME mcbx_dram_odt;
    end
    assign sdram_dm = sdram_dmn;
    
    ddr2 MT47H64M16_25E(
        .dq(ddr2_dq_sdram),
        .dqs(ddr2_dqs_sdram),
        .dqs_n(ddr2_dqs_n_sdram),
        .rdqs_n(),
        .addr(sdram_address),
        .ba(sdram_ba),
        .ck(sdram_clk),
        .ck_n(sdram_clkb),
        .cke(sdram_cke),
        .cs_n(1'b0),
        .ras_n(sdram_rasb),
        .cas_n(sdram_casb),
        .we_n(sdram_web),
        .dm_rdqs(sdram_dm),
        .odt(sdram_odt)
    );

  // END USER CODE (Do not remove this line)

endmodule


下にISimの結果を示す。
BitMapDispCont_115_120816.png

axi_s6_ddrx_0 のAXI4スレーブバスの信号が見えている。約57.3usec 後にuo_done_cal が1になってDDR2 SDRAMのキャリブレーションが終了し、ビットマップ・ディスプレイ・コントローラからAXI4 Readアクセスが開始されている。これは正常な動作だ。
ビットマップ・ディスプレイ・コントローラのエンジン部分 (bitmap_disp_engine.v) を見ても、正常に動作しているのがわかる。
BitMapDispCont_116_120816.png

シミュレーションでも正常だと、何が悪いのだろうか?そう言えば、MCBの外部入出力ピンのIOSTANDARDの設定をXPSのMIG設定にお任せしていて、自分で書いたUCF で SSTL18_II に設定してなかったと思うので、これを設定してみようと思う。
  1. 2012年08月16日 05:14 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製15(デバック2)

ビットマップ・ディスプレイ・コントローラの作製14(デバック1)”の続き。

前回デバックは出来るようになった。ChipScopeで見るとMCBへのアクセスが出来ていないようだがまだ良くわからない。
今回はaxi2axi_connector_0 を削除してみることにした。

・axi2axi_connector_0 を右クリックして、右クリックメニューからDelete Instance を選択した。
BitMapDispCont_110_120813.png

・axi2axi_connector_0 を削除した。
BitMapDispCont_111_120813.png

・AXI4バスを分離したため、axi_s6_ddrx_0 はアドレスが分離された。
BitMapDispCont_112_120813.png

これで論理合成、インプリメントしてみたが、やはり同様に動作しない。

ChipScopeで観察する信号を変えてやってみた。ChipScope のWaveウインドウを下に示す。
BitMapDispCont_113_120813.png

hard_done_cal が0のままだった。これはたぶんMCBの初期化時のキャリブレーションのDONEじゃないか?と思う。そうだった場合は、MCBが使えるようになっていないのかもしれない?(”ar37425のAXI4 Masterサンプルを試す5(シミュレーション2)”参照)
  1. 2012年08月14日 04:40 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製14(デバック1)

ビットマップ・ディスプレイ・コントローラの作製13(実機で動作1)”の続き。

前回、ビットマップ・ディスプレイ・コントローラが動作しなかったので、ChipScopeでデバックをすることにしたが、すでにchipscope_axi_monitor_0 が入っていたので、このIPとchipscpe_icon_0 を削除してから、新たにPlanAheadでChipScope を入れた。(”PlanAhead14.1でChipScope Proを試してみた1(ChipScope の設定)”、”PlanAhead14.1でChipScope Proを試してみた2(ChipScope Analyzer)”を参照)
そうすると、PlanAheadで論理合成して、インプリメントすると、エラーで止まってしまう。
BitMapDispCont_101_120812.png

[Designutils 20-396] Could not read top design file ["H:/HDL/FndtnISEWork/Spartan6/Atlys/test/Atlys_EDK_test_PA_142/Atlys_EDK_test_PA.data/sources_1/cs/chipscope_axi_monitor_0/U_ILA_1/chipscope_axi_monitor_0/U_ILA.ngc"] because this file does not exist


すでにchipscope axi monitor は削除されているのだが、どこかのスクリプトに残ってしまっているみたいだった。もう一度、chipscope axi monitor を入れてみたが、エラーは解決されなかった。
トップフォルダ以下を”cs/chipscope_axi_monitor_0/U_ILA_1/chipscope_axi_monitor_0”のキーワードで検索してみたところ、”Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.data\sources_1”フォルダのchipscope.xml ファイルに記述を見つけた。
BitMapDispCont_102_120812.png

BitMapDispCont_103_120812.png

Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.data\sources_1フォルダ下のchipscope.xml とcs フォルダを削除してみることにした。
PlanAhead を落としてから、上のファイルを削除した。
PlanAhead を起動すると、chipscope.xmlがないとダイアログが出てきてしまった。
BitMapDispCont_104_120812.png

構わず、Synthesized Design を開くと開けた。上のエラーが出ている時はSynthesized Design が開けなかった。
ここから、ToolsメニューのSet up ChipScope... を選択して、ChipScope を設定する。
BitMapDispCont_105_120812.png

ChipScope の信号を設定した。
BitMapDispCont_106_120812.png

インプリメントを開始して、Synthesized Design をセーブすると、Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.data\sources_1フォルダにchipscope.xml が生成された。
BitMapDispCont_107_120812.png

ビットストリームも生成できました~~~。嬉しいです。いくらやってもバグが直らなくてどうしようかと思っていたのですが、良かったです。ツイッターで@apulo_さんにxml ファイルでソースファイルを管理していると教えてもらったのも大きかった。ありがとうございました。

インプリメントが終了したら、csフォルダも出来ていた。
BitMapDispCont_109_120812.png

さて、インプリメント出来たのは良いのだが、XSTのFMaxが86.401MHz、Implementation で42.316MHzと出ていて、タイミング制約は満足できているのか心配になった。
Flow Navigator -> Implementation -> Implemented Design -> Run TRCE を実行して、タイミング解析を実行したところ、クロック周期は10nsec 以内に収まっていて問題ないようだった。それでは、XSTやImplementation のFMax は何なんだろうか?
BitMapDispCont_108_120812.png

  1. 2012年08月12日 07:14 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

東京美術館で「マウリッツハイス美術館展 オランダ・フランドル絵画の至宝」を見てきました

私は8月9日から8月20日まで、お休みです。お盆休みと有給をつなげています。
今日は、上の娘が仙台から昨日帰ってきたので、上野の東京美術館で「マウリッツハイス美術館展 オランダ・フランドル絵画の至宝」を見てきました。
フェルメール「真珠の耳飾りの少女」を見てきましたよ。案外大きさが小さかったです。この絵の前だけは、20分くくらい並んで、立ち止まらずに進んでください状態だったので、じっくり見えませんでしたが、良い感じでしたよ。
他にも当時の貴族の肖像画などが並んでました。やはりレンブラントはとっても絵がうまいと感じました。レンブラントも良いですね。
私は印象派の絵が好きです。昔々、大学生の頃、選択で取った授業、芸術学だっけかな?そのレポートのためにルノアール展を見に行ったのですが、とっても良かったです。ほんとに良かったです。少し離れてみたほうが雰囲気があって良かったです。
見終わったら、東京美術館のレストランでミックスフライを食べたんですが、味は好みはあると思いますが、インカ展の国立博物館のほうがメニューも良かったと思いました。
  1. 2012年08月10日 21:14 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製13(実機で動作1)

ビットマップ・ディスプレイ・コントローラの作製12(BitMapDCのインプリメント1)”の続き。

インプリメント後、Atlysボードの電源をONして、iMPACTでコンフィギュレーションしてみた。HDMIコネクタを液晶ディスプレイに接続したところ、No Signal になってしまった。
ビットマップ・ディスプレイ・コントローラのDDR2 SDRAMへアクセスするときのアドレスが0になっていた。DDR2 SDRAMのアドレスは、axi2axi_connector_0 でmicroblaze_0 につながっている関係上、0x20000000 のアドレスが付いている。よって、ビットマップ・ディスプレイ・コントローラのDDR2 SDRAMアクセス用アドレスを0x20000000とした。
それでも、DDR2 SDRAMコントローラ(MCB) のAXI4バスにChipScope AXI Monitor を入れてあるのでChipScope Analyzer で確かめてみた。
結果としては、MCBへのアクセスが無かった。そんなはずは無いのだが、下はARVALIDでトリガが掛からないので、フリーランのChipScopeのキャプチャデータだ。
BitMapDispCont_97_120810.png

ビットマップ・ディスプレイ・コントローラの単体シミュレーションでは、AXI4バスにRead Transaction が問題なく出ていた。(”AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製3(単体シミュレーション)”を参照)
次は、ビットマップ・ディスプレイ・コントローラのAXI4バスにChipScope AXI Monitor を仕掛けて見てみようと思う。
  1. 2012年08月10日 07:04 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製12(BitMapDCのインプリメント1)

ビットマップ・ディスプレイ・コントローラの作製11(BitMapDCの接続3)”の続き。

今回はPlanAheadに戻ってインプリメントしようと思う。

・XPSを閉じる。

・PlanAheadでsystem.xmp (XPS Project) を右クリックして、右クリックメニューから、Create Top HDL を行う。(TMDS信号を追加した)

・system_stub.ucf を開いて、TMDS信号の制約を追加した。下に制約を示す。

# 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;


・PlanAheadで、Project Manager のSynthesis -> Run Synthesis をクリックした。論理合成がスタートした。

・途中でエラーが出てしまった。エラーの内容を下に示す。

[Edk 24-166] (generate_target): Failed to execute XPS script. Please check for any errors reported by the XPS application in the console: [H:/HDL/FndtnISEWork/Spartan6/Atlys/test/Atlys_EDK_test_PA_142/Atlys_EDK_test_PA.srcs/sources_1/edk/system/__xps/pa/_system_synth.tcl]


BitMapDispCont_88_120807.png

エラーを検索してみたところ、”Can't synthesize microblaze system in EDK 14.2”が見つかったが、今年の8月1日に質問がアップされているが、まだ回答は無かった。

とりあえず、_system_synth.tcl を見てみることにした。Atlys_EDK_test_PA_142/Atlys_EDK_test_PA.srcs/sources_1/edk/system/__xps/paフォルダを下に示す。
BitMapDispCont_89_120807.png

_system_synth.tcl を下に示す。

######################################################
#
# XPS Tcl API script generated by PlanAhead
#
######################################################

proc _main_ {} {
  cd "H:/HDL/FndtnISEWork/Spartan6/Atlys/test/Atlys_EDK_test_PA_142/Atlys_EDK_test_PA.srcs/sources_1/edk/system"
  if { [ catch {xload xmp system.xmp} result ] } {
    exit 10
  }
  # Set host application type
  xset intstyle PA

  # Set design flow type
  xset flow ise

  # Set language type
  xset hdl verilog

  if { [catch {run netlist} result] } {
    return -1
  }
  return $result
}

# Generate Synthesized Netlists
if { [catch {_main_} result] } {
  exit -1
}

# Check return status and exit
if { [string length $result] == 0 } {
  exit 0
} else {
  exit $result
}


どこが悪いかわからないので、とりあえず、_system_synth.tcl を削除してみて、再生成をさせてみようと思った。

・_system_synth.tcl を削除して、もう一度、Synthesis -> Run Synthesis をクリックした。論理合成がスタートした。やはり同様のエラーが出た。

再生成された_system_synth.tcl と以前の_system_synth.tcl を比較してみたが、内容は同一だった。こうなるとXPSの設定がおかしいんだろう?

(2012/08/08:追加)
XPS単体でHardware メニューからGenarate Netlistをやってみたところエラーになった。エラー内容は、bitmap_afifoが見つからないとのことだった。

ERROR:HDLCompiler:1654 - "H:/HDL/FndtnISEWork/Spartan6/Atlys/test/Atlys_EDK_test_PA_142/Atlys_EDK_test_PA.srcs/sources_1/edk/system/pcores/bitmap_disp_cntrler_axi_master_v1_00_a/hdl/verilog/bitmap_disp_engine.v" Line 72: Instantiating from unknown module


bitmap_disp_cntrler_axi_master_v2_1_0.mpdのOPTION STYLE が”OPTION STYLE = HDL”になっていたので、”OPTION STYLE = MIX”に変更した。
やはり、同様にエラーになる。

(もう一度追加)
bitmap_afifo.ngc だけでなくbitmap_afifo.v をVerilog ファルダに追加して、bitmap_disp_cntrler_axi_master_v2_1_0.pao にbitmap_afifo.v のエントリを追加した。こうすると論理合成が成功した。インプリメント、ビットストリーム生成も成功した。
BitMapDispCont_94_120808.png

  1. 2012年08月07日 06:23 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製11(BitMapDCの接続3)

ビットマップ・ディスプレイ・コントローラの作製10(BitMapDCの接続2)”の続き。

今回は、XPS上でbitmap_disp_cntrler_axi_master の配線をつないでいく。

・XPSのBus Interfaceタブでbitmap_disp_cntrler_axi_master_0 のM_AXIをaxi_interconnect_0 に接続した。
BitMapDispCont_79_120806.png

・bitmap_disp_cntrler_axi_master_0 のM_AXIとaxi_s6_ddrx_0 のS0_AXI を接続した。
BitMapDispCont_80_120806.png

・Portsタブをクリックして、TMDSピンをすべてMake External した。
BitMapDispCont_82_120806.png

・ACLKをclk_100_0000MHz に接続した。
BitMapDispCont_83_120806.png

・External Ports でTMDS信号の名前が長すぎるので、Nameフィールドをクリックして修正した。
BitMapDispCont_84_120806.png

ビットマップ・ディスプレイ・コントローラの解像度はVGAとする。よってピクセルクロックとして25MHzをpixclk に入力する。

・clock generator_0 をダブルクリックして、XPS Core_Config を表示して、CLKOUT3を25MHz に設定した。
BitMapDispCont_85_120806.png

・bitmap_disp_cntrler_axi_master_0 のNet をクリックして、New Connectionを選択した。
・bitmap_disp_cntrler_axi_master_0_pixclk ネットが生成された。
BitMapDispCont_86_120806.png

・clock generator_0 のCLKOUT3 にbitmap_disp_cntrler_axi_master_0_pixclk を接続した。
BitMapDispCont_87_120806.png

・ProjectメニューからDesign Rule Check をやってみたところエラーは無かった。

エラーはなかったが、axi2axi_connector_0でWARNINGが出ていた。やはりAXI4 LiteとAXI4をつなぐのには無理があるのかな?

WARNING:EDK:3977 - AXI4 protocol type BUSIF: S0_AXI of IPINSTANCE: axi_s6_ddrx_0 connected with AXI4LITE type BUSIF: M_AXI of IPINSTANCE: axi2axi_connector_0.

  1. 2012年08月06日 05:01 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製10(BitMapDCの接続2)

ビットマップ・ディスプレイ・コントローラの作製9(BitMapDCの接続1)”の続き。

前回は、XPSでユーザーIPとして認識させる準備を行った。今回はXPSでbitmap_disp_cntrler_axi_master をユーザーIPとしてXPSのシステムに追加する。

・XPSのPoject メニューからRescan User Repositoriesを選択し、リポジトリを更新した。

・IP Catalog のDescription のProject Local PCores -> USER -> bitmap_disp_cntrler_axi_master が追加された。
BitMapDispCont_72_120804.png

・上のbitmap_disp_cntrler_axi_master を右クリックして、右クリックメニューからAdd IPを選択した。

・Add IP Instance to Desgin ダイアログが表示された。Yesボタンをクリックした。
BitMapDispCont_73_120804.png

・XPS Core Config ダイアログが立ち上がる。

・Userタブはデフォルトのままとした。
BitMapDispCont_74_120804.png

・Systemたぶでは、C_M_AXI_DATA_WIDTHを32から64に変更した。
・ビットマップ・ディスプレイ・コントローラはWriteを行わないので、 C_M_AXI_SUPPORTS_WRITEのチェックを外した。
BitMapDispCont_75_120804.png

・Interconnect Settings for BUSIFタブではデフォルトのままとした。
BitMapDispCont_76_120804.png

・OKボタンをクリックした。(この辺の設定については、”AXI4マスタIPのパラメータ”を参照)

・Instantiate and Connect IPダイアログが表示された。User will make necessary connections and settings のラジオボタンをクリックして、Okボタンをクリックした。
BitMapDispCont_77_120804.png

・bitmap_disp_cntrler_axi_master がXPSのシステムに追加された。
BitMapDispCont_78_120804.png
  1. 2012年08月05日 05:35 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

ビットマップ・ディスプレイ・コントローラの作製9(BitMapDCの接続1)

ビットマップ・ディスプレイ・コントローラの作製8(デバック1)”の続き。

MicroBlazeからDDR2 SDRAMを読み書きできない状態になっていたが、MCBの設定にAXI Supports Narrow BurstがあってAutoになっていたので、Enableにしてやってみたが、やはりAXI4バスのAWVALIDに反応していない。
今回は、64ビットバーストReadを試して見られるので、ビットマップ・ディスプレイ・コントローラ(BitMapDC) を追加してみることにした。元々はビットマップ・ディスプレイ・コントローラの作製なので、本当はこれがメインなのだが、MCBがMicroBlazeからアクセス出来ないため延び延びになってしまった。

・Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.srcs\sources_1\edk\system\pcoresフォルダに、bitmap_disp_cntrler_axi_master_v1_00_a がある。

・Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.srcs\sources_1\edk\system\pcores\bitmap_disp_cntrler_axi_master_v1_00_a\dataフォルダにテンプレートのままのファイルがある。
BitMapDispCont_67_120803.png

・ファイルの名前をbitmap_disp_cntrler_axi_master_v2_1_0 に変更した。
BitMapDispCont_68_120803.png

・まずは、bitmap_disp_cntrler_axi_master_v2_1_0.pao を編集して、HDLファイルを追加した。(2012/08/06:修正)(2012/08/09:修正 bitmap_afifo.v のエントリを追加した
(2012/12/13:修正、1行目と2行目が同じだったので、1行目を消しました。御指摘ありがとうございました。)

lib bitmap_disp_cntrler_axi_master_v1_00_a bitmap_disp_cntrler_axi_master.v verilog
lib bitmap_disp_cntrler_axi_master_v1_00_a axi_master_interface.v verilog
lib bitmap_disp_cntrler_axi_master_v1_00_a bitmap_disp_engine.v verilog
lib bitmap_disp_cntrler_axi_master_v1_00_a bitmap_afifo.v verilog
lib bitmap_disp_cntrler_axi_master_v1_00_a dvi_disp.vhd vhdl
lib bitmap_disp_cntrler_axi_master_v1_00_a Digilent_RTL/DVITransmitter.vhd vhdl
lib bitmap_disp_cntrler_axi_master_v1_00_a Digilent_RTL/TMDSEncoder.vhd vhdl
lib bitmap_disp_cntrler_axi_master_v1_00_a Digilent_RTL/SerializerN_1.vhd vhdl


・bitmap_disp_cntrler_axi_master_v2_1_0.bbd ファイルを追加して、bitmap_afifo.ngc を設定した。

FILES
bitmap_afifo.ngc


BitMapDispCont_69_120803.png

・同時にbitmap_afifo.ngc のVerilog ファイル(bitmap_afifo.v)もVerilog フォルダに追加した。(こうしないとbitmap_afifoが認識されないので注意)(2012/08/09:修正)
BitMapDispCont_96_120809.png

・bitmap_disp_cntrler_axi_master_v2_1_0.mpd を開いて、外部ポートを追加した。

PORT pixclk = "", DIR = I
PORT TMDS_tx_clk_p = "", DIR = O
PORT TMDS_tx_clk_n = "", DIR = O
PORT TMDS_tx_2_G_p = "", DIR = O
PORT TMDS_tx_2_G_n = "", DIR = O
PORT TMDS_tx_1_R_p = "", DIR = O
PORT TMDS_tx_1_R_n = "", DIR = O
PORT TMDS_tx_0_B_p = "", DIR = O
PORT TMDS_tx_0_B_n = "", DIR = O


・bitmap_disp_cntrler_axi_master_v2_1_0.mpd の下図のピンクの四角で囲ってある部分をbitmap_disp_cntrler_axi_master に変更した。
BitMapDispCont_71_120804.png

・bitmap_disp_cntrler_axi_master_v2_1_0.mpd の51行目、”OPTION STYLE = HDL”を”OPTION STYLE = MIX”に変更した。これはbitmap_fifo.ngc を使用することを宣言する設定だ。。(2012/08/09:修正)
BitMapDispCont_95_120808.png

・Atlys_EDK_test_PA_142\Atlys_EDK_test_PA.srcs\sources_1\edk\system\pcores\bitmap_disp_cntrler_axi_master_v1_00_a フォルダの下にnetlist フォルダを作成し、bitmap_afifo.ngc を追加した。
BitMapDispCont_70_120803.png
  1. 2012年08月04日 05:23 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:5

ビットマップ・ディスプレイ・コントローラの作製8(デバック1)

AXI4バスに接続するビットマップ・ディスプレイ・コントローラの作製7(MCBインプリメント4)”の続き。

今回は、どうしてMicroBlazeからDDR2 SDRAMがRead/Writeできないのか?探ってみることにした。具体的には、ChipScope AXI Monitor を追加して、AXIバスの動作をチェックすることにした。ChipScope AXI Monitor の追加の仕方については、”ChipScope AXI Monitor を試してみた”を参照のこと。ChipScope AXI Monitor の使い方に関しては、このブログに書いてあるので、ここでは詳しく書かない。

・”ChipScope AXI Monitor を試してみた”に従って、ChipScope AXI Monitor IPを追加した。なお、IP追加時の設定については下図を参照。axi_s6_ddrx_0のAXIバスを監視する。前回組み込んだProtocol Checker は組み込まなかった。
BitMapDispCont_60_120801.png

・XPSに戻るとchipscope_axi_monitor_0 が追加されて、MON_AXIは、axi_s6_ddrx_0.S0_AXIに接続されていた。
BitMapDispCont_61_120801.png

・Portsタブをクリックした時のchipscope_axi_monitor_0 の設定。
BitMapDispCont_62_120801.png

・XPSを終了して、PlanAhead14.2にもどって、論理合成、インプリメント、ビットストリームの生成を行った。下の画面は終了後だ。
BitMapDispCont_63_120801.png

・PlanAheadからChipScope Pro を立ち上げた。

・SDKにハードウェアをエクスポートしてSDKを立ちあげた。デバックモードでXMDを使用して、MCBのアドレスにWriteしてみた。Writeはうまくコマンドが終了していたので、最初にみることにした。ChipScope Pro のトリガをAXI_AWVALID に設定して、トリガ待ちに設定し、下のコマンドを入力した。

XMD% mwr 0x20000000 0x12345678


・キャプチャできたAXI4バスの動作を下に示す。
BitMapDispCont_64_120801.png

AXI4バスのパラメータを下に示す。(パラメータの値は、”AXI4バスのパラメータの意味”を参照のこと)

AWLEN -> 00 :転送長は1
AWSIZE -> 2 :1回のデータ転送で4バイト(32ビット)転送
AWBURST -> 1 :INCR  (アドレスをインクリメント)
AWLOCK -> 0 :ノーマル・アクセス
AWCACHE -> 0 :Device Non-bufferable
AWPORT -> 0 :Unprivileged access, Secure access, Data access

AXI_WDATA -> 1234567812345678
AXI_WSTRB -> 0F :AXI_WDATAの下4バイトが有効


・AWVALIDが1にアサートされているが、AWREADYが1にならない。axi_s6_ddrx_0がAWREADYをアサートしていないということになる。次にだいぶ時間が経過してしまったが、もう一度、シングルランで波形をキャプチャしてみた。それが下の図だ。
BitMapDispCont_65_120801.png

・AWVALIDが1になったままになっている。AWREADYが1にならないようだ。ちゃんとaxi_s6_ddrx_0が実装できているんだろうか? FPGA Editor で確かめてみることにした。FPGA Editor を立ちあげ、List1ウインドウで、*axi_s6_ddrx_0* で検索してaxi_s6_ddrx_0を表示させてみた。
BitMapDispCont_66_120801.png

しっかり、実装されていて問題は無いように見えた。やはり、32ビット幅、AXI4 Liteバスから64ビット幅AXI4バスにアクセスしているのがダメなのか?(MicroBlazeはAXI4 Lite Master 32ビットデータバス幅で、そこからReadコマンドを発行して、axi_s6_ddrx_0(MCB) のAXI4 Slave 64ビットデータ幅のデータをReadしようとしている)
AXI4バスのパラメータでも、AWSIZEが2で、4バイト転送になっている。DDR2 SDRAMは16ビットバス幅で、DDR2なのでプリフェッチ4と言うことは、64ビットデータが最小単位になる。ここでのAXI4バスアクセスは4バイト長(AWSIZEから)、つまり32ビットデータなので、DDR2 SDRAMに書き込むとすれば、後の32ビットデータはDMをインアクティブにしてWrite動作はしても書き込まないようにする必要がある。その辺の動作に齟齬があるのかもしれない?もしくは、そういう動作はできないのかも? axi_interconnect にそういう設定がないかどうか?調べてみたい。
  1. 2012年08月02日 04:57 |
  2. AXI4 Master IPの作製
  3. | トラックバック:0
  4. | コメント:0

メリダとおそろしの森(映画)を見てきました

今日は、今度の土曜日の代休でお休みだったので、7月28日に引き続いて、下の娘と今度はPIXARの”メリダとおそろしの森”を見てきました。3DのCGは素晴らしかったです。お笑いもあって良かったんですが、やはり、”おおかみこどもの雨と雪”の方が良かったです。
  1. 2012年08月01日 21:46 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

AXI4バスのパラメータの意味

AXI4バスのパラメータの意味についてブログに書いておく。いちいちIHI0022D_amba_axi_protocol_spec.pdfを見るのが面倒だからだ。(AMBA ® AXI ™ and ACE ™ Protocol Specification IHI0022D_amba_axi_protocol_spec.pdfを参考にさせて頂いた。)

・ARLEN[7:0], AWLEN[7:0]
8ビットの値+1 が転送長

・ARSIZE[2:0], AWSIZE[2:0]
------------------------------------
AxSIZE[2:0]  1回に転送するバイト数
------------------------------------
000       1
001       2
010       4
011       8
100       16
101       32
110       64
111       128
------------------------------------

・ARBURST[1:0], AWBURST[1:0]
-----------------------------------
AxBURST[1:0]  バースト・タイプ
-----------------------------------
00       FIXED (アドレス固定)
01       INCR  (アドレスをインクリメント)
10       WRAP  (キャッシュに使われるようにwrap aroundする。2,4,8,16バースト長のみ)
11       Reserved
-----------------------------------

・AxLOCK
----------------------------------
AxLOCK  アクセス・タイプ
----------------------------------
0     ノーマル・アクセス
1     排他的アクセス
----------------------------------

・ARCACHE[3:0], AWCACHE[3:0]
------------------------------------------------------------------------
ARCACHE[3:0]  AWCACHE[3:0]   メモリ・タイプ
------------------------------------------------------------------------
0000      0000       Device Non-bufferable
0001      0001       Device Bufferable
0010      0010       Normal Non-cacheable Non-bufferable
0011      0011       Normal Non-cacheable Bufferable
1010      0110       Write-through No-allocate
1110 (0110)  0110       Write-through Read-allocate
1010      1110 (1010)   Write-through Write-allocate
1110      1110       Write-through Read and Write-allocate
1011      0111       Write-back No-allocate
1111 (0111)  0111        Write-back Read-allocate
1011      1111 (1011)   Write-back Write-allocate
1111      1111       Write-back Read and Write-allocate
-------------------------------------------------------------------------

・ARPORT[2:0], AWPORT[2:0]
AxPROT[0] : 0 (Unprivileged access), 1 (Privileged access)
AxPROT[1] : 0 (Secure access), 1 (Non-secure access)
AxPROT[2] : 0 (Data access), 1 (Instruction access)

・ARQOS[3:0], AWQOS[3:0]
デフォルト値は 0000

・RRESP[1:0], BRESP[1:0]
----------------------------------------------------------------------
xRESP[1:0]  Response
----------------------------------------------------------------------
00       OKAY(通常のアクセスが成功した)
01       EXOKAY(排他的アクセスが成功した)
10       SLVERR(スレーブにアクセスが届いたけど、エラーを返した)
11       DECERR(デコード・エラー、インターコネクトでスレーブがそのアドレスにない)
----------------------------------------------------------------------
  1. 2012年08月01日 21:34 |
  2. AXI4バス
  3. | トラックバック:0
  4. | コメント:0