12.構造体

構造体(structure)は複数の配線とレジスタを管理する構文です。
この構造体により複数の配線/レジスタを一度に宣言することが可能です。
構造体の宣言時には”structure”を省略した”struct”をつかいます。

構造体の宣言

構造体はNSLの”declare文”と”module文”から独立した”struct文”をつかって宣言します。
struct文中で宣言する配線/レジスタは、端子の名前とビット幅のみ宣言し、
配線であるかレジスタであるかはインスタンス化する時に決定します。
構造体の宣言は以下のように書きます。

struct 構造体名 {
メンバー名1 [ビット幅] ;
メンバー名2 [ビット幅] ;
………
} ;

※構造体の宣言後には必ずセミコロンが必要です。

次に、構造体をつかったNSL例題を示します。

例題12-1.構造体の宣言方法
	struct st_RGB {
    R[8] ;	//構造体"st_RGB"の8bit端子"R"
    G[8] ;	//構造体"st_RGB"の8bit端子"G"
    B[8] ;	//構造体"st_RGB"の8bit端子"B"
} ;

	

構造体を使用する場合はmodule文の中でインスタンス化を行い、このとき構造体をレジスタか配線のどちらかに設定します。

構造体のインスタンス化は以下のように書きます。

配線の宣言例)

構造体名 wire インスタンス名[多重度]

レジスタの宣言例)

構造体名 reg  インスタンス名[多重度] = 初期値

多重度と初期値は省略可能です。
インスタンスをレジスタで宣言した場合のみ、初期値を設定できます。
また多重度を省略した場合はインスタンスは1つだけ使用できます。

また、module文の内部で構造体のインスタンスを使用する場合は、以下のように書きます。

例)インスタンスを使用する場合

インスタンス名

例)インスタンスのメンバを使用する場合

インスタンス名.メンバ名

インスタンスは配線かレジスタで指定するので、転送も配線とレジスタに沿ったものを使用します。
構造体を配線でインスタンス化した場合、インスタンスへ値の転送は以下のように書きます。

例)インスタンスに転送する場合

インスタンス名 = 値

例)インスタンスのメンバに転送する場合

インスタンス名.メンバ = 値

構造体をレジスタでインスタンス化した場合は、以下のように書きます。

例)インスタンス全体に転送する場合

インスタンス名 := 値

例)インスタンスのメンバに転送する場合

インスタンス名.メンバ := 値

構造体におけるインスタンス化の例題を以下に示します。
例題12-2はRGB信号をCMYK信号に変換する回路です。

例題12-2.構造体のインスタンス化

// ※CMYK、RGBのビット深度がそれぞれ8bitの場合
struct st_RGB {
    R[8] ;  //R色情報
    G[8] ;  //G色情報
    B[8] ;  //B色情報
};

struct st_CMYK {
    C[8] ;  //C色情報
    M[8] ;  //M色情報
    Y[8] ;  //Y色情報
    K[8] ;  //K色情報
};

declare RGB_CMYK_conv {
    input       inRGB[24] ;
    output      outCMYK[32] ;
    func_in     exec(inRGB) ;
    func_out    ack(outCMYK) ;
}

module RGB_CMYK_conv {
    st_RGB  reg  RGB  = 0 ;    //構造体"st_RGB"をレジスタの"RGB"としてインスタンス化
                               //"0"を初期値として設定
    st_CMYK reg  CMYK = 0 ;    //構造体"st_CMYK"をレジスタの"CMYK"としてインスタンス化
                               //"0"を初期値として設定

    reg opr1[8] = 0 ;          //演算用レジスタを宣言する
    reg opr2[8] = 0 ;          //演算用レジスタを宣言する
    reg opr3[8] = 0 ;          //演算用レジスタを宣言する

    func exec seq {            //sequence文でファンクションを記述する

        RGB := inRGB ;         //"inRGB"をインスタンス"RGB"に書込む

        //RGBをCMYKに変換する
        {
            opr1 := 8'hFF - RGB.R ;    //インスタンス"RGB"の"R"を取り出して演算
            opr2 := 8'hFF - RGB.G ;    //インスタンス"RGB"の"G"を取り出して演算
            opr3 := 8'hFF - RGB.B ;    //インスタンス"RGB"の"B"を取り出して演算
        }

        //Kを算出する
        if(opr1>opr2) opr1 := opr2 ;
        if(opr1>opr3) opr1 := opr3 ;   //"opr1","opr2","opr3"の最小値を"opr"に代入する
        CMYK.K := opr1 ;               //インスタンスCMYKのKのみに書込む

        //CMYを算出する
        {
            CMYK.C := 8'hFF - RGB.R - CMYK.K ;  //"RGB"の"R"、"CMYK"の"K"を取り出して演算
            CMYK.M := 8'hFF - RGB.G - CMYK.K ;  //"RGB"の"G"、"CMYK"の"K"を取り出して演算
            CMYK.Y := 8'hFF - RGB.B - CMYK.K ;  //"RGB"の"B"、"CMYK"の"K"を取り出して演算
        }

        ack(CMYK) ;                             //"CMYK"を引数として、"ack"を出力する
    }
}
	

例題12-2は構造体をインスタンス化し、インスタンスを文中で使用する例です。
構造体を例題のように使用すると、レジスタや配線をまとめて管理できます。
本例題はRGB信号をCMYK信号へ変換する回路例です。例題では”st_RGB”、”st_CMYK”のそれぞれを構造体で宣言しています。
モジュール”RGB_CMYK_conv”内では、”st_RGB”は”RGB”、”st_CMYK”は”CMYK”とそれぞれインスタンス化しています。
“RGB_CMYK_conv”内のファンクション”exec”を起動すると、ファンクション内を順番に実行していきます。
“exec”の中では以下の様な処理を行っています。

1.RGB信号をインスタンス”RGB”に取り込む
2.”RGB”の値からCMYK信号の”K”を算出する
3.”RGB”の値からCMYK信号の”C”,”M”,”Y”を算出する
4.”CMYK”を出力する

では、例題12-2をシミュレーションしてみましょう。

入力側
RGB:a0,50,20
RGB:ff,ff,ff
RGB:ff,40,00

出力側
CMYK:00,50,80,5f
CMYK:00,00,00,00
CMYK:00,bf,ff,00