FC2カウンター FPGAの部屋 SOPC Builder
fc2ブログ

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

FPGAの部屋

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

Avalon-MMスレーブペリフェラル4(Nios2 IDEで7セグLEDをテスト)

KiCADをいじっていたので、前回と間が空いてしまったが、ダイナミック点灯7セグメントLEDのAvalon-MMスレーブペリフェラルをNios2 IDEでファームを作って動作チェックをしてみることにした。
まずはQuartus2のProgrammerでボードに書き込んでみた。そうすると7セグメントLEDはオール0を表示した。とりあえず合っているが、少し明るさが暗い感じだ。ダイナミック点灯の1KHzに周波数が高すぎるのか?それとも分周をミスって周波数が高いのかはわからない(オシロを持っていないので)後で実際に値を表示してみればわかると思う。
Nios2 9.0 IDEを立ち上げて、新しいboard_diagを作った。具体的にはFile メニューからNew -> NiosⅡ C/C++ Application を選択した。New Project ダイアログが起動した。
Name にboard_diag_7segと入れてPTFファイルを選択し、Finishボタンをクリックして、Board Diagnosticsテンプレートを生成した。
AvalonMMslave7seg_21_090829.png

Nios2 9.0 IDEの左のペインのboard_diag_7segのところで右クリックして、Build Projectを選択してプロジェクトをビルドした。
AvalonMMslave7seg_22_090829.png

board_diag_7seg_syslib\Debug\system_description\system.h にAvalonMM_Slave_Dyna7seg_0 configurationが出来ていた。

/*
* AvalonMM_Slave_Dyna7seg_0 configuration
*
*/

#define AVALONMM_SLAVE_DYNA7SEG_0_NAME "/dev/AvalonMM_Slave_Dyna7seg_0"
#define AVALONMM_SLAVE_DYNA7SEG_0_TYPE "AvalonMM_Slave_Dyna7seg"
#define AVALONMM_SLAVE_DYNA7SEG_0_BASE 0x00000020
#define AVALONMM_SLAVE_DYNA7SEG_0_SPAN 32
#define AVALONMM_SLAVE_DYNA7SEG_0_TERMINATED_PORTS ""
#define ALT_MODULE_CLASS_AvalonMM_Slave_Dyna7seg_0 AvalonMM_Slave_Dyna7seg


これからファームを書いて、7セグメントLEDをテストしする。
最初にboard_diag.cの既存の7セグメントLEDのテストルーチンを改造した。オリジナルは2ケタの7セグメントLEDに00からFFの表示をするものだった。今回のボードは8桁あるので、2桁ずつ00からFFまで表示するようにした。下にそのCコードを示す。

static void SevenSegCount( void )
{
  alt_u32 count;
  
  for (count = 0; count <= 0xff; count++)
  {
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+4, count>>4);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+8, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+12, count>>4);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+16, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+20, count>>4);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+24, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+28, count>>4);
    usleep(500000);
  }
}


上のコードに書き換えて、他のところもつじつまの合わない部分を書き換えて、左側のペインのboard_diag_0 で右クリックしてRun As -> Nois Ⅱ Hardware を選択しmakeした。
その結果、表示が全く読めない。ただし、全部のLEDに同じ数字がそろうときにはきちんと読むことができる。
次に、先ほどのコードをしたように変更して、全部の7セグLEDに同じ表示が出るようにした。

static void SevenSegCount( void )
{
  alt_u32 count;
  
  for (count = 0; count <= 0xff; count++)
  {
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+4, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+8, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+12, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+16, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+20, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+24, count&0xf);
    IOWR_ALTERA_AVALON_PIO_DATA(AVALONMM_SLAVE_DYNA7SEG_0_BASE+28, count&0xf);
    usleep(500000);
  }
}


そうするときちんと表示されてたのだが、Dを表示した後にFになっている。Eが抜けているようだ。B27segDec.vのソースを見るとEを表示する記述が抜けていた。失敗。。。早速、Eを表示する記述を書き加えた。
表示がおかしいのは、7セグLEDのダイナミック点灯の周波数が高くて、スイッチング用のトランジスタが間に合っていないのが原因じゃないかと思う。
上記の項目を修正して、もう一度Quartus2でコンパイル、Nios2 9.0 IDEでBuild Projectを行った。
今度はEは点灯したが、やはり表示がおかしい。


わかりました。ケアレスミスです。それは。。。

AvalonMM_Slave_Dyna7seg.vファイルのseven_seg_digitを接続するのを忘れていました。道理でこれでは表示がおかしくなるはずです。

assign seven_seg_digit = drive_led;


を追加しました。これで正常になるでしょう。元も直しておきました。でもQuartus2ではエラーにならないんですね。ISEでは確実にピンがなくなり、UCFと合わないので、Translateでエラーが出ます。
これでまた、もう一度やり直して、Consoleでボードと通信ができるようになりました。下はNios2 9.0 IDEの一番下のConsoleペインです。Main Menuからd: Seven Segmeent Menuを選択するためにSelect Choiceに d +リターンキーを入力します。
AvalonMMslave7seg_24_090903.png

Seven Segment Menuからa: Count From 0 to FF. を選択するために a +リターンキーを入力します。b:は実装してありません。
AvalonMMslave7seg_25_090903.png

そうすると、ボードの7セグメントLED8個が4つの組で00からFFまでカウントを始めました。良かった。ケアレスミスでした。
AvalonMMslave7seg_090904.jpg

紆余曲折、途中でKiCADに浮気するというアクシデントはあったが、曲がりなりにもAvalon-MMスレーブペリフェラルを実装することができて、良かった。
  1. 2009年09月04日 06:06 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:0

Avalon-MMスレーブペリフェラル3(Quartus2でのコンパイル)

Avalon-MMスレーブペリフェラル2(SOPC Builder)”の続き。KiCADもやりたいが、これも終わらせないと。。。
前回、SOPC Builderで7セグメントLEDのダイナミック点灯回路を追加して生成したので、今回はトップのVerilogファイルにダイナミック点灯7セグメントLEDの出力ポートを追加してコンパイルする。
まずは、前回のSOPC Builderのインスタンス時のポートは以下のようになった。

  nois_sdram nois_sdram_inst
    (
      .clk_0                                              (clk_0),
      .out_port_from_the_led_pio                          (out_port_from_the_led_pio),
      .reset_n                                            (reset_n),
      .seven_seg_a_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_a_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_b_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_b_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_c_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_c_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_d_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_d_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_digit_from_the_AvalonMM_Slave_Dyna7seg_0 (seven_seg_digit_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_dp_from_the_AvalonMM_Slave_Dyna7seg_0    (seven_seg_dp_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_e_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_e_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_f_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_f_from_the_AvalonMM_Slave_Dyna7seg_0),
      .seven_seg_g_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_g_from_the_AvalonMM_Slave_Dyna7seg_0),
      .zs_addr_from_the_sdram                             (zs_addr_from_the_sdram),
      .zs_ba_from_the_sdram                               (zs_ba_from_the_sdram),
      .zs_cas_n_from_the_sdram                            (zs_cas_n_from_the_sdram),
      .zs_cke_from_the_sdram                              (zs_cke_from_the_sdram),
      .zs_cs_n_from_the_sdram                             (zs_cs_n_from_the_sdram),
      .zs_dq_to_and_from_the_sdram                        (zs_dq_to_and_from_the_sdram),
      .zs_dqm_from_the_sdram                              (zs_dqm_from_the_sdram),
      .zs_ras_n_from_the_sdram                            (zs_ras_n_from_the_sdram),
      .zs_we_n_from_the_sdram                             (zs_we_n_from_the_sdram)
    );


AvalonMM_Slave_Dyna7seg_0の信号が増えている。これをトップのnios2_sdram_led.vに追加した。下に全ソースを示す。

// nois2_sdram_led

`default_nettype none

module nois2_sdram_led(
    input    wire         clk,
    input    wire        reset_n,
    output    wire [7:0]    led_pio, 
    output    wire        sdram_clk,
    output    wire [11:0]    SDRAM_A,
    output    wire [1:0]    SDRAM_BA,
    output    wire        SDRAM_nCAS,
    output    wire        SDRAM_CKE,
    output    wire        SDRAM_nCS,
    inout    wire [15:0]    SDRAM_D,
    output    wire [1:0]    SDRAM_DQM,
    output    wire        SDRAM_nRAS,
    output    wire        SDRAM_nWE,
    
    output    wire [7:0]    seven_seg_digit,
    output    wire        seven_seg_a,
    output    wire        seven_seg_b,
    output    wire        seven_seg_c,
    output    wire        seven_seg_d,
    output    wire        seven_seg_e,
    output    wire        seven_seg_f,
    output    wire        seven_seg_g,
    output    wire        seven_seg_dp
);
    
    wire clk_pll;
    wire pll_locked;
    reg        [10:0] count;
    wire reset_n_int_node, reset_n_int;

  nois_sdram nois_sdram_inst
    (
      .clk_0                             (clk_pll),
      .out_port_from_the_led_pio (led_pio),
      .reset_n                           (reset_n_int),
      .seven_seg_a_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_a),
      .seven_seg_b_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_b),
      .seven_seg_c_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_c),
      .seven_seg_d_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_d),
      .seven_seg_digit_from_the_AvalonMM_Slave_Dyna7seg_0 (seven_seg_digit),
      .seven_seg_dp_from_the_AvalonMM_Slave_Dyna7seg_0    (seven_seg_dp),
      .seven_seg_e_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_e),
      .seven_seg_f_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_f),
      .seven_seg_g_from_the_AvalonMM_Slave_Dyna7seg_0     (seven_seg_g),
      .zs_addr_from_the_sdram          (SDRAM_A),
      .zs_ba_from_the_sdram            (SDRAM_BA),
      .zs_cas_n_from_the_sdram         (SDRAM_nCAS),
      .zs_cke_from_the_sdram           (SDRAM_CKE),
      .zs_cs_n_from_the_sdram          (SDRAM_nCS),
      .zs_dq_to_and_from_the_sdram     (SDRAM_D),
      .zs_dqm_from_the_sdram           (SDRAM_DQM),
      .zs_ras_n_from_the_sdram         (SDRAM_nRAS),
      .zs_we_n_from_the_sdram          (SDRAM_nWE)
    );
    
    altpllpll altpllpll_inst(
        .inclk0 ( clk ),
        .c0 ( clk_pll ),
        .c1 ( sdram_clk ),
        .locked ( pll_locked )
    );
    
    always @(posedge clk) begin
        if (!reset_n)
            count <= 11'd0;
        else begin
            if (count[10]==1'b0)
                count <= count + 11'd1;
        end
    end
    assign reset_n_int_node = count[10];
    assign reset_n_int = reset_n_int_node & pll_locked;    
endmodule


Quartus?のAnalysis & Synthesisは通ったので、今度はPin Plannerでピンを設定した。下のPin Plannerの様子。
AvalonMMslave7seg_19_090829.png

これでQuartus2でデザインをコンパイルした。成功し、Total logic elementsは88%となった。
AvalonMMslave7seg_20_090829.png

現在の状態はNios2/s を実装し、SignalTap?を実装、おまけにEnable Burstビットをチェックしている状態。以前のダイナミック点灯7セグメントLED回路を入れる前の
Total logic elementsは85%なので、3%増えていることになる。下が以前のSummary。
Nios2_IDE_90_30_090819.png
  1. 2009年08月29日 05:47 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:0

Avalon-MMスレーブペリフェラル2(SOPC Builder)

Avalon-MMスレーブペリフェラル1(ダイナミック点灯7セグLED)”の続き。
前回は8個のダイナミック点灯7セグメントLEDを制御するAvalon-MMスレーブペリフェラルのVerilogコードを作成したが、これをSOPC Builderに登録する。
これらの作業は、FPGA技術No.5の備州長船さんの第3章 THE AVALONM@STER(Avalon-MMスレーブペリフェラルの作成方法)を参考にさせていただいています。

さて、QuartusⅡからSOPC Builderを立ち上げる。SPOC Builder の内容は下のような感じ。PLLを外に追い出してあるので、PLLは入っていない。前回、作ったVerilogファイルを追加するためにNewボタンをクリックした。
AvalonMMslave7seg_2_090827.png

Component Editorが起動した。Next-> ボタンをクリックした。
AvalonMMslave7seg_3_090827.png

最初にAdd..ボタンをクリックして、トップモジュールのAvalonMM_Slave_Dyna7seg.vを追加した状態。Warningが出ている。
AvalonMMslave7seg_4_090827.png

次に、FreqDiv.vとB27segDec.vも追加した。Warningが出ているのはFPGA技術No.5によると問題ないそうなので、Next-> ボタンをクリックした。(ちなみにFPGA技術No.5には詳しい説明などがいろいろ書いてある)
AvalonMMslave7seg_5_090827.png

Signalsのタブに行くと、下のようになっていた。
AvalonMMslave7seg_6_090827.png

この信号のうち、seven_seg_digit, seven_seg_a, seven_seg_b, seven_seg_c, seven_seg_d, seven_seg_e, seven_seg_f, seven_seg_g, seven_seg_dp を外部信号として登録する。まずはseven_seg_digitのInterfaceをクリックして、New Conduit... を選択した。
AvalonMMslave7seg_7_090827.png

次にSignal Typeからexportを選択した。
AvalonMMslave7seg_8_090827.png

これで外部信号として認識されたそうだ。seven_seg_a, seven_seg_b, seven_seg_c, seven_seg_d, seven_seg_e, seven_seg_f, seven_seg_g, seven_seg_dp も続けてInterfaceをクリックしてconduit_endを選択し、Signal Typeからexportを選択した。Next-> ボタンをクリックした。
AvalonMMslave7seg_9_090827.png

Interfaceタブだが、凄い。。。いろいろなバスの設定などをGUIで出来るみたい。完成度が高そう?
AvalonMMslave7seg_10_090827.png

Signalタブで選択した外部信号もあったが、全部表示されていない。が大丈夫なんだろう?
AvalonMMslave7seg_11_090827.png

波形の下のDeprecatedを展開して、Slave addressing をNATIVEにした。これは、バイトアクセスを許可しないスレーブペリフェラルの場合は必ずNATIVEにする必要があるそうだ。
AvalonMMslave7seg_12_090827.png

次はWarningを消します。Remove Interface With No Signalsボタンをクリックすると、信号を持たないインターフェースが消えて、Warningが消えました。下の図はハイドされていますが、Warningがある時は正常の状態でした。
AvalonMMslave7seg_13_090827.png

Next-> ボタンをクリックしたら、次はComponent Wizardタブ。Group:をPeripheralsに指定した。これで終了なので、Finishボタンをクリックした。
AvalonMMslave7seg_14_090827.png

Save Changesダイアログが開くので、Yes,Saveボタンをクリックした。
AvalonMMslave7seg_15_090827.png

SOPC Builderに戻ると、System ContentsにAvalonMM_Slave_Dyna7segが登録されているので、それを選んでAdd...ボタンをクリックすると、AvalonMM_Slave_Dyna7segが登録された。
AvalonMMslave7seg_16_090827.png

アドレスを見ると0x20から0x3fまでの32バイトアサインされている。これは32ビットレジスタ8個分ということになって、Verilogファイルと合致している。これで終了なので、Finishボタンをクリックした。
Save Changes?ダイアログが出るので、Yesボタンをクリックした。
System generationが成功しました。良かったです。
AvalonMMslave7seg_17_090827.png

QuartusⅡに戻ってコンパイルした。コンパイル成功。
Entityを見ると、AvalonMM_Slave_Dyna7segが入っていた。Total logic elementsは 87% で以前に比べ 2% 増えていたが、まだSOPC Builderで作ったNiosⅡプロセッサのインスタンスに7セグメント関係の入出力が出ているはず。それをトップに接続する必要があるので、もっと増えると思う。次の回でそれらを行う。(2009/08/28 修正)
AvalonMMslave7seg_18_090827.png


FPGA技術No.5では、PCMコアの補足資料も付いています。上のAvalonMM_Slave_Dyna7seg はIRQを付けませんでしたが、IRQの接続方法も載っています。
  1. 2009年08月27日 21:03 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:4

Avalon-MMスレーブペリフェラル1(ダイナミック点灯7セグLED)

FPGA技術No.5の備州長船さんの第3章 THE AVALONM@STER(Avalon-MMスレーブペリフェラルの作成方法)を参考に、ダイナミック7セグメントLED用のAvalon-MMスレーブペリフェラルを試しに作成中だ。
まずはVerilogファイルの作成をした。トップをAvalonMM_Slave_Dyna7seg.vとしてAvalonバスのRead、Writeを実装して、7セグメントLEDのダイナミック点灯回路も実装した。ダイナミック点灯の周波数は1KHz、これは以前から使用しているFreqdiv.vを使用した。7セグメントLEDのデコーダーには、これまた以前から使用しているB27segDec.vを使用した。それぞれのソースを示す。
まずは、AvalonMM_Slave_Dyna7seg.v

// Dynamic 7segment Display test
//    avs_s1_address = 0 : seven_value0(下位5ビットのみ使用)
//    avs_s1_address = 1 : seven_value1(下位5ビットのみ使用)
//    avs_s1_address = 2 : seven_value2(下位5ビットのみ使用)
//    avs_s1_address = 3 : seven_value3(下位5ビットのみ使用)
//    avs_s1_address = 4 : seven_value4(下位5ビットのみ使用)
//    avs_s1_address = 5 : seven_value5(下位5ビットのみ使用)
//    avs_s1_address = 6 : seven_value6(下位5ビットのみ使用)
//    avs_s1_address = 7 : seven_value7(下位5ビットのみ使用)
//  +16をするとDPが点灯


`default_nettype none

module AvalonMM_Slave_Dyna7seg(
    input    wire        csi_global_reset,    // リセット
    input    wire        csi_global_clk,        // クロック
    input    wire[2:0]    avs_s1_address,        // アバロンバス
    input    wire        avs_s1_read,        // アバロンバス
    output    reg[31:0]    avs_s1_readdata,    // アバロンバス
    input    wire        avs_s1_write,        // アバロンバス
    input    wire[31:0]    avs_s1_writedata,    // アバロンバス
    output    wire[7:0]    seven_seg_digit,    // 外部出力、7セグメントLEDデジット
    output    reg            seven_seg_a,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_b,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_c,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_d,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_e,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_f,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_g,        // 外部出力、7セグメントLEDセグメント
    output    reg            seven_seg_dp        // 外部出力、7セグメントLEDセグメント
);
    reg[7:0] seven_value [7:0]; // 7セグメントの表示
    reg[31:0] avs_s1_readdata_node;
    reg[7:0] drive_led; // 7セグLEDを指定するカウント
    wire disp_ena;
    reg[3:0] led_binary;
    wire[6:0] segdecout;
    
    
    // avalon bus write
    always @(posedge csi_global_clk, posedge csi_global_reset) begin : SEVEN_VALUE_PROCESS
        integer i; // ローカル変数iの宣言
        
        if (csi_global_reset) begin
            for (i=0; i<8 ; i=i+1) begin
                seven_value[i] <= 8'd0;
            end
        end else begin
            if (avs_s1_write) begin
                case(avs_s1_address)
                    3'b000 :
                        seven_value[0] <= avs_s1_writedata[7:0];
                    3'b001 :
                        seven_value[1] <= avs_s1_writedata[7:0];
                    3'b010 :
                        seven_value[2] <= avs_s1_writedata[7:0];
                    3'b011 :
                        seven_value[3] <= avs_s1_writedata[7:0];
                    3'b100 :
                        seven_value[4] <= avs_s1_writedata[7:0];
                    3'b101 :
                        seven_value[5] <= avs_s1_writedata[7:0];
                    3'b110 :
                        seven_value[6] <= avs_s1_writedata[7:0];
                    3'b111 :
                        seven_value[7] <= avs_s1_writedata[7:0];
                endcase
            end
        end
    end
    
    // avalon bus read
    always @* begin
        avs_s1_readdata[31:8] = 24'd0;
        case (avs_s1_address)
            3'b000 :
                avs_s1_readdata[7:0] <= seven_value[0];
            3'b001 :
                avs_s1_readdata[7:0] <= seven_value[1];
            3'b010 :
                avs_s1_readdata[7:0] <= seven_value[2];
            3'b011 :
                avs_s1_readdata[7:0] <= seven_value[3];
            3'b100 :
                avs_s1_readdata[7:0] <= seven_value[4];
            3'b101 :
                avs_s1_readdata[7:0] <= seven_value[5];
            3'b110 :
                avs_s1_readdata[7:0] <= seven_value[6];
            default : // 3'b111
                avs_s1_readdata[7:0] <= seven_value[7];
        endcase
    end
    
    // LED選択用シフトレジスタ
    always @(posedge csi_global_clk) begin
        if (csi_global_reset)
            drive_led <= 8'b1111_1110;
        else begin
            if (disp_ena) begin
                if (drive_led[7]==1'b0) // 最後の次はdrive_led[0]を0にする
                    drive_led <= 8'b1111_1110;
                else
                    drive_led <= {drive_led[6:0], 1'b1}; // 0を1ビットシフト
            end
        end
    end
    assign seven_seg_digit = drive_led;
    
    // LEDリフレッシュ周波数分周器
    FreqDiv FreqDiv_inst(
        .clk(csi_global_clk),
        .reset(csi_global_reset),
        .disp_ena(disp_ena)
    );
        
    // 7セグメント・デコーダ
    B27segDec B27segDec_inst(
        .binary(led_binary),
        .enable(1'b1),
        .segdecout(segdecout)
    );
    
    // 7セグメント・デコーダに入れるバイナリデータの選択と出力の選択
    always @(posedge csi_global_clk) begin : SELECTED_BINAREY_DATA
        integer i; // ローカル変数の宣言
        
        if (csi_global_reset) begin
            led_binary <= 4'd0;
            {seven_seg_dp, seven_seg_a, seven_seg_b, seven_seg_c, seven_seg_d, seven_seg_e, seven_seg_f, seven_seg_g} <= -1;
        end else begin
            for(i=0; i<8; i=i+1) begin
                if (drive_led[i]==1'b0) begin
                    led_binary <= seven_value[i];
                    {seven_seg_dp, seven_seg_a, seven_seg_b, seven_seg_c, seven_seg_d, seven_seg_e, seven_seg_f, seven_seg_g} <= {~seven_value[i][4], ~segdecout}; // 0で点灯なのでsegdecoutを反転する
                end
            end
        end
    end
endmodule


(2009/09/04 更新:AvalonMM_Slave_Dyna7seg.vのseven_seg_digit出力に信号がつながっていなかったので、追加しました。詳しくは”Avalon-MMスレーブペリフェラル4(Nios2 IDEで7セグLEDをテスト)”を参照ください)

次はFreqdiv.v

//入力クロックをダイナミック点灯時の周波数(1KHz)に分周する
// 1KHz clock
// マスタークロックを1KHzのdisp_enaに分周します。
// クロック周波数をclk_frequencyにKHz単位で設定してください。defaultで50MHzです。
// lcntが16ビットになっているので、clk_frequencyが65536以上の場合はビットを増やしてください。
// sync resetに変更

`default_nettype none
`timescale 1ns / 1ps

module FreqDiv(clk, reset, disp_ena);
    input clk, reset;
    output disp_ena;
    wire clk, reset;
    wire disp_ena;
    
    reg [20:0] lcnt;
    
    parameter clk_frequency = 50000;
    
    always @(posedge clk) begin
        if (reset)
            lcnt <= 0;
        else if (lcnt==clk_frequency)
            lcnt <= 0;
        else
            lcnt <= lcnt + 1;
    end
    
    assign disp_ena = (lcnt==clk_frequency);
endmodule


最後にB27segDec.v

// Frequncy Divider for Dynamic Lighting
// 1KHz clock
// マスタークロックを1KHzのdisp_enaに分周します。
// クロック周波数をclk_frequencyにKHz単位で設定してください。defaultで50MHzです。
// Binary to 7 segment LED Decoder
// バイナリデータを7セグメントLED用のデータに変換します。
// enableを0にすると消灯。
// 点灯するセグメントを1で表しているが、実際には0で点灯するので上のファイルで反転しています。


`default_nettype none
`timescale 1ns / 1ps

module B27segDec(binary, enable, segdecout);
    input [3:0] binary;
    input enable;
    output [6:0] segdecout;
    
    wire [3:0] binary;
    wire enable;
    reg [6:0] segdecout;
    
    always @* begin
        if (enable)
            case (binary)
                4'h0 :
                    segdecout = 7'b1111110;
                4'h1 :
                    segdecout = 7'b0110000;
                4'h2 :
                    segdecout = 7'b1101101;
                4'h3 :
                    segdecout = 7'b1111001;
                4'h4 :
                    segdecout = 7'b0110011;
                4'h5 :
                    segdecout = 7'b1011011;
                4'h6 :
                    segdecout = 7'b1011111;
                4'h7 :
                    segdecout = 7'b1110000;
                4'h8 :
                    segdecout = 7'b1111111;
                4'h9 :
                    segdecout = 7'b1111011;
                4'hA :
                    segdecout = 7'b1110111;
                4'hB :
                    segdecout = 7'b0011111;
                4'hC :
                    segdecout = 7'b1001110;
                4'hD :
                    segdecout = 7'b0111101;
                default : // F
                    segdecout = 7'b1000111;
            endcase
        else
            segdecout = 7'b1111111;
    end
endmodule


これらをシミュレーションするために、テストベンチAvalonMM_Slave_Dyna7seg_tb.vを作成してVeritakでシミュレーションしてみた。
テストベンチAvalonMM_Slave_Dyna7seg_tb.vを下に示す。

// AvalonMM_Slave_Dyna7seg_tb

`default_nettype none
`timescale 1ns / 1ps

module AvalonMM_Slave_Dyna7seg_tb;
    reg            csi_global_reset;    // リセット
    reg            csi_global_clk;        // クロック
    reg[2:0]    avs_s1_address;        // アバロンバス
    reg            avs_s1_read;        // アバロンバス
    wire[31:0]    avs_s1_readdata;    // アバロンバス
    reg         avs_s1_write;        // アバロンバス
    reg[31:0]    avs_s1_writedata;    // アバロンバス
    wire[7:0]    seven_seg_digit;    // 外部出力、7セグメントLEDデジット
    wire        seven_seg_a;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_b;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_c;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_d;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_e;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_f;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_g;        // 外部出力、7セグメントLEDセグメント
    wire        seven_seg_dp;        // 外部出力、7セグメントLEDセグメント

    parameter CLK_PERIOD = 20;
    
    defparam AvalonMM_Slave_Dyna7seg_inst.FreqDiv_inst.clk_frequency = 5; // シミュレーション用にカウント数を小さくする
    AvalonMM_Slave_Dyna7seg AvalonMM_Slave_Dyna7seg_inst(
        .csi_global_reset(csi_global_reset),
        .csi_global_clk(csi_global_clk),
        .avs_s1_address(avs_s1_address),
        .avs_s1_read(avs_s1_read),
        .avs_s1_readdata(avs_s1_readdata),
        .avs_s1_write(avs_s1_write),
        .avs_s1_writedata(avs_s1_writedata),
        .seven_seg_digit(seven_seg_digit),
        .seven_seg_a(seven_seg_a),
        .seven_seg_b(seven_seg_b),
        .seven_seg_c(seven_seg_c),
        .seven_seg_d(seven_seg_d),
        .seven_seg_e(seven_seg_e),
        .seven_seg_f(seven_seg_f),
        .seven_seg_g(seven_seg_g),
        .seven_seg_dp(seven_seg_dp)
    );
    
    initial begin
                csi_global_reset = 1'b1;
        #100    csi_global_reset = 1'b0;
    end
    
    always begin
       #(CLK_PERIOD/2)    csi_global_clk = 1'b1 ;
       #(CLK_PERIOD/2)    csi_global_clk = 1'b0 ;
    end
    
    task AVALON_BUS_WRITE;
        input[2:0]    write_address;
        input[31:0]    write_data;
        
        begin
            @(posedge csi_global_clk); // 次のクロックの立ち上がり
            #1;
            avs_s1_write = 1'b1; // Write
            avs_s1_address = write_address;
            avs_s1_writedata = write_data;
            @(posedge csi_global_clk); // 次のクロックの立ち上がり
            #1;
            avs_s1_write = 1'b0;
        end
    endtask
    
    task AVALON_BUS_READ;
        input[2:0]    read_address;
        
        begin
            @(posedge csi_global_clk); // 次のクロックの立ち上がり
            #1;
            avs_s1_address = read_address;
            @(posedge csi_global_clk); // 次のクロックの立ち上がり
            #1;
        end
    endtask
    
    initial begin
        avs_s1_address = 3'd0;
        avs_s1_read = 1'b0;
        avs_s1_write = 1'b0;
        avs_s1_writedata = 32'd0;
        
        #100;
        AVALON_BUS_WRITE(3'd0, 32'h0000_0001);
        AVALON_BUS_WRITE(3'd1, 32'h0000_0002);
        AVALON_BUS_WRITE(3'd2, 32'h0000_0003);
        AVALON_BUS_WRITE(3'd3, 32'h0000_0004);
        AVALON_BUS_WRITE(3'd4, 32'h0000_0005);
        AVALON_BUS_WRITE(3'd5, 32'h0000_0006);
        AVALON_BUS_WRITE(3'd6, 32'h0000_0007);
        AVALON_BUS_WRITE(3'd7, 32'h0000_0008);
        #100;
        AVALON_BUS_READ(3'd0);
        AVALON_BUS_READ(3'd1);
        AVALON_BUS_READ(3'd2);
        AVALON_BUS_READ(3'd3);
        AVALON_BUS_READ(3'd4);
        AVALON_BUS_READ(3'd5);
        AVALON_BUS_READ(3'd6);
        AVALON_BUS_READ(3'd7);
        #500;
        $stop;
    end
endmodule


シミュレーションした結果の波形を下に示す。
AvalonMMslave7seg_1_090826.png

次はSOPC Builderでコンポーネントの追加をする予定。
  1. 2009年08月26日 05:20 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:0

SOPC Builderを使ってみる3(IOピンやタイミング制約を加えてテスト)

SOPC Builderを使ってみる2(NiosⅡのインスタンシエーション)”でコンパイルは通ったので、今度はIOピンや動作周波数などのタイミング制約を入力してコンパイルし、テストしてみる。
まずは、”QuartusⅡでSignalTapⅡを試してみるまでの準備5(入力、出力ピンの制約とタイミング制約)”を参照してPin Plannerを立ち上げて、IOピンの配置を制約する。途中までIOピンを入力したのだが、QuartusⅡでのIOピンの制約ファイルはどれなんだろう? ISEだと、配置制約もタイミング制約も.ucf というファイルに全部書いてあったが、QuartusⅡのタイミング制約を書いたファイルは、”QuartusⅡでSignalTapⅡを試してみるまでの準備6(入力、出力ピンの制約とタイミング制約2)”でやってみたように.sdc だった。
下に途中まで入力したPin Plannerを示す。
SOPC_Builder_15_090806.png

入出力ピンの制約ファイルをフォルダから探ってみたが、どうやら nois2_sdram_led.qsf というのがそうらしい。下に nois2_sdram_led.qsf を示す。

# -------------------------------------------------------------------------- #
#
# Copyright (C) 1991-2009 Altera Corporation
# Your use of Altera Corporation's design tools, logic functions
# and other software and tools, and its AMPP partner logic
# functions, and any output files from any of the foregoing
# (including device programming or simulation files), and any
# associated documentation or information are expressly subject
# to the terms and conditions of the Altera Program License
# Subscription Agreement, Altera MegaCore Function License
# Agreement, or other applicable license agreement, including,
# without limitation, that your use is for the sole purpose of
# programming logic devices manufactured by Altera and sold by
# Altera or its authorized distributors. Please refer to the
# applicable agreement for further details.
#
# -------------------------------------------------------------------------- #
#
# Quartus II
# Version 9.0 Build 184 04/29/2009 Service Pack 1 SJ Web Edition
# Date created = 19:20:23 July 31, 2009
#
# -------------------------------------------------------------------------- #
#
# Notes:
#
# 1) The default values for assignments are stored in the file:
# nios2_sdram_led_assignment_defaults.qdf
# If this file doesn't exist, see file:
# assignment_defaults.qdf
#
# 2) Altera recommends that you do not modify this file. This
# file is updated automatically by the Quartus II software
# and any changes you make may be lost or overwritten.
#
# -------------------------------------------------------------------------- #


set_global_assignment -name FAMILY "Cyclone II"
set_global_assignment -name DEVICE EP2C5Q208C8
set_global_assignment -name TOP_LEVEL_ENTITY nois2_sdram_led
set_global_assignment -name ORIGINAL_QUARTUS_VERSION "9.0 SP1"
set_global_assignment -name PROJECT_CREATION_TIME_DATE "19:20:23 JULY 31, 2009"
set_global_assignment -name LAST_QUARTUS_VERSION "9.0 SP1"
set_global_assignment -name EDA_SIMULATION_TOOL ""
set_global_assignment -name EDA_TIME_SCALE "1 ps" -section_id eda_simulation
set_global_assignment -name EDA_OUTPUT_DATA_FORMAT NONE -section_id eda_simulation
set_global_assignment -name USE_GENERATED_PHYSICAL_CONSTRAINTS OFF -section_id eda_blast_fpga
set_global_assignment -name DEVICE_FILTER_PACKAGE PQFP
set_global_assignment -name DEVICE_FILTER_PIN_COUNT 208
set_global_assignment -name MIN_CORE_JUNCTION_TEMP 0
set_global_assignment -name MAX_CORE_JUNCTION_TEMP 85
set_global_assignment -name QIP_FILE nois_sdram.qip
set_global_assignment -name VERILOG_FILE nois2_sdram_led.v
set_global_assignment -name PARTITION_NETLIST_TYPE SOURCE -section_id Top
set_global_assignment -name PARTITION_COLOR 16764057 -section_id Top
set_global_assignment -name LL_ROOT_REGION ON -section_id "Root Region"
set_global_assignment -name LL_MEMBER_STATE LOCKED -section_id "Root Region"
set_instance_assignment -name PARTITION_HIERARCHY root_partition -to | -section_id Top
set_global_assignment -name STRATIX_DEVICE_IO_STANDARD "3.3-V LVTTL"
set_location_assignment PIN_152 -to SDRAM_A[11]
set_location_assignment PIN_187 -to SDRAM_A[10]
set_location_assignment PIN_160 -to SDRAM_A[9]
set_location_assignment PIN_161 -to SDRAM_A[8]
set_location_assignment PIN_162 -to SDRAM_A[7]
set_location_assignment PIN_163 -to SDRAM_A[6]
set_location_assignment PIN_164 -to SDRAM_A[5]
set_location_assignment PIN_165 -to SDRAM_A[4]
set_location_assignment PIN_185 -to SDRAM_A[3]
set_location_assignment PIN_182 -to SDRAM_A[2]
set_location_assignment PIN_181 -to SDRAM_A[1]
set_location_assignment PIN_180 -to SDRAM_A[0]
set_location_assignment PIN_188 -to SDRAM_BA[1]
set_global_assignment -name MISC_FILE "H:/HDL/Altera/qdesigns/nisyo_board/nios2_sdram_led/nios2_sdram_led.dpf"


一度、Pin Planner を終了して、試しに nois2_sdram_led.qsf に下の行をBA[1]のすぐ下の行にテキストエディタで追加してみる。

set_location_assignment PIN_189 -to SDRAM_BA[0]


再びPin Planner を立ち上げるとSDRAM_BA[0] のピン制約が入っていました。
SOPC_Builder_16_090806.png

これでPin Planner だけでなく、テキストエディタでIOピン制約のコピー&ペーストができるようになった。
すべてのIOピンの制約を入力した。ところで、Pin Planner を設定していて思ったのだけれど、AlteraのFPGAのデフォルト出力電流値は24mAに設定されているのですね?Xilinxは12mAだと思ったけど、倍の電流を流していますね。これだと波形の立ち上がりは速くなるし、クロックエッジからの出力の立ち上がり時間も速くなると思うけど。。。SSOや波形のリンキングはどうなのかな?と思ったりする。特にQFPだし。。。でもそんなところまで気にするような動作周波数ではないかな?とりあえずデフォルトで行くことにする。

次はTimeQuestで動作周波数の制約だが、日昇テクノロジーのサンプルがどうなっているか見たら.sdc ファイルがなかった。制約はかかっていないようだが、PLLの動作周波数での制約はかかっているようだった。どうも制約がかかっていないのは、Xilinx使いとしては気分が悪いので、セットアップ時間、クロックからの出力時間も制約をかけることにした。もう一度、”QuartusⅡでSignalTapⅡを試してみるまでの準備5(入力、出力ピンの制約とタイミング制約)”を見ながらTimeQuestでタイミング制約を生成してみる。
SDRAMからの入力のセットアップ時間を7nsとすることにした。TimeQuest のConstraintsメニューからSet Input Delay...を選ぶ。Set Input Delayダイアログが表示されたら、SDRAM_Dをすべて選んで、7nsの制約をかける。
SOPC_Builder_17_090806.png

SDRAMのクロックからの出力時間も7nsとした。同様にConstraintsメニューからSet Output Delay...を選ぶ。Set Output Delayダイアログが表示されたら、SDRAMの信号をすべて選んで、やはり7nsの制約をかける。
SOPC_Builder_18_090806.png

nois2_sdram_led.sdc を書いておこうと思ったが、設定しないのにFalse Pathがたくさん設定されていて長いので省略。自動的に設定されるのだろうか?
その後、コンパイルして通りました。これでQuartusⅡでのコンパイルは終了かな?
SOPC_Builder_19_090806.png


2009/08/09 追記:
くりさんのご指摘によってTimeQuest の制約が使われていないのがわかりました。もう一度、制約を使ってコンパイルできるようにしたいと思います。

QuartusⅡのAssignmentsメニューからSettings...を選択する。Settingsダイアログが出るので、CategoryでTiming Analysis Settings を選択する。Timing analysis processing のUse TimeQuest Timing Analyzer during Compilation のラジオボタンをクリックして選択する。
SOPC_Builder_20_090810.png

次にTiming Analysis Settings の下のTimeQuest Timing Analyzer を選ぶ。SDC file to include in the project でSDC filename: にnois2_sdram_led.sdc を選択してAddボタンをクリックする。
SOPC_Builder_21_090810.png

nois2_sdram_led.sdc が追加される。
SOPC_Builder_22_090810.png

これでOKボタンをクリックしてSettingsのダイアログを閉じる。もう一度コンパイルする。コンパイル後はTimeQuest Timing Analyzerに変わっていた。そうかこうなるのか?納得。。。タイミングは満たしていました。
SOPC_Builder_23_090810.png

くりさん、教えていただいてありがとうございました。

  1. 2009年08月06日 18:11 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:6

SOPC Builderを使ってみる2(NiosⅡのインスタンシエーション)

やっと、日昇テクノロジーのFPGAボードのIOピンの接続リストが出来上がりました。欲しい方がもしいらっしゃったらメールください。

SOPC Builderを使ってみる1”でNiosⅡを生成できた。
次にNiosⅡのインスタンシエーションをする。日昇テクノロジーのMAX II/Cyclone IIボードのマニュアル2009/2/26では、回路図(BDF)でシンボルを読み込んでIOポートを付けたが、私はVerilogでインスタンシエーションを行うことにする。
nois_sdram_inst.v にインスタンシエーションの例が載っているので、それを参考にnios2_sdram_led.v を書くことにする。下にnois_sdram_inst.v の内容を示す。

  //Example instantiation for system 'nois_sdram'
  nois_sdram nois_sdram_inst
    (
      .clk_0                             (clk_0),
      .out_port_from_the_exboard_led_pio (out_port_from_the_exboard_led_pio),
      .pll_0_c0_out                      (pll_0_c0_out),
      .pll_0_c1_out                      (pll_0_c1_out),
      .reset_n                           (reset_n),
      .zs_addr_from_the_sdram_0          (zs_addr_from_the_sdram_0),
      .zs_ba_from_the_sdram_0            (zs_ba_from_the_sdram_0),
      .zs_cas_n_from_the_sdram_0         (zs_cas_n_from_the_sdram_0),
      .zs_cke_from_the_sdram_0           (zs_cke_from_the_sdram_0),
      .zs_cs_n_from_the_sdram_0          (zs_cs_n_from_the_sdram_0),
      .zs_dq_to_and_from_the_sdram_0     (zs_dq_to_and_from_the_sdram_0),
      .zs_dqm_from_the_sdram_0           (zs_dqm_from_the_sdram_0),
      .zs_ras_n_from_the_sdram_0         (zs_ras_n_from_the_sdram_0),
      .zs_we_n_from_the_sdram_0          (zs_we_n_from_the_sdram_0)
    );


nois2_sdram_led.v をNotepad++で作って、ProjectメニューからAdd/Remove Files in Project を選択して、nois2_sdram_led.v をプロジェクトに追加した。
SOPC_Builder_11_090805.png

これで、コンパイルしたらエラーが出た。どうやらwire input clk などと書くと通らないようだ。Verilog2001に対応していないのかな?(Verilog2001の書き方を間違っていました。正しくは input wire clk, です。takepon256さん、ありがとうございました。)
仕方がないので、input clk; wire clk; に分けて記述したところ、文法のエラーはなくなったのだが、今度はTop-level design entity がないとエラーが出てしまった。
SOPC_Builder_12_090805.png

一旦、nois2_sdram_led.v を消して、FileメニューのNew...からnois2_sdram_led.v を作り直してみたがだめ。検索してみると、”Error: top level design entity " " is undefined”が引っ掛かった。
それによると、AssignmentsメニューからDevice...のGeneralをクリックして、Top-level entityを設定するとのことだった。実際にやってみるとnois2_sdram_ledが2つあって、現在選択されていない方にしたらコンパイルが通り始めた。一安心。やはり、最初にトップのファイルを作った方がよさそうだ。
でも、最終的にEDA Netlist Writerで下に示すエラーが出た。

Error: Can't generate netlist output files because the file "H:/HDL/Altera/qdesigns/nisyo_board/nios2_sdram_led/incremental_db/compiled_partitions/nios2_sdram_led.root_partition.map.atm" is an OpenCore Plus time-limited file


検索してみたところ、やはりAltera Forlumの”Open Core IP time limited source files expired.”にsettings->eda tool settings->simultionをオフしたらと書いてあったが、settingsがわからない。どうやら、Assignments->eda tool setting...のsimulation のようだ。現在はModelSim Alteraになっているので、これをNoneに変更した。
SOPC_Builder_13_090805.png

やっとコンパイルが通りました。よかった。。。
SOPC_Builder_14_090805.png

良かったけど、まだIOピンもアサインしていないし、動作周波数も制約していないので、もう一度コンパイルをやり直す。
最終的なnois2_sdram_led.vを下に示す。

// nois2_sdram_led

`default_nettype none

module nois2_sdram_led(clk, reset_n, exboard_led_pio, sdram_clk, SDRAM_A, SDRAM_BA, SDRAM_nCAS, SDRAM_CKE, SDRAM_nCS, SDRAM_D, SDRAM_DQM, SDRAM_nRAS, SDRAM_nWE);

    input             clk;
    input             reset_n;
    output [7:0]    exboard_led_pio;
    output             sdram_clk;
    output [11:0]    SDRAM_A;
    output [1:0]    SDRAM_BA;
    output             SDRAM_nCAS;
    output             SDRAM_CKE;
    output             SDRAM_nCS;
    inout    [15:0]    SDRAM_D;
    output    [1:0]    SDRAM_DQM;
    output            SDRAM_nRAS;
    output             SDRAM_nWE;

    wire         clk;
    wire         reset_n;
    wire [7:0]    exboard_led_pio;
    wire         sdram_clk;
    wire [11:0]    SDRAM_A;
    wire [1:0]    SDRAM_BA;
    wire         SDRAM_nCAS;
    wire         SDRAM_CKE;
    wire         SDRAM_nCS;
    wire [15:0]    SDRAM_D;
    wire [1:0]    SDRAM_DQM;
    wire         SDRAM_nRAS;
    wire         SDRAM_nWE;

  nois_sdram nois_sdram_inst
    (
      .clk_0                             (clk),
      .out_port_from_the_exboard_led_pio (exboard_led_pio),
      .pll_0_c0_out                      (),
      .pll_0_c1_out                      (sdram_clk),
      .reset_n                           (reset_n),
      .zs_addr_from_the_sdram_0          (SDRAM_A),
      .zs_ba_from_the_sdram_0            (SDRAM_BA),
      .zs_cas_n_from_the_sdram_0         (SDRAM_nCAS),
      .zs_cke_from_the_sdram_0           (SDRAM_CKE),
      .zs_cs_n_from_the_sdram_0          (SDRAM_nCS),
      .zs_dq_to_and_from_the_sdram_0     (SDRAM_D),
      .zs_dqm_from_the_sdram_0           (SDRAM_DQM),
      .zs_ras_n_from_the_sdram_0         (SDRAM_nRAS),
      .zs_we_n_from_the_sdram_0          (SDRAM_nWE)
    );
endmodule


しかし、AlteraのQuartusⅡの論理合成ツールはVerilog2001に対応していないのでしょうか?
AlteraはSignalTapⅡがFreeで使える分、ポイントが高いと思ったが、Verilog2001が使えないのでは考えてしまう。。。
Verilog2001使えました。訂正いたします。(AlteraはSignalTapⅡがFreeで使える分、ポイントが高い)
#年は取っていますが、Alteraのツールは初心者で学ぶことが多すぎます。limuxが動作したら良いな。。。いつも途中で挫折してしまうので、このボードでは無理かもしれないけど。うまく行くんだったボードを買っても良いかな?20年前くらいにUNIXのソースコードをみんなで読んだりしたけど、もうだいぶ過去になっている。
#実は今日から5日間夏休みです。いつもと同じようなことをやっています。

(追記)
年をとってもケアレスミスをしてしまってお恥ずかしい。。。もう一度nois2_sdram_led.v を貼っておきます。

// nois2_sdram_led

`default_nettype none

module nois2_sdram_led(
    input    wire         clk,
    input    wire        reset_n,
    output    wire [7:0]    exboard_led_pio, 
    output    wire        sdram_clk,
    output    wire [11:0]    SDRAM_A,
    output    wire [1:0]    SDRAM_BA,
    output    wire        SDRAM_nCAS,
    output    wire        SDRAM_CKE,
    output    wire        SDRAM_nCS,
    output    wire [15:0]    SDRAM_D,
    output    wire [1:0]    SDRAM_DQM,
    output    wire        SDRAM_nRAS,
    output    wire        SDRAM_nWE);

  nois_sdram nois_sdram_inst
    (
      .clk_0                             (clk),
      .out_port_from_the_exboard_led_pio (exboard_led_pio),
      .pll_0_c0_out                      (),
      .pll_0_c1_out                      (sdram_clk),
      .reset_n                           (reset_n),
      .zs_addr_from_the_sdram_0          (SDRAM_A),
      .zs_ba_from_the_sdram_0            (SDRAM_BA),
      .zs_cas_n_from_the_sdram_0         (SDRAM_nCAS),
      .zs_cke_from_the_sdram_0           (SDRAM_CKE),
      .zs_cs_n_from_the_sdram_0          (SDRAM_nCS),
      .zs_dq_to_and_from_the_sdram_0     (SDRAM_D),
      .zs_dqm_from_the_sdram_0           (SDRAM_DQM),
      .zs_ras_n_from_the_sdram_0         (SDRAM_nRAS),
      .zs_we_n_from_the_sdram_0          (SDRAM_nWE)
    );
endmodule

  1. 2009年08月05日 13:34 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:4

SOPC Builderを使ってみる1

日昇テクノロジーのMAX II/Cyclone IIボードのマニュアル2009/2/26を参考にして、SOPC Builder を試してみることにした。しかし、このマニュアルに載っているnios_led_sch というフォルダはサンプルをダウンロードした中にないし、このマニュアルもボードのマニュアルと銘打っている割にはQuartusⅡやSOPC Builder などツールの説明書だし、結局ボードのマニュアルはないんだよな~。回路図から読み解けといった感じ。回路図もCycloneⅡの乗ったボードと表示ボードの2つになっているので、コネクタを合わせて読み解く必要があるし。。。ちょっとマニュアルが不親切。FPGAも小さいし、もっとやりたくなったら、純正のボードを購入することにする。USB Blasterもどきは今回手に入ったし。。。

愚痴はこのくらいにして、SOPC Builder を試してみることにする。MAX II/Cyclone IIボードのマニュアル2009/2/26の53ページ、第五章 NIOSⅡシステム・モジュールの設計を参考に進めていく。
QuartusⅡを立ち上げてnois2_sdram_led プロジェクトを作る。ToolsメニューからSOPC Builder を立ち上げる。(この辺は日昇テクノロジーのマニュアルを参照しているので、適宜、画面を貼り付ける)
SOPC_Builder_1_090731.png

Verilogを選択して、NiosⅡプロセッサを追加する。その際にJTAG Debug Module のレベルも選択できるみたい。どのレベルのJTAG Debug をするかによってLEの数が違ってくる。これは当たり前か。。。MicroBlazeにはXMDがあるが、設定はなかったような?
SOPC_Builder_2_090731.png

次に行くと、Custom Instractions が設定できる。気軽にカスタム命令が設定できるのかな?あらかじめ使いそうな命令は左側に用意されているようだが、ハードウェアを追加した命令追加はImport... ボタンあたりから使うのかな?
SOPC_Builder_3_090731.png

これでNiosⅡプロセッサの設定は終わり、ちなみにNiosⅡはNiosⅡ/f という一番機能が充実しているもの。
つぎにSDRAMコントローラを追加する。Custom を指定して、データ幅を16bitsにする。次に行くとSDRAMのパラメータを指定するが、SDRAMのデータシートがないので、ネットで探してきた。型番はK4S640432HというサムソンのSDRAM。
まずは、リフレッシュコマンドの発行間隔だけど、64ms refresh period (4K cycle)なので、15.625usでOK。初期化についてはマニュアルに何も書いていないで、これで大丈夫でしょう?
後はデータシートに書いていないのでわからない。サンプルプロジェクトを立ち上げてみたらデフォルトだったので、そのままで行くことにする。
SOPC_Builder_4_090731.png

これでNiosⅡとSDRAMは作られたようだ。
次はインターフェース・ボードに8個付いているLEDを組み込む。左のペインのPeripherals -> Microcontroller Peripherals -> PIO(Parallel I/O)をダブルクリック、PIOを設定する。マニュアルと違って8ビット幅あるので、そのままFinishボタンをクリックした。
SOPC_Builder_5_090731.png

JTAG UARTを組み込む。JTAG UARTは、Interface Protocols -> Serial -> JTAG UART をダブルクリックして、JTAG UARTを設定する。これはマニュアルと同じくデフォルトのまま。
その後はPLLの設定。
Output Clocksのclk c2はSDRAM用の制御クロックだそうですが、Clock Phase Shiftを -63度にするとは、もしかして、READデータを受けるFPGAのセットアップ時間を確保するためなのかな?(2009/08/06 追記:そうとも言いますが、クロックを出力するときの出力の遅延をキャンセルするためですね。たぶん。。。)
SOPC_Builder_6_090731.png

PLLを設定し終わった。次は、Peripherals -> Debug and Performance -> System ID Peripheralをダブルクリックする。
現在のSOPC Builder の表示は下のようになっている。
SOPC_Builder_7_090731.png

ここからpio_0 をrename で名前を変えて、exboard_led_pio に変更した。
Clockフィールドでpllから出力されたpll_0.c0 に各モジュールのクロックを変更するようなのだが、SDRAM Controller だけは、わざわざ作ったpll_0.c1にするのではないだろうか?マニュアルみてもそのようには書いていないが、はたしてどうしたほうがいいか???サンプルとして出来ているsdram_testプロジェクトを見ると、PLLは使っていないし、SDRAM Controller もそのままのクロックを使っている。ここは、pll_0.c1 はせっかく作ったのだが、とりあえず、SDRAM Controller もpll_0.c0 を使うことにする。
(2009/8/2追加:ここでのクロックはあくまでもSDRAM Controller のクロックで、後でpll_0.c1をSDRAMのクロックとして出力していました)
SOPC_Builder_8_090731.png

(2009/08/10 追加:ここでWarning が出ていました。sysid_0 をsysidにRenameするとWarning が消えました。Warningを消しておかないと、後でNoisⅡ IDEでエラーが出ます。Warningを消した状態を下の図に示します。)
SOPC_Builder_24_090810.png

cpuをダブルクリックして、Reset VectorとException Vectorにsdram_0を指定する。Finishボタンで終了する。
SOPC_Builder_9_090731.png

SOPC Builder でGenerateボタンをクリックする。System generationが成功した。
(2009/08/10 追加:sysid_0をsysidにRenameした図に変更しました)
SOPC_Builder_25_090810.png

2009/08/02 追記: 日昇テクノロジーのFPGAボードは回路図だけでピンにどの素子がつながっているかのリストがありません。問い合わせてみたのですが、ないとのこと。仕方がないので、QuartusⅡでインプリメントする前に自分でリストを作ることにしました。まだ、1つの基板だけだったら良いのですが、上にインターフェース基板が載っているので、IOがコネクタ経由になるのでリストを作らないとわかりません。SUZAKUはリストがマニュアルに記載されているので良かったのですが。。。今度、購入するときにはAltera 純正のボードを購入することにします。サンプルプロジェクトのコメントはたぶん中国語で化けていますし、別にコメントを見なくてもVerilogコードは読めるのですけど、どうもいまいちです。。。
  1. 2009年08月01日 15:11 |
  2. SOPC Builder
  3. | トラックバック:0
  4. | コメント:0