FC2カウンター FPGAの部屋 2011年01月24日
FC2ブログ

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

FPGAの部屋

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

電子サイコロをNSLで書いてみる3(NSLをVerilogに変換してインプリント)

電子サイコロをNSLで書いてみる2(NSLに変換)”でUMLのクラス図からNSLのスケルトンに変換したので、これをサンプルを参照しながら、NSLのメソッドを書いていった。

最初に、”電子サイコロをNSLで書いてみる1(Papyrusでクラス図を作成)”の最後の出来上がりのクラス図は、counter_1to6クラスの中にreg counter_1to6; が定義してあるので、2重定義になってしまった。
NSL_Sample_41_110119.png

counter_1to6クラスの中のregの名前をcouter1to6に変更した。
NSL_Sample_42_110119.png

もう一度、UMLtoNSLでNSLスケルトンを生成して、サンプルを参照しながら、NSLのメソッドを書いていった。出来上がったNSLを下に示す。

// UML2NSL converter Ver. 2010-03-28 Copyright (c) 2009-2010 IP ARCH, Inc. All rights reserved.
// xmi  --- version 2.1 --- 

    #define C5MS_SECOND        ( 18'd250000 - 18'd1 )
//    #define C5MS_SECOND        ( 19'd4 )

    #define SEG_VALUE_6        8'b0111_1101
    #define SEG_VALUE_5        8'b0110_1101
    #define SEG_VALUE_4        8'b0110_0110
    #define SEG_VALUE_3        8'b0100_1111
    #define SEG_VALUE_2        8'b0101_1011
    #define SEG_VALUE_1        8'b0000_0110

declare    dice  {
    
    // -- dice  --
    input    roll;
    output    seg_o[8];
    output    seg_figure[4];
    
}

declare    counter_1to6  {
    
    // -- counter_1to6  --
    output    seg1to6_o[8];
    
    // -- counter_1to6  --
    func_in    countup();

}

declare    hex_to_7segout  {
    
    // -- hex_to_7segout  --
    input    hexdata[3];
    output        segdata_o[8] ;
    
    // -- hex_to_7segout  --
    func_in    output7seg(hexdata);

}

module    dice {
    
    // -- dice  --
    reg    count_5msec[18];
    reg    count_20msec[3];
    counter_1to6    u_counter_1to6;

    /* common operations */
    {
        seg_o = ~u_counter_1to6.seg1to6_o;
        seg_figure = 0b1110;
        
        any {
            count_5msec == C5MS_SECOND : {
                count_20msec++;
                count_5msec := 0;
            } else : {
                count_20msec++;
            }
        }
        
        any {
            count_20msec == 4 : {
                if (roll) {
                    u_counter_1to6.countup();
                }
                count_20msec := 0;
            }
        }        
    }
}

module    counter_1to6 {
    
    // -- counter_1to6  --
    reg    counter1to6[3] = 1;
    hex_to_7segout    u_hex_to_7segout;
    


    /* common operations */
    {
        seg1to6_o = u_hex_to_7segout.output7seg(counter1to6).segdata_o ;
    }

    
    /* func_in countup() operation */
    function    countup {
        any {
            counter1to6 == 3'b110 : {
                counter1to6 := 3'b001;
            } else : {
                counter1to6++;
            }
        }
    }
}

module    hex_to_7segout {
    wire         hex_value[3] ;
    wire        seg_value[8] ;

    func_self    seg_decode(hex_value)    :    seg_value ;

    /* common operations */
    {
        segdata_o = seg_decode(hexdata).seg_value ;
    }

    
    /* func_in output7seg(hexdata) operation */
    func seg_decode {
        any {
            hex_value == 0b001 : seg_value = SEG_VALUE_1 ;
            hex_value == 0b010 : seg_value = SEG_VALUE_2 ;
            hex_value == 0b011 : seg_value = SEG_VALUE_3 ;
            hex_value == 0b100 : seg_value = SEG_VALUE_4 ;
            hex_value == 0b101 : seg_value = SEG_VALUE_5 ;
            hex_value == 0b110 : seg_value = SEG_VALUE_6 ;
        }
    }
        
}


(大分サンプルのコードを参照させていただきました。なにかまずいことがあったらお知れらせください)

VerilogやVHDLで書いた時よりもコードが大分すっきり短くなった。NSLを自分で書いてみると(ほんの少しだが、)やはりサンプルを見てわかった様なつもりになっていても、色々と戸惑うことが多かった。新しい言語を習得するのだから、やはり色々とわからない部分がある。ほんとうに簡単なコードだが、NSLを書いてよかったと思う。
1つの疑問は、declare hex_to_7segout でfunc_in output7seg(hexdata);を宣言していて、module counter_1to6でも、seg1to6_o = u_hex_to_7segout.output7seg(counter1to6).segdata_o ;で使っているが、module hex_to_7segoutには、output7seg(hexdata)の記述がないことだ。これは自分が無知なだけかもしれない?
問い合わせをお願いしているので、結果がわかったら書き足すことにする。

次にNSL CoreでVerilogに変換して(Optimizeオプションをチェック)、ISE12.4 のプロジェクトを生成して、インプリントしてみた。
NSL_Sample_43_110124.png

できたビットファイルをSpartan3 Starter Kit にダウンロードしたら、サイコロが動作した。
NSL_Sample_44_110124.jpg

うまく行った。ほんとうに簡単なサンプルだがうれしい。
最後に、これ用(dice.v) のUCFファイルを下に示す。

NET "m_clock" LOC = T9;
NET "p_reset" LOC = L14;
NET "roll" LOC = M13;

# PlanAhead Generated physical constraints
NET "seg_figure[0]" LOC = D14;
NET "seg_figure[1]" LOC = G14;
NET "seg_figure[2]" LOC = F14;
NET "seg_figure[3]" LOC = E13;
NET "seg_o[0]" LOC = E14;
NET "seg_o[1]" LOC = G13;
NET "seg_o[2]" LOC = N15;
NET "seg_o[3]" LOC = P15;
NET "seg_o[4]" LOC = R16;
NET "seg_o[5]" LOC = F13;
NET "seg_o[6]" LOC = N16;
NET "seg_o[7]" LOC = P16;
#Created by Constraints Editor (xc3s200-ft256-4) - 2011/01/16
NET "m_clock" TNM_NET = m_clock;
TIMESPEC TS_m_clock = PERIOD "m_clock" 20 ns HIGH 50%;



(2011/01/27:追記)
疑問だったhex_to_7segoutのoutput7segの件で回答をいただきました。ありがとうございました。
正しいコードを下に示します。

module    hex_to_7segout {
    wire         hex_value[3] ;
    wire        seg_value[8] ;

    func_self    seg_decode(hex_value)    :    seg_value ;

    /* common operations */
    {
    }

    
    /* func_in output7seg(hexdata) operation */
    func    output7seg    {
        segdata_o = seg_decode(hexdata).seg_value ;
    }
    
    func seg_decode {
        any {
            hex_value == 0b001 : seg_value = SEG_VALUE_1 ;
            hex_value == 0b010 : seg_value = SEG_VALUE_2 ;
            hex_value == 0b011 : seg_value = SEG_VALUE_3 ;
            hex_value == 0b100 : seg_value = SEG_VALUE_4 ;
            hex_value == 0b101 : seg_value = SEG_VALUE_5 ;
            hex_value == 0b110 : seg_value = SEG_VALUE_6 ;
        }
    }
        
}


common operationsは空で、func output7segにコードを書くそうです。動作としては同じで、この方がすっきりする気がします。

  1. 2011年01月24日 05:51 |
  2. NSL
  3. | トラックバック:0
  4. | コメント:0