3.アクション記述

第3章ではNSLのアクション記述について解説します。

3-1.共通アクション記述の解説

3-1章では共通アクション記述について解説します。
NSLには、回路の状態によってアクションが変化する部分があります。
また、回路の状態とは関係なく、起動時から常に動いている部分があります。
その”常に動いている部分”のことを共通アクション記述と言います。

例として、共通アクション記述に論理積を記述した例題を提示します。
次の例題5を見てみましょう。

<<例題5.共通アクション記述の例>>
declare ex05 {
   //入出力構成要素の宣言
   input a, b ;
   output f ;
}
module ex05 {
   //共通アクション記述
   f = a & b ;
}

この例題5は”データ端子の宣言”,”共通アクション記述”だけのモジュールです。
例題の中では、データ入力端子a,bとデータ出力端子fを宣言しています。
また、共通アクション記述の中でデータ入力端子a,bの論理積をデータ出力端子fに転送しています。

例題5のシミュレーション結果を見てみましょう。

a,bの入力に合わせて、fに論理積の結果が出力されていることが分かります。

3-2.並列アクションの解説

ハードウェア記述言語は、記述したアクションを同時に実行します。
このように同時実行することを並列アクションと言います。
では、並列アクションの例として例題6を見てみましょう。

<<例題6.並列アクションの例>>
declare ex06 {
   //入出力構成要素の宣言
   input a, b ;
   output f, g ;
}
module ex06 {
   //共通アクション記述
   f = a ^ b ;
   g = a | b ;

}

例題6は、データ入力端子a,bの排他的論理和をデータ出力端子fに転送しています。また、a,bの論理和をデータ出力端子gにそれぞれ転送しています。

例題のシミュレーション結果を見てみましょう。

a,bの入力に合わせてfに排他的論理和が、
gに論理和を転送していることが分かります。

3-3.複数ビットの信号を使うとき

HDLで設計を行う場合、1ビットの信号だけでなく、
複数ビットの信号を使うことが多々あります。

本稿では複数ビットの信号線のことを束線信号、1ビットの信号のことを単線信号と呼びます。
では、束線信号の例を作ってみます。
例題7を見てみましょう。

<<例題7.束線信号の例>>
declare ex07 {
   //複数ビットの入出力構成要素の宣言
   input a[8], b[8] ;
   output f[8] ;
}
module ex07 {
   //共通アクション記述
   f = a & b ; //式1
}

この例題7は”データ端子の宣言”と”共通アクション記述”だけを有するモジュールです。例題7のモジュールは、8ビットのデータ入力端子a,bと、8ビットのデータ出力端子fを持っています。

そして、式1でa,bの論理積をfに出力するようになっています。
では、以下のシミュレーション結果を見てみましょう。

例題7の演算子”&”はビット毎の論理演算を行う演算子です。
データ入力端子a,bの各ビット毎の論理積がデータ出力端子fに出力しています。

3-4.ブロックの解説

アクションを記述した一文の事を“単位アクション”と呼びます。
また、単位アクションが起動するルールを記述したものをブロックと呼びます。

ブロックは、アクション記述内で{}で囲んだ領域の事を指し、
if,any,alt,並列動作,seqなどの種類があります。
NSLは、ブロックの組み合わせでモジュールを設計します。

表9はアクションの構文とブロックの種類を表しています。

【表9.アクション記述の種類】
種別 説明
単位アクション
値の転送、レジスタ・メモリへの書き込み、プロシージャの起動、 制御端子の起動、状態変数の生成など。
if文
条件付きアクション。
anyブロック
条件付きアクション。条件に合致するすべてのアクションは並列に起動する。 ‘else’アクションを指定していれば、どの条件にも合致しないときに ‘else’アクションを起動する。
altブロック
優先順位付き条件付きアクション。条件に合致する最初のアクションを起動する。 ‘else’アクションを指定していれば、 どの条件にも合致しないときに’else’アクションを起動する。
並列動作ブロック
複数の単位アクションの並列起動
seqブロック
順序アクション。※制御端子内限定
forブロック
条件付きループアクション。※seqブロック内限定
whileブロック
条件付きループアクション。※seqブロック内限定

なお、seqブロック及びforブロック、whileブロックは制御端子内部に限り
使用可能な構文ですので、次の「4章 制御端子」で解説します。

3-5.if文の解説

if文は、条件式によってアクションを決定する条件文です。
条件式が真の場合、if直後に記述したアクション記述を実行します。
そして、条件式が偽の場合、if直後のアクションを実行しません。

if文は以下の式で記述します。

if ( 条件式 ) 単位アクション

また、if文の条件式が偽の場合にアクションを実行する“else”という構文があります。

else文は以下の式で記述します。

if ( 条件式 ) 単位アクション1
else 単位アクション2

以上を踏まえて例題8「if文の記述例」を見てみましょう。

<<例題8.if文の記述例:条件文>>
declare ex08 {
   input a, b ;
   output f, g, h ;
}
module ex08 {

	//式1
	if(a == 0b1) f = 0b1 ;

	//式2
	if(a & b) g = 0b1 ;

	//式3
	if(a | b) h = 0b1 ;
	else h = 0b0 ;
}

条件式で真は「0以外」、偽は「0」を指します。
複数ビットの時も、条件は変わりません。

例題8は、if文の条件式によって動きが変化します。
例題8の式1は、「aの値が1ならばfに1を代入する」というアクションです。
同じように式2は、「aとbの論理積が真ならばgに1を代入する」というアクションです。
さらに式3は、
「aとbの論理和が真ならば、hに1を代入し、
aとbの論理和が偽ならば、hに0を代入する」というアクションです。
では、例題8のシミュレーション結果を見てみましょう。
シミュレーション結果のxは不定値という意味です。

3-6.anyブロックの解説

条件付きアクションを記述する他の構文としてanyブロックがあります。
anyブロックは、一つのブロック内で複数の条件式を書くことができます。
またanyブロックは、ブロック内の条件を満たしたアクション記述が全て起動します。
anyブロックの記述方法は以下になります。

any {
条件式1 : 単位アクション1
条件式2 : 単位アクション2

else : 単位アクションx
}

anyの条件式は、1つでも複数でも構いません。
また、anyブロックには全ての条件が偽の場合に実行する”else”構文もあります。
else構文は省略可能です。
では、anyブロックの使用例について解説します。

以下の例題9を見てみましょう。

<<例題9.anyブロック例:条件文>>
declare ex09 {
   input a, b ;
   input c, d ;
   output f, g, h ;
}
module ex09 {

   any {
      //式1
      c : f = a & b ;

      //式2
      d : g = a ^ b ;

      //式3
      else : h = a | b ;
   }
}

この例題9は”データ端子の宣言”, “anyブロックのアクション記述”を有するモジュールです。
例題9の式1は「cが真の場合、fにa,bの論理積を出力する」というアクションです。
また式2は、「dが真の場合、gにa,bの排他的論理和を出力する」というアクションです。
そして式3は、「cとdが両方とも偽の場合、fにa,bの論理和を出力する」というアクションです。

では、アクションの確認をしてみましょう。
以下に論理シミュレーション結果を示します。

条件式に記述したc,dの値によってデータ出力端子f,g,hが変化しています。
データ出力端子に値を何も代入しない場合は不定値となります。
また、

  any {
  c : f = a ;
  d : f = b ;
  }

といったように、 同じ端子に同時に転送を行う場合は、
処理系によってはエラーとなりますので注意して下さい。

3-7.altブロックの解説

altブロックは、条件付きアクションを記述する構文です。
anyブロックとの大きな違いは、条件付きアクションに優先順位が存在する点です。

altブロックは上から記述した順に、アクションの優先順位が高くなります。

そのため、条件式が2個以上”真”の場合、先に記述したアクション記述のみを実行します。

以下がaltブロックの記述方法です。

alt {
条件式1 : 単位アクション1
条件式2 : 単位アクション2

else : 単位アクションx
}

anyブロックの場合と同じく、条件式は1つでも複数でも構いません。
また、条件式が全て偽の場合に実行される構文”else”も使用できます。
elseは省略可能です。
では、altブロックの記述例として例題10を見てみましょう。

<<例題10.altブロック例:条件文>>
declare ex10 {
   input a, b ;
   input c, d ;
   output f ;
}
module ex10 {

   alt {
      //式1
      c : f = a & b ;

      //式2
      d : f = a ^ b ;

      //式3
      else : f = a | b ;
   }
}

この例題10は”データ端子の宣言”, “altブロックのアクション記述”,を有するモジュールになります。
例題10の式1は「cが真の場合、a,bの論理積をfに出力する」というアクションです。
また、式2は「dが真の場合、a,bの排他的論理和をfに出力する」というアクションです。
そして式3は「cとdが偽の場合、a,bの論理積をfに出力する」というアクションです。
以下がシミュレーション結果です。

シミュレーション結果を見ると、
altブロックの中では、条件式c,dの値によってアクションが変化しています。
また、条件式に優先順位があることも表されています。

3-8.並列動作ブロックの解説

並列アクションを記述する構文として並列動作ブロックがあります。
並列動作ブロックは、本来単位アクションしか書けない部分に使用して、並列動作を記述できます。
(条件付きアクションや順序アクションなど)
並列動作ブロックの記述方法を以下に示します。

{
単位アクション1
単位アクション2

}

以上のように、{}の中に並列動作するアクション記述を並べます。
次の例題11を見てみましょう。

<<例題11.並列動作ブロックの例>>
declare ex11 {
   input a, b ;
   output f[2] ;
}
module ex11 {

   reg r1[2] = 0b00;

   alt {
      a : { //並列動作ブロック開始
         r1 := 0b10 ;
         f = r1 ;
      } //並列動作ブロック終了

      b : {
         r1 := 0b01 ;
         f = r1 ;
      }

      else : {
         r1 := 0b11 ;
         f = 0b00 ;
      }
   }
}

この例題11は”データ端子の宣言”, “並列動作ブロックを使ったanyブロックのアクション記述”を有するモジュールになります。
例題11の式1は、「aが真の場合、f,gにそれぞれ1を出力する」というアクションです。
また式2は、「bが真の場合、fに1,gに0をそれぞれ出力する」というアクションです。
式3は、「cが真の場合、fに0,gに1をそれぞれ出力する」というアクションです。
そして式4は、「a,b,cが全て偽の場合、f,gにそれぞれ0を出力する」というアクションです。
例題11の様に、条件付きアクションで並列動作ブロックを使用すると、条件分岐後に並列動作を行うことが可能です。
以下に例題のシミュレーション結果を示します。

3-9.束線信号の加工方法

この3章9節では、3章3節で触れた束線信号の加工方法について解説します。

ビット連結

ビット連結演算子は、信号や数値を連結して、複数ビットの信号を作る演算子です。
ビット連結演算子は以下の様に用います。

{ sigA, sigB, … }

ビット連結の例として、例題12を見てみましょう。

<<例題12.ビット連結の例>>
declare ex12 {
   input a[4], b[4] ;
   output f[8], g[8] ;
}
module ex12 {
   f = { 0b0000, a } ; //式1
   g = { a, b } ;      //式2
}

例題12では2つのビット連結作業を行っています。
式1は「4ビット二進数の値”0000″と、aを連結してfに出力する」という動作です。
また、式2は「a,bを連結してgに出力する」というアクションです。
以下の例題12のシミュレーション結果を見てみましょう。

ビット切り出し

ビット切り出し演算子は、複数ビットの信号から指定するビットだけを取り出す演算子です。
ビット切り出しとビット連結を組み合わせて、信号のさまざまな加工が容易に行えます。

ビット切り出し、ビット連結の例として例題13を見てみましょう。

<<例題13.ビット切出し・連結の例>>
declare ex13 {
   input a[8], b[8] ;
   output f[4], g[8] ;
}
module ex13 {

	f = a[3:0] ;   //式1
	g = { a[6:5], b[6:1] } ;  //式2
}

例題13の式1は、「aの3-0ビットをfに出力する」という動作です。
また式2は、「aの6-5ビットとbの6-1ビットを連結して、gに出力する」というアクションです。
例題13のシミュレーション結果は以下になります。

符号拡張

符号拡張は、2の補数表記の数値を、符号をそのままにビット拡張する演算子です。
符号拡張は次の様に表記して使います。

<拡張するビット数>#<拡張対象の信号や値>

符号拡張の例として例題14を見てみましょう。

<<例題14.符号拡張の例>>
declare ex14 {
   input a[4] ;
   output f[8] ;
}
module ex14 {
   f = 8#a ; //式1
}

例題14の式1は「4ビットの信号aを8ビットに符号拡張して、fに出力する」というアクションです。
符号拡張ではなく、ただ固定したビットを左に追加したい場合にはビット連結を用いてください。
以下が例題14のシミュレーション結果です。

3-10.演算子その他

本項目ではNSLの演算子を使用する方法を解説します。

リダクション演算

リダクション演算は、複数桁の信号を一つずつ論理演算する演算です。 例えば、4ビットの信号aの値が1010だった場合、リダクション演算子&を使用すると 1 & 0 & 1 & 0 となり、結果は0となります。

また、動作記述中での表記は信号とセットで以下のように行います。

&sigA

リダクション演算子の例として、以下の例題15を見てみましょう。

<<例題15.リダクション演算の例>>
declare ex15 {
   input a[4] ;
   output f, g, h;
}
module ex15 {

   f = &a ; //式1
   g = |a ; //式2
   h = ^a ; //式3
}

式1は、”&a”つまり

f = a[3] & a[2] & a[1] & a[0]

と記述しているのと同じ意味になります。

また式2は”|a”なので、

g = a[3] | a[2] | a[1] | a[0]

と記述しているのと同じ意味になります。

そして、式3は^aなので、

h = a[3] ^ a[2] ^ a[1] ^ a[0]

と記述しているのと同じ意味になります。

例題15のシミュレーション結果が以下になります。

算術演算

算術演算は、加算、減算、乗算を用意しています。
加算、減算、乗算共に、1クロックで終了する演算回路を提供します。
算術演算の使用例として以下の例題16を見てみましょう。

<<例題16.算術演算の例>>
declare ex16 {
   input a[4], b[4] ;
   output f[4], g[4], h[8] ;
}
module ex16 {

   f = a + b ; //式1
   g = a - b ; //式2
   h = a * b ; //式3
}

例題16は算術演算です。
算術演算は加算・減算・乗算をサポートしています。
式1はaとbの和をfに転送するというアクションです。
式2はaとbの差をfに転送するというアクションです。
式3はaとbの積をfに転送するというアクションです。

例題16のシミュレーション結果を見てみましょう。

シフト演算

シフト演算は、ビット長はそのままに、 ビットの桁を左右にスライドする演算です。 左シフトの場合、右から追加する値は常に”0″となります。
右シフトの場合も、左から追加する値は常に”0″となります。
また両シフトとも、本来のビット長を越えてシフトした値は切り捨てになります
例えば、0011を左に2ビットシフトした場合1100となります。

シフト演算の例として、以下の例題17を見てみましょう。

<<例題17.シフト演算の例>>
declare ex17 {
   input a[8] ;
   output f[8], g[8] ;
}
module ex17 {

   f = a<<4 ; //式1
   g = a>>5 ; //式2
}

例題17はシフト演算の例です。
式1は、信号aを左に4ビットシフトしてfに出力するという意味の単位アクションです。
式2は、信号bを右に5ビットシフトしてgに出力するという意味の単位アクションです。

例題17のシミュレーション結果を見てみましょう。

論理演算

論理演算は、ビット演算とは違い、 演算対象の信号自体も真偽で演算する演算です。 複数ビットの信号でも、0以外ならば”真”。
複数ビットの信号でも、0ならば”偽”になります。

論理演算の例として、以下の例題18を見てみましょう。

<<例題18.論理演算の例>>
declare ex18 {
   input a[4], b[4] ;
   output f, g, h ;
}
module ex18 {

   if(!a) f = 0b1 ; //式1
   else f = 0b0 ;

   if(a&&b) g = 0b1 ; //式2
   else g = 0b0 ;

   if(a||b) h = 0b1 ; //式3
   else h = 0b0 ;
}

例題18は論理演算を行っています。式1は、aの論理否定をif文で条件判定しており、真の場合はfに1を、偽の場合はfに0を出力するアクションを表しています。
式2は、a,bの論理積をif文で条件判定しており、真の場合はgに1を、偽の場合はgに0を出力するアクションを表しています。
式3は、a,bの論理和をif文で条件判定しており、真の場合はhに1を、偽の場合はhに0を出力するアクションを表しています。
では、例題18のシミュレーション結果を見てみましょう。

リピート演算

リピート演算は、同じ値の繰り返しを複数ビット用意するための演算子です。
例えば、1を10ビット用意する場合は、 10{0b1} と表記すると実際には 0b1111111111 と同じ表記になります。

リピート演算の例として、以下の例題19を見てみましょう。

<<例題19.リピート演算の例>>
declare ex19 {
	output f[8] ;
}
module ex19 {
	reg r1[8] ;

	r1 := 8{0b1} ; //式1
	f = r1 ;
}

例題19のリピート演算は、
式1は、

r1 = { 0b1, 0b1, 0b1, 0b1, 0b1, 0b1, 0b1, 0b1 }

と同じ意味の単位アクションです。

以下のシミュレーション結果を見てみましょう。

条件演算

条件演算は信号や値の転送時に使用する条件分岐の演算子です。
転送の際に条件演算を使用することで、右辺へ転送する信号・値を場合分けすることができます。
条件演算の記述方法はifとelseを使用して以下のように記述します。

sigA = if(条件文) 信号・値 else 信号・値

次に、より具体的な条件演算の表記例を示します。

sigA = if(sigB) sigC else 0b1 ; //式1

式1は、sigBが真の場合sigAにsigCを転送し、
sigBが偽の場合sigAに0b1を転送するという意味のアクションです。
条件演算の例として、以下の例題20を見てみましょう。

<<例題20.条件演算の例>>
declare ex20 {
	input a[4] ;
	input b[2] ;
	output f[4], g[4] ;
}
module ex20 {

	f = if(b == 0b10) a else 0b1010 ;          //式1
	g = a + if(b == 0b01) 0b0101 else 0b0011 ; //式2
}

例題20の式1は、b==0b10が真の場合fにaを転送し、偽の場合fに0b1010を転送するというアクションです。
また式2はb==0b01が真の場合gにa+0b0101を転送し、偽の場合a+0b0011を転送するというアクションです。
以下の例題20のシミュレーション結果を見てみましょう。

レジスタのインクリメント及びデクリメント

変数の値を1足してその変数に書き戻すことをインクリメント
変数の値を1引いて変数に書き戻すことをデクリメントと言いますが、
NSLではレジスタに対してインクリメント、デクリメントできる単位アクションがあります。

++,– は演算子ではないことに注意してください。
変化した数値がレジスタに反映するのは次のクロックです。

レジスタの値をインクリメントするとき”++” を、
デクリメントする場合は”–” を用いて以下のように表記します。

レジスタ名++
レジスタ名–

インクリメント・デクリメントの例として、
以下の例題21を見てみましょう。

<<例題21.インクリメント・デクリメントの例>>
declare ex21{
   output f[4], g[4] ;
}
module ex21 {
   reg r1[4]=0, r2[4]=0 ;

   r1++ ; //式1
   r2-- ; //式2

   f = r1 ;
   g = r2 ;
}

例題21は、インクリメントとデクリメントの例です。
式1は、

r1 := r1 + 0×1

と同じ意味です。

また、式2は

r2 := r2 + 0×1

と同じ意味です。

例題21のシミュレーション結果を見てみましょう。