デザイン向け（論理合成可能）SystemVerilog記述

## ■ はじめに
VerilogはSystemVerilogへとアップグレードされ、多くの機能改善と強化がなされた。Verilogでの弱点はSystemVerilogでほぼ解消されたと言っても過言ではない。しかし、検証面での強化、改善が多く、ネットや本でも圧倒的に検証向けの情報が多い。中にはSystemVerilogを検証言語だと壮大な勘違いしている人もいるぐらいである。デザイン向けのSystemVerilogの情報が不足している様に思う。特に日本語での情報が少ないせいなのか、日本でのデザイン分野での浸透がまだいまいちな様に思う。なのでデザイン向けのSystemVerilogの記事を書いてみようと思った。
上述の様にデザイン向けの改善、強化項目は多くはないのだが、それらは非常に強力で、少し知っているだけで開発効率に雲泥の差が出る。なので今までVerilogしか使って来なかった人はこれを機に是非SystemVerilogを覚えて日々の開発業務に取り入れて役立ててもらいたい。なにも既に存在するVerilogのコードを全ていっぺんに置き換える必要はなく、SystemVerilogは完全に上位互換なので、使えそうな部分から少しずつ取り入れて改善して行けば良いのである。
以下、実用上よく使われ、有用だと思われるSystemVerilogのデザイン向けの記述方法を順次少しずつ書いて行くので是非参考にしてもらいたい。尚、一部Verilog 2001/2005の時点で既に導入されていた物も入れた。

## ■ logic
logicはassignでもalwaysでの代入でもどちらでも使える。要するにwireとregの両対応版。VHDLのsignalと同等。Verilogではassignの時にはwire,alwaysの時にはregといちいち気にしなくてはいけなかったが、System Verilogではlogicにしておけば一切気にする必要ない。なので今日からはlogicを使ってみよう。今までVerilogしか使っていなくてSystemVerilogを導入したいが何から手を付けていいか分からないという人はまずlogicを使ってみると良いと思う。

```verilog:logicの使用例
logic a, b, c, d, e;

assign c = a & b;

always@*
  if (d) e = c;
  else   e = 0;
```

ただ、wireでできる、宣言と同時にassignを省略しての継続代入には対応していないようなので注意。その場合はwireを使おう。logicの場合は手続き代入として扱われてしまう。

```verilog:宣言同時継続代入OK
wire c = a & b;
```
```verilog:宣言同時継続代入NG（手続き代入扱い）
logic c = a & b;
```

実はlogicは本当はwire/regの完全な置き換えと言う訳ではなく、SystemVerilogではwireの様な信号タイプを表すのとは別のデータタイプと言う属性を指定するのに導入された。なので以下の様な信号タイプをwire、データタイプをlogicに明示的に指定した記述は有効である。

```verilog:宣言同時継続代入OK
wire logic c = a & b;
```

信号タイプが省略されてlogicのみ記述された場合にassignかalwaysの代入のされ方によって信号タイプが自動で決定される。実はこれがlogicの本当の正体である。しかし、その正体を知らずともwire/regの置き換えと思って使って問題はない。

因みに信号タイプとしてはVerilogではwire/regであったが、SystemVerilogではwire/varの2つ。wireが継続代入向けでvarが手続き代入向け。

```verilog:wire/varとlogic
wire logic c;
var  logic e;

assign c = a & b;

always@*
  if (d) e = c;
  else   e = 0;
```

varが従来のregの扱いと同様。regはその名称からレジスターや順序回路にのみ用いられるとの誤解が多く、SystemVerilogでは代わりにvarが導入された。
SystemVerilogではregは信号タイプではなく、データタイプ扱い。但し、var専用でassignはN.G。なので実質Verilogのregと同じ。

```verilog:wire/varとreg
wire reg c; // N.G
var  reg e;
     reg f; // Implicit var declaration 
     
assign c = a & b; // N.G

always@*
  if (d) e = c;
  else   e = 0;

assign f = a | b; // N.G

```

一部のシミュレータではassingも可能の様だが規格上N.Gなので合成にはN.G。上述の様にregは誤解を生む名前の為SystemVerilogでは使用が推奨さない。なので未だにregを使う積極的は理由はないのでlogicを使うようにしよう。

## ■ always_ff, always_comb, always_latch
SystemVerilogでは設計者の意図を明確にする為に順序回路、組み合わせ回路、ラッチそれぞれのalways文が追加された。logicの次はこの辺りを使ってみよう。
それぞれ、always_ffなのに組み合わせ回路の記述、always_combなのにラッチの記述の様に意図しない記述をするとエラーとなるので事前にバグの検出ができる。組み込みのアサーションとも言える。是非積極的に使ってみてもらいたい。

- always_ff

always_ffはVerilogの順序回路のalwaysと同様に記述する。

```verilog:always_ffの使用例
always_ff@(posedge clk or negedge rst_n)
  if(!rst_n)    data <= '0;
  else if(en)   data <= in;
```

- always_comb

always_combはVerilogのalways@(xxx, yyy, ...)での組み合わせ回路記述のようなセンシティビティリストを記述しなくてもよい。

```verilog:always_combの使用例１
always_comb
  if(a) b = c;
  else  b = 0;
```
```verilog:always_combの使用例２
always_comb begin
  b = 0;
  if(a) b = c;
end
```
Verilog2001でもalways@\*と同等の記述ができるが、always@\*では
- functionの中から参照される信号センシティビティリストに含まれない
- シミュレーション開始時時刻0で実行されない
という問題があり、always_combではそれらが解消されているのでこちらを使うようにしよう。
以下、always@\*とalways_combの違いについて「[SystemVerilog Logic Specific Processes for Synthesis - Benefits and Proper Usage](http://www.sunburst-design.com/papers/CummingsSNUG2016SV_SVLogicProcs.pdf)」 by [Sunburst Design](http://www.sunburst-design.com)より抜粋。
![Capture2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/410e90c2-459e-258d-ad09-35e897b50d5d.png)
又、上述の[Sunburst Design](http://www.sunburst-design.com)のpaparにも紹介されているが、System Verilogで導入された返り値がvoidのvoid functionと組み合わせて以下の様な記述ができる。

```verilog:alwas_combとfunctionの組み合わせ
always_comb begin
  step_a();
  step_b();
  step_c();
end

function void function a();
...
endfunction

function void function b();
...
endfunction

function void function c();
...
endfunction
```
この記述はalways_combがfunction内で参照する信号もきちんとセンシティビティリストに入れてくれるから可能となる。こうすると何が良いかと言うと、always_combで行う組み合わせ回路ロジックの処理の抽象度を階層化できるのである。上位のalways_combで全体の処理フローが分かり、細かい処理はそれぞれのfunction内で行っている。一部のロジックの変更があった場合は対象のfunction内だけをいじれば良いのである。
この事に限らずまた後々キーワードとして出てくるが、なるべく「***抽象度***」を上げて、開発効率を上げ人間によるミスを少なくしたいのである。

- always_latch

ラッチは殆ど使う機会はないと思われるのでここでは省略。

## ■ .portname, .* module接続
SystemVerilogではmoduleの信号接続の記述をできる限り簡略化できるようになった。Verilogではポート名、ネット名で接続する場合
`module_name  instance_name  ( .portname(netname) );`
の様な記述が必要だったが、SystemVerilogではportnameとnetnameが同じであれば(netname)を書かなくてもよくなった。接続情報としては冗長なので。
`module_name  instance_name  ( .portname );`
さらに.portnameさえ記述しなくてもよく
`module_name  instance_name  ( .* );`
とすればポート名と同じ名前のネットを自動で接続してくれる。
これらは従来の接続方法とも混在可能で、ポート名と違う名前のネットを繋ぎたい所にだけ従来通りの接続方法にすることができる。

```verilog
block  i_block ( .clk, .rst_n, .port_a(signal_x) );
block  i_block ( .*          , .port_a(signal_x) );
```
しかし、`.*`での接続はどの信号が繋がっているかぱっと見分からないのでデザインで使用はあまりお勧めしない。今は亡き懐かしのSTARCの設計スタイルガイドでも`.*`での接続は禁止しているようだ。

https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7#215-%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%83%95%E3%82%A1%E3%83%B3%E3%82%AF%E3%82%B7%E3%83%A7%E3%83%B3%E5%AE%A3%E8%A8%80%E3%81%A8%E6%8E%A5%E7%B6%9Averilog-2001-systemverilog%E7%B7%A8

https://qiita.com/vega77/items/398a343ae616bd618f22
これらの接続方法はポートの数が少ないうちは大して効果はないが、数が膨大になってくるとかなり大きな効果を発揮してくる。

## ■ interface
SystemVerilogではmodule間接続を簡単にする為に更にinterfaceと言う物が導入された。これはmoduleの入出力信号をまとめた物である。バス信号などは同じ入出力信号の定義がいくつものモジュールで何回もされるのでその都度書くのは冗長である。なので１度定義しておいて、それをいろいろなモジュールで使い回わせば良いと言う発想である。
バスの信号をまとめて１つのinterfaceで表すと、モジュールの接続にバスの個々の信号を考えなくても良くなる。例えば、バスの信号の種類やビット幅等が変わったとしてもモジュール間の接続は一切変える必要はない。要するに***抽象度***を１段上げているのである。
以下に実際の使用例を示す。
![SV_Interface_1_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/199b3564-25bc-80dc-0243-72605a4c7819.png)

```verilog:bus_if.sv
//---- Definition of the interface ----//
interface #(parameter width=32) bus_if(input logic clk, rst_n);
  logic[ 7:0]      addr;
  logic            wr_rq;
  logic            rd_rq;
  logic[width-1:0] wr_data;
  logic[width-1:0] rd_data;
  logic            rd_en;
  modport mst_port(                  output addr, wr_rq, wr_data, rd_rq, input  rd_en, rd_data);
  modport slv_port(input clk, rst_n, input  addr, wr_rq, wr_data, rd_rq, output rd_en, rd_data);
endinterface
```
```verilog:top.sv
module top(input logic clk, rst_n, logic[7:0] cfg_reg, output logic[3:0] flag);

  bus_if #(32) bus1(.clk, .rst_n);  // <-- Instanciate the interface as bus1
  bus_if #(16) bus2(.clk, .rst_n);  // <-- Instanciate the interface as bus2

  master  mst( .clk, .rst_n, .cfg_reg, .flag, .bus1, .bus2 );
  slave  slv1( .bus(bus1) );
  slave  slv2( .bus(bus2) );
  /*------- Another Way --------------------
  master  mst( .clk, .rst_n, .cfg_reg, .flag, .bus1(bus1.mst_port), .bus2(bus2.mst_port) );
  slave  slv1( .bus(bus1.slv_port) );
  slave  slv2( .bus(bus2.slv_port) );
  ------------------------------------------*/

endmodule
```
```verilog:master.sv
module master (
 input  logic      clk, rst_n,
 input  logic[7:0] cfg_reg,
 output logic[3:0] flg,
 bus_if.mst_port   bus1,  // <-- Use mst_port of bus_if as port (interface) name bus1
 bus_if.mst_port   bus2   // <-- Use mst_port of bus_if as port (interface) name bus2
/*------- Another Way --------------------
 bus_if   bus1,  // <-- modport mst_port must be assigned in the upper module
 bus_if   bus2   // <-- modport mst_port must be assigned in the upper module
------------------------------------------*/
);

  assign  bus1.addr    = ...
  assign  bus1.wr_data = ...
  assign  bus1.wr_rq   = ...
  assign  bus1.rd_rq   = ...

  assign  bus2.addr    = ...
  assign  bus2.wr_data = ...
  assign  bus2.wr_rq   = ...
  assign  bus2.rd_rq   = ...

  always_ff@(posedge clk or negedge rst_n)
    if(!rst_n)          rd_data <= '0;
    else if(bus1.rd_en) rd_data <= bus1.rd_data;
    else if(bus2.rd_en) rd_data <= bus2.rd_data;
```
```verilog:slave.sv
module slave (
  bus_if.slv_port  bus   // <-- Use mst_port of bus_if as port (interface) name bus
/*------- Another Way --------------------
  bus_if bus   // <-- Modport mst_port must be assigned in the upper module
-----------------------------------------*/
);
  slave_sub  sub(.bus);  // <-- Pass the interface to a lower module (implicit port connection)
endmodule
```
```verilog:slave_sub.sv
module slave_sub (
  bus_if.slv_port  bus   // <-- Use mst_port of bus_if as port (interface) name bus
);
  assign  bus.rd_en   = ...
  assign  bus.rd_data = ...

  always_ff@(posedge bus.clk or negedge bus.rst_n)
    if(!bus.rst_n)     wdata <= '0;
    else if(bus.wr_rq) wdata <= bus.wr_data;
    else if(bus.rd_rq) ...
```
bus_ifでバスに使用される各信号を定義している。modportで各moduleで使用される際の方向を指定している。この例ではmodport mst_portでmaster用の信号の入出力の方向を決めている。それと対向するslave用にはmodport slv_portで信号の方向を決めていて、当然mst_portとは反対方向となる。modportはmodule portの事でその名の通りmoduleでのポートの入出力方向を記述している。時々interface自体の入出力と勘違いしている人がいるので注意。modportでの入出力方向の指定は、interface自体の入出力ではなくinterfaceを使うmoduleでの入出力方向である。
bus_ifで定義されたinterfaceをtopでbus1, bus2と言う名前でインスタンス化している。インスタンス化の方法はmoduleと同様で、moduleと同様にやはりparameterも使える。
こうしてインスタンス化されたinterface(bus1, bus2)をmasterとslaveの各moduleに接続している。接続の方法は通常の信号と同様だが、その方法に２通りある。１つはinterfaceのインスタンス名（bus1, bus2）をそのままmoduleにつなげる方法。もう１つはinterfaceのインスタンス名に続けてmodportを指定して接続する方法。この例のコメントアウトで示したの部分ではmaster向けには`.mst_port`を付けて、slave向けには`.slv_port`を付けて接続している。
下位モジュールのmaster及びslaveではinput, outputを使う代わりに定義したinterface名 bus_ifを用いる。その際に上述の上位モジュールでの接続方法によってそれぞれbus_if.mst_port, bus_if.slv_portとmodportを指定するか、modport名なしでbus_ifだけをしていする。要するに上位モジュールか下位モジュールのどちらかでmodportを指定していれば良い。又、両方で指定しても良い。
interfaceが繋がったmodule内では`<interface port name>.<signal name>`で信号にアクセスできる。この例では例えばmaster側ではbus1.rd_dataやbus1.wr_dataの様に信号にアクセスしている。そしてassignやalwaysで代入や参照する事ができる。
slave側ではさらにもう１階層下のmoduleであるslave_subにbusを渡している。このように下位階層にバスをあたかも１つの信号の様に渡すことができる。階層が深くなってくるとバス信号を渡すのも一苦労なので大変便利である。この事を説明している日本語のページをあまり見かけないので是非覚えておくと良いと思う。
上の例ではinterface内にMasterとSlaveそれぞれに対し１つの一対のmodporを持っていた。しかし、必ずしも一対である必要はなく、modportをいくつ持っても良い。例えば以下の例では一つのinterface内に２つのスレーブポートを持つようにした。それぞれ別名である必要があるのでslv_port1,slv_port2とした。
![SV_Interface_2_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/2059ec1f-4c24-5e09-279c-1124c9e0d1e4.png)

```verilog:bus_if.sv
//---- Definition of the interface ----//
interface #(parameter width=32) bus_if(input logic clk, rst_n);
  logic[ 7:0]      addr1   , addr2   ;
  logic            wr_rq1  , wr_rq2  ;
  logic            rd_rq1  , rd_rq2  ;
  logic[width-1:0] wr_data1, wr_data2;
  logic[width-1:0] rd_data1, rd_data2;
  logic            rd_en1  , rd_en1  ;
  modport mst_port(
    output addr1, wr_rq1, wr_data1, rd_rq1, input  rd_en1, rd_data1,
    output addr2, wr_rq2, wr_data2, rd_rq2, input  rd_en2, rd_data2
  );
  modport slv_port1(input clk, rst_n, input  addr1, wr_rq1, wr_data1, rd_rq1, output rd_en1, rd_data1);
  modport slv_port2(input clk, rst_n, input  addr2, wr_rq2, wr_data2, rd_rq2, output rd_en2, rd_data2);
endinterface
```

又、interfaceは内部にロジックを持つ事もできる。以下の例ではセレクターを持ってマスタ側のポートの信号を一組にした。
![SV_Interface_3_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/5081f11a-581a-6ca8-3c48-fc5bf109a603.png)

```verilog:bus_if.sv
//---- Definition of the interface ----//
interface #(parameter width=32) bus_if(input logic clk, rst_n);
  logic            sel2;
  logic[ 7:0]      addr   ;
  logic[width-1:0] wr_data, wr_data1, wr_data2;
  logic            wr_rq  , wr_rq1  , wr_rq2  ;
  logic            rd_rq  , rd_rq1  , rd_rq2  ;
  logic[width-1:0] rd_data, rd_data1, rd_data2;
  logic            rd_en  , rd_en1  , rd_en1  ;

  assign addr1    = addr   ;
  assign wr_data1 = wr_data;
  assign addr2    = addr   ;
  assign wr_data2 = wr_data;

  always_comb begin
    wr_rq1   = wr_rq  ; 
    rd_rq1   = rd_rq  ;
    if(sel2) begin
      wr_rq1   = 'b0; 
      rd_rq1   = 'b0;
    end
  end 
  always_comb begin
    wr_rq2   = 'b0; 
    rd_rq2   = 'b0;
    if(sel2) begin
      wr_rq2   = wr_rq  ; 
      rd_rq2   = rd_rq  ;
    end
  end 

  assign rd_data  = !sel2 ? rd_data1 : rd_data2;
  assign rd_en    = !sel2 ? rd_en    : rd_en2  ;

  modport mst_port (                  output  sel2 , addr , wr_rq , wr_data , rd_rq , input  rd_en , rd_data );
  modport slv_port1(input clk, rst_n, input          addr1, wr_rq1, wr_data1, rd_rq1, output rd_en1, rd_data1);
  modport slv_port2(input clk, rst_n, input          addr2, wr_rq2, wr_data2, rd_rq2, output rd_en2, rd_data2);
endinterface
```
### ・modport expression
interface内で定義した信号名がそのinterfaceが使われるmodule内でも参照信号名として使われるが、interface内の信号名とmodule内での参照信号名とで変えたい場合がある。その場合modeportで信号名を変換する事ができる。又、単に信号名を変えるだけでなく同時にビット選択や連結等の操作や簡単なロジック演算を行う事が出来る。
上記のマスターポート１つスレーブポート２つのinterfaceは以下の様にする事もできる。

```verilog:modport_expression
interface #(parameter width=32) bus_if(input logic clk, rst_n);
  logic                 sel2;
  logic     [ 7:0]      addr;
  logic     [width-1:0] wr_data;
  logic                 wr_rq  ;
  logic                 rd_rq  ;
  logic[1:2][width-1:0] rd_data; // <-- 2D Array
  logic[1:2]            rd_en  ;
  modport mst_port (output sel2, addr, wr_rq, wr_data, rd_rq, input  .rd_en(!sel2 ? rd_en[1] : rd_en[2]), .rd_ata(!sel2 ? rd_data[1] : rd_data[2]));
  modport slv_port1(input clk, rst_n, input  addr, .wr_rq(!sel2 ? wr_rq : 'b0), wr_data, .rd_rq(!sel2 ? rd_rq : 'b0), output .rd_en(rd_en[1]), .rd_data(rd_data[1]));
  modport slv_port2(input clk, rst_n, input  addr, .wr_rq( sel2 ? wr_rq : 'b0), wr_data, .rd_rq( sel2 ? rd_rq : 'b0), output .rd_en(rd_en[2]), .rd_data(rd_data[2]));
endinterface
```
と、この様にmodule側で使用したい信号名の前に`.`を付けてinterface側の信号は`()`の中に入れる。
この記事とか参照。

https://sites.google.com/site/dejitarudezainfan/systemverilog/interface#h.p_ID_513

なおこの例ではrd_dataのビット分割に分かり易い様に２次元配列を使った。下の方に出てくる[多次元Vector/Array](#-多次元vectorarray)を参照。

### ・generic interface
interfaceのmoduleでの宣言方法としてgeneric interfaceと言う物もある。generic interfaceではmoduleのポートの入出力宣言にbus_ifの様な自分で定義したinterface名を使う代わりに`interface`キーワードそのものを使用する。

```verilog:generic_interface
module slave_sub ( interface  bus　);
```
[この記事とか参照](http://japanese.sugawara-systems.com/systemverilog/interface.htm)。
この様にするとinterfaceを使用する下位moduleではinterfaceの種類を意識しなくて済む。interfaceの種類はinterfaceをインスタンス化する上位のmoduleがインスタンス時に指定する。この様に下位のmoduleがinterfaceの種類を意識しなくて済むと何が良いかと言うとinterfaceの種類を変えたい時に下位moduleは一切変えなくて良いと言う事である。ここでもやはり更に***抽象度***を上げて柔軟性が上げていると考えられる。[電子回路日和](https://sites.google.com/site/dejitarudezainfan/systemverilog/interface)ではgeneric interfacceはあまり利点が無いのではと述べているが、それは大いに違うと思う。特にmodule階層が深い大規模な開発でinterfaceを変更したい場合、通常のinterfaceでは下位のmoduleでのポート宣言のinterface名を全て変えなくてはならずとても大変である。それに対してgeneric interfaceであれば下位moduleのポートでは全て`interface`で宣言されているので変えなくて良いのである。むしろ通常のinterface名を使ったポート宣言方法の方が不要なんじゃないだろうかと思う。一体なぜそんな物作ったのだろう。せっかくの抽象度を上げる手段なのに台無しである。moduleのポート宣言もgeneric interfaceの方が理解し易いし、generic interfaceだけで良いのではないかと思う。なのでinterface名を使用した通常のポート宣言よりこのgeneric interfaceの方の使用を強くおススメする。

因みに以下の記事ではこのgeneric interfaceを使用して上位からの下位moduleの機能の変更方法を紹介している。

https://qiita.com/taichi-ishitani/items/03b13589431c5213b968

generic interfaceの高抽象度に起因する柔軟性を利用しているのである。

### ・Interface Array
interfaceは配列として扱う事もできる。これもmoduleの配列と同様にインスタンス名の横に`[]`を付けて配列の数を指定する。`[N]`の様に配列数で指定しても良いし、`[0:N-1]`や`[1:N]`の様に配列インデックスの範囲で指定しても良い。`[N]`とした場合は`[0:N-1]`と指定したのと同じ。
インスタンス名の括弧を省略した名前自体は配列の全体を表す。なので、下位moduleのport接続には括弧なしのインスタンス名を使う事ができる。その際に上述した[.portname, .* module接続](#-portname--module%E6%8E%A5%E7%B6%9A)を使う事もできる。もちろん従来通り明示的に`.bus(bus)`の様に接続しても良い。又、配列の範囲の括弧を省略せずに`.bus(bus[0:1])`様に書いても良い。しかし、`.bus(bus[2])`の様には書けない。`.bus(bus[X])`は配列のうちのインデックスXで指定した個別の要素を指定している事になる。
下位モジュールでは`bus_if.mst_port bus[2]`の様にmodport名付きでinterfaceの定義名を指定し、ポートインスタンス名に括弧で配列の指定をする。`bus[0:1]`の様にやはりインデックスの範囲で指定しても可。
上位モジュールでは`.bus(bus.mst_port)`や`.bus(bus[0:1].mst_port)`の様なmodport名を指定した接続はできない。~~従って、上位でのmodport名指定が必須な[generic interface](#generic-interface)は使用できない。~~ 上位でのmodport名指定が必須な[generic interface](#generic-interface)を使用する場合には下位のモジュールで`interface.mst_port bus[10]`の様にmodport名を指定する。但しLRMに明確に記述されていないので合成ツールが対応できているかは分からない。

![SV_Interface_Array.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/9429602b-b8c8-e6f9-faca-a0e0dbb9e894.png)

```verilog:bus_if.sv
interface #(parameter WID=32) bus_if(input clk, rst_n);
  logic          wr_rq, rd_rq;
  logic[ 7:0]    addr;
  logic[WID-1:0] wr_data, rd_data;
  logic          rd_en;
  modport mst_port(input clk, rst_n, output addr, wr_rq, wr_data, rd_rq, input  rd_en, rd_data);
  modport slv_port(input clk, rst_n, input  addr, wr_rq, wr_data, rd_rq, output rd_en, rd_data);
endinterface
```
```verilog:top.sv
module top(input logic clk, rst_n);

  bus_if  bus[2]   (.clk, .rst_n);  //Interface Array 
//bus_if  bus[0:1] (.clk, .rst_n);  //Interface Array 
//bus_if  bus[1:2] (.clk, .rst_n);  //Interface Array 
  
  master  mst( .bus );
  slave   slv( .bus );

//master  mst( .bus(bus)      ); // OK
//slave   slv( .bus(bus)      ); // OK
//master  mst( .bus(bus[0:1]) ); // OK
//slave   slv( .bus(bus[0:1]) ); // OK
//master  mst( .bus(bus[2]  ) ); // NG
//slave   slv( .bus(bus[2]  ) ); // NG

//master  mst( .bus(bus.mst_port)      ); // NG
//slave   slv( .bus(bus.slv_port)      ); // NG
//master  mst( .bus(bus[0:1].mst_port) ); // NG
//slave   slv( .bus(bus[0:1].slv_port) ); // NG

endmodule
```
```verilog:master.sv
//module master ( interface          bus[2] ); // NG, generic interface
//module master ( interface.mst_port bus[2] ); // OK, generic interface
module master ( bus_if.mst_port bus[2] );
  generate
  for(genvar i=0; i<2; i++) begin
    assign  bus[i].addr    = ...
    assign  bus[i].wr_data = ...
    assign  bus[i].wr_rq   = ...
    assign  bus[i].rd_rq   = ...
  end
  endgenerate
```
```verilog:slave.sv
//module slave ( interface          bus[2] ); // NG, generic interface
//module slave ( interface.slv_port bus[2] ); // OK, generic interface
module slave ( bus_if.slv_port bus[2] ); // bus[0:1] is also OK
  generate
  for(genvar i=0; i<2; i++) begin
    slave_sub  sub( .bus(bus[i]) ); // Connect Individual Array Item
  end
  endgenerate
endmodule
```
```verilog:slave_sub.sv
//module slave_sub ( interface bus ); // generic interface
module slave_sub ( bus_if.slv_port bus );
always_comb
    if(bus.wr_rq)
      ...
    else if(bus.rd_rq)
      ...
```

### ・Assertion
interface内には[アサーション](#-assertion)を書く事ができる。プロトコルが決まったバスをinterfaceでまとめた場合等は非常に有効なので是非interfaceに[アサーション](#-assertion)も入れてみてもらいたい。[アサーション](#-assertion)に関しては下で紹介しようと思う。

## ■ package
packageは複数のmodule間で定数や定義などのリソースを共有する為に使用する。VHDLでは同じくpackageというのがありお馴染みだが、Verilogでは無かった概念で、SystemVerilogでようやく導入された。なのでVerilogしか知らない人には最初理解に戸惑う人もいる様だ。要するにいろんな所（module）で共通で利用できるライブラリだ。C++でのnamespaceと同等。
あまり知られてない様だがデザイン向けにもpackageを使う事ができる。デザイン向けには主にはparameter, localparam, function等をpackageに入れる事ができる。それから後述する [typedef](#-typedef) [struct](#-struct), [typedef](#-typedef) [enum](#-enum)なんかも入れる事ができる。 Assertionを使用する場合にはpropertyの定義なんかもpackageに含めることができる。デザイン向けには値が変わる変数は入れることはできない。ただしあまり必要性はないかもしれないが、const設定された変数は使用可能ではないかと思われる。固定値は通常parameterかlocalparamを使用する。以下、packageの例。

```verilog:common_lib_pkg.sv
`ifndef COMMON_LIB_PKG_SV
`define COMMON_LIB_PKG_SV
package common_lib_pkg;

  parameter  p_NUM_CHANNEL = 8;

  function automatic logic[3:0]  calc (input logic[7:0] a,b);
    if(a[7])    calc = a + b;
    else        calc = 0;
  endfunction

endpackage
`endif
```
この例ではパラメータp_NUM_CHANNELとcalcというfunctionをpackageに入れている。デザインに使用するpackage内のfunctionにはautomaticが必須。コールされる度に別インスタンスとなるので。
因みにここで使用している\`ifndef, \`define, \`endifはインクルードガードと言ってC/C++や他ソフトウエア言語ではよく用いられる。ヘッダファイルの様に複数のファイルでincludeされた場合に、重複コンパイルを避けるために最初にincludeされた記述のみ有効にして他は無効にする為だ。packageは上述のようにライブラリとして用いられるので、Cでのライブラリの使用方法と同様に、使用するmoduleファイルの先頭でincludeされたりする場合がある。そのような使われ方をした場合に重複コンパイルでトラブルとなる事を避ける為に入れておくと無難である。includeせず、コンパイルリストにpackageのファイルも追加して、他moduleのファイルと一緒にコンパイルする場合にはインクルードガードは必要無いが、一応入れておいた方が良いだろう。又、他moduleと一緒にコンパイルする時にはそのpackageを使用するmoduleより先にコンパイルされている必要があるので要注意。
packageの使用方法については以下で説明する。
### ・package内リソースへのアクセス方法
packageの使用方法（リソースへの参照方法）は以下の２通りがある。
1. `import <package name>::<resource name>`で暗黙的に参照
2. その都度明示的に`<package name>::<resource name>`で参照

どちらもスコープ演算子`::`を用いてpackage内のリソースを指定している。

#### 　1. importで暗黙的に参照
一度`import <package name>::<resource name>`を宣言するとそのpackageの指定したリソースへは以降特に何も指定しなくても参照が可能となる。リソースの指定にはワイルドカード`*`を使ってすべてにアクセス可能とする方法と、リソース名を個別に指定する方法の２つがある。
* `import <package name>::*;`
* `import <package name>::<resource name>;`

module内のどこでもimport宣言できるが、通常はmoduleの先頭で行い、そのmodule内であればどこでもそのpackageのリソースへアクセス可能にしておく。

```verilog:import宣言で暗黙的にpackageリソースへアクセス
module  example1  (input logic in_a, in_b, output out_z);
  import common_lib_pkg::*;         // All resouces inside common_lib_pkg are available after this in this module.
  import special_pkg::p_BUS_WIDTH;  // Only p_BUS_WIDTH inside special_pkg is available after this in this module.

  logic[p_BUS_WIDTH-1:0] data;
```
ポートの信号にもpackage内で定義したリソースを使いたい場合がある。その場合にはmodule名宣言の直後、パラメータ、ポート宣言の前にimport宣言を置く事もできる。

```verilog:module宣言の直後でimport宣言
module  example2
  import common_lib_pkg::*;
  import special_pkg::p_BUS_WIDTH;  // p_BUS_WIDTH is used for output bus width.
  #(parameter p_ID = 0)
  (input logic in_a, in_b, output  logic[p_BUS_WIDTH-1:0] out_z);

  logic[p_BUS_WIDTH-1:0] data;
```
importはmodule内だけでなく、package内で使用してpackageから更に別のpackageのリソースへアクセスする事も可能。
更にmoduleの外のグローバル領域でもimport宣言が可能ではあるがそれはお勧めしない。何故なら全てのmoduleでpackage内のリソース名との名前の競合を気にしなくてはならないからである。せっかく名前の競合を避けたくてpackageを使ったのにそれでは本末転倒である。だったら初めからpackageなんか使わずに裸でグローバル領域に置けばいいのである。やはりimportを使うのはmoduleやpackageの中でのみにした方が良いだろう。
`import <package name>::*;`は丁度C++での`using namespace <space name>;`と同等なのである。packageの意味もnamespaceと捉えた方がが分かりやすいのではないだろうか。

#### 　2. `::`で明示的に参照
importを使わずともスコープ演算子`::`を使用してpackage内のリソースに直接アクセスする事ができる。以下その例。

```verilog:明示的packageリソース参照
module  example2
 #(parameter p_ID = 0)
  (input logic in_a, in_b,
   output  logic[special_pkg::p_BUS_WIDTH-1:0] out_z  // p_BUS_WIDTH is referred without import
  );

  logic[special_pkg::p_BUS_WIDTH-1:0] data;  // p_BUS_WIDTH is referred without import
```
この例の様に、当然ポートリスト宣言の信号でもmoduleの内部の信号でもどこでも使える。importに対する利点としてはmodule内の名前との競合が起きない点がある。ただしimportと違い、参照する度にその都度`<package name>::`を書く必要があるので参照する回数が多いと面倒になってくるという欠点がある。
`::`も丁度C++でのnamespace内の変数へのアクセスに使うそれと全く同じである。

### ・export
importの他にexportと言う物ある。これはpackageの中で使い、他のpackageのリソースをそのpackage内に展開して、あたかもそのpackagegのリソースの様に扱いたい場合に使用する。なのでexportしたリソースは展開された先のpackage名で外からも参照する事ができるのである。importではそのpackage内でのみしか参照できない。exportを使うとpackageを階層構造にすることができる。

```verilog:top_pkg.sv
package top_pkg;
  parameter p_WIDTH = 8;
  parameter p_DEPTH = 256;
endpackage
```
```verilog:top.sv
module top import top_pkg::*;
  (input logic[p_WIDTH-1:0] a,b, output logic z);

  sub i_sub (.a, .b, .z);
```
```verilog:sub_pkg.sv
package sub_pkg;
  export  top_pkg::p_WIDTH; // <---- Borrow p_WIDTH from top_pkg
  parameter  p_NUM_CHANNEL = 8;
endpackage
```
```verilog:sub.sv
module sub
//import top_pkg::*; // <---- This is not necessary.
  import sub_pkg::*;
  (input logic[p_WIDTH-1:0] a,b, output logic z);
```
この様にするとsub以下ではtop_pkgを参照せずともsub_pkgの参照のみで良くなる。
exportを説明している日本語のページをあまり見かた事がないので是非参考にしてみてもらいたい。
尚、とあるLint Checkerで`export::*;`としたら何故かexportされた筈のリソースをきちんと認識してくれなかったのでexortでワイルドカードを使ってはいけないのかもしれない。その場合はexportではワイルドカードを使わず、個別でexportをしよう。

## ■ typedef
typedefはC言語などではお馴染みだがSystemVerilogにも導入された。ユーザーがデータのタイプ名を新たに定義でき、使うことができる。VHDLではsubtypeが同様の物。例えば

```verilog:typedefの例
typedef  logic[15:0]  byte2_t;

byte2_t  signal_A;
assign singal_A = 'hAABB;
```
の様にtypedefでlogic[15:0]と言うタイプにbyte2_tと言う別名を定義する。この定義したbyte2_tと言うタイプでsignal_Aを宣言した。signal_Aにはlogic[15:0]で宣言したのと同様に代入、参照ができる。
実用上はlogic[15:0]をtypedefでユーザータイプ定義することは殆ど意味がない。実際には以下で紹介する[struct](#-struct)や[enum](#-enum)と一緒に使う事が殆どだろう。C言語ではよくunsigned intをuintとかuint32とか定義したりする。

## ■ struct
structもC/C++ではお馴染み。VHDLではrecordに相当。いくつかの信号をまとめた物。

```verilog:structの例
  struct {
    logic[7:0]  data;
    logic[3:0]  addr;
    logic[7:0]  bit_en;
    logic       write_en;
  }  bus_signals;
```
この例ではdata, addr, bit_en, write_enと言う信号をひとまとめにしてbus_signalsというひと塊のstruct信号にした。structのメンバへの信号の代入と参照には`.`でアクセス可能。

```verilog:structアクセス例
 assign  bus_singals.data     = 'hFF;
 assign  bus_signals.addr     = 'hA;
 assign  bus_signals.bit_en   = 'hF;
 assign  bus_signals.write_en = signal_A; 

 assign  write_data = bus_signals.data;
```
又、以下の様な代入方法も可能である。

```verilog:structへの一括代入
 assign  bus_signals = '{ data : 'hFF, addr : 'hA, bit_en : 'hF, write_en : signal_A};
```
又、この代入方法ではすべて同じ値を入れるdefaultが使える。

```verilog:structへのdefaultでの代入
always_ff@(posedge clk or negedge rst_n)
  if(!rest_n)
    bus_signals <= '{ default : 0, addr : 'hF};
```
この例の様にdefaultの値以外を入れたい場合はそのメンバだけ別の値を指定する事もできる。
同じstruct同士であれば一括で直接代入も可能。

```verilog:struct一括直接代入
  struct {
    logic[7:0]  data;
    logic[3:0]  addr;
    logic[7:0]  bit_en:
    logic       write_en;
  }  bus_signals, bus_signals_pre;

always_ff@(posedge clk or negedge rst_n)
  if(!rest_n)    bus_signals <= '{ default : 0};
  else           bus_signals <= bus_signals_pre;
```

ここでpackedと言う概念を紹介する。packedを指定するとstructのそれぞれのメンバーはメモリ上、隣り合って配置される事になる。なのでreg/wire/logcのベクターと同じ扱いになりビット位置の番号でアクセスもできる。

```verilog:structのpacked
struct packed {logic[7:0] data; logic[3:0] addr; logic[7:0] bit_en; logic write_en;}  bus_signals;

 assign  bus_signals[20:13] = 'hFF;      // data
 assign  bus_signals[12: 9] = 'hA;       // addr
 assign  bus_signals[ 8: 1] = 'hFF;      // bit_en
 assign  bus_signals[    0] = signal_A;  // write_en
```
この例では分かりやすいようにstructを改行せず一行で書いてみた。左側のメンバが上位ビットに割り付けられる。改行して書く場合には上に書かれるメンバが上位ビットになる。ベクターと同じ扱いなので、structをベクターに代入したり、ベクターをstructに代入する事も可能になる。

```verilog:structのvector代入参照
struct packed {logic[7:0] data; logic[3:0] addr; logic[7:0] bit_en; logic write_en;}  bus_signals;
logic [20:0]  a, b;

 assign  bus_signals = a; 
 assign  b = bus_signals;
```
このようにpackedにする方ができる事が多く何かと便利なのでデザインでは特に理由がなければpackedを使うようにしよう。STARCの設計スタイルガイドでもunpackedの使用を禁止している[（参照）](https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7#212-%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AE%E6%8B%A1%E5%BC%B5systemverilog-%E7%B7%A8)。
さて、このstructだが、複数の箇所で宣言する場合いちいちその宣言ごとにメンバーの定義をしなくていはならない。それは非常に面倒である。なので実際には[typedef](#-typedef)と合わせて使う事が殆どである。以下の例の様にmodule内の一か所でstructを[typedef](#-typedef)でbus_strとして定義しておけばそのmodule内のどこででもbus_strを複数回宣言する事ができる。

```verilog:typedefでstructを定義
typedef struct packed {
  logic[7:0] data;
  logic[3:0] addr;
  logic[7:0] bit_en;
  logic write_en;
}  bus_str;

bus_str  signals_a;
bus_str  signals_b;
bus_str  signals_c;
```
そしてさらに、module間でも同じstructを共有したい。そこですでに紹介した[package](#-package)を使うのである。以下の様にpackage内で[typedef](#-typedef)を使ってstructの定義をする。

```verilog:common_pkg.sv
package common_pkg;

  typedef struct packed {
    logic[7:0] data;
    logic[3:0] addr;
    logic[7:0] bit_en;
    logic write_en;
  }  bus_str;

endpackage
```
そしてその定義したタイプを各moduleで共通して参照するのである。参照の仕方は既に紹介したように`import`宣言１回で以降は暗黙的に参照可能にしても`<package name>::`で毎回個別に明示的に参照してもどちらでも良い。

```verilog:block_a.sv
module(input clk, rst_n, input  common_pkg::bus_str bus_signals);
```
```verilog:block_b.sv
module(input clk, rst_n, output common_pkg::bus_str bus_signals);
```
```verilog:top.sv
module(input clk, rst_n);
  import  common_pkg::*;
  bus_str bus_signals;
  block_a a(.clk, .rst_n, .bus_signals);
  block_b b(.clk, .rst_n, .bus_signals);
```
この例の様にmoduleの内部信号だけでなく当然入出力信号のタイプにも使えるのである。つまり[interface](#-interface)で信号をまとめたのと同様にstructでも入出力信号をまとめる事が出来るのである。[interface](#-interface)と違いstructは単にまとめるだけなのでポートの入出力の方向はinputかoutputの一方向だけである。そして当然moduleのportに使用する場合にはinputかoutputを付ける必要がある。このようにstructをpackageと合わせてmoduleの入出力信号に使うと簡易的な[interface](#-interface)っぽい使い方ができる。
[interface](#-interface)と同様にstructで同じ仲間の信号をグループとしてまとめると言う事はやはり「***抽象度***」を上げていると言う事なのである。そのまとめた信号グループ単位で一括処理できたり、名前でアクセスできるからである。信号に限らず処理なども同じ仲間でまとめると言う事はやはり「***抽象度***」を上げているのである。因みに余談だがSystemVerilogにもあるオブジェクト指向プログラミングのclassも関数や変数を仲間でまとめて抽象度を上げているのである。

## ■ union
unionはC/C++のそれと同様。[struct](#-struct)と似ているが[struct](#-struct)程使用頻度は高くないだろう。unionも[struct](#-struct)同様にいくつかの信号を一つにまとめるのだが、[struct](#-struct)が別々の信号としてまとめるのに対しunionでは同じ信号線を共有する。信号を共有するので、同じ信号を違う名前で参照できるのである。例えば信号DATA_AとDATA_Bがあったとして以下の様にunionを定義してみる。

```verilog:unionの例（合成不可）
union {
  logic[31:0]  DATA_A;
  logic[16:0]  DATA_B;
}  united_data;
```
メンバへのアクセスはstructと同様にunited_data.DATA_A、united_data.DATA_Bと.と名前でアクセスするが[struct](#-struct)との違い、このunited_dataは32ビットの信号となり、united_data.DATA_Aはその32ビットのすべてビット、united_data.DATA_Bはその32ビットのうちの16ビットの信号線を表す。
ただし、この例では合成は不可で、合成可能なデザイン向け記述にするにはunionの各メンバが同じビット幅でかつpackedで宣言する必要がある。

```verilog:unionの例（合成可能）
union packed {
  logic[31:0]  DATA_A;
  logic[31:0]  DATA_B;
}  united_data;
```
しかし、この例では実用的ではない。同じlogic[31:0]の信号にDATA_Aと参照しようがDATA_Bと参照しようがどちらも大した違いが無いからである。unionを使う意味が出てくるのは各メンバのタイプが違う場合、特に[struct](#-struct)で定義されたタイプを使う場合である。

```verilog:unionの実用的な例
typedef union packed {
  logic     [31:0]  DATA_32 ;
  logic[0:3][ 7:0]  DATA_8x4;
  struct packed {logic[15:0]  opcode; logic[7:0]  data1; logic[7:0]  data2;    }  CMD;
  struct packed {logic[15:0]  addr  ; logic[15:0]  data;                       }  ADD_DATA;
  struct packed {logic[ 7:0]  mode  ; logic[7:0] R; logic[7:0] G; logic[7:0] B;}  COLOR;  
  struct packed {logic[ 7:0]  mode  ; logic[7:0] Y; logic[7:0] U; logic[7:0] V;}  COMPONENT;  
}  data_set_32bit_t
```
この例の様にunionも[struct](#-struct)同様[typedef](#-typedef)で定義できる。そして以下の様に用いる。

```verilog:union使用例
data_set_32bit_t  data_set;

always_comb
  if(...)
    data_set.DATA_32       = 'hABCD;
  else if(...) begin
    data_set.DATA_8x4[0]   = 'hA;
    data_set.DATA_8x4[1]   = 'hB;
    data_set.DATA_8x4[2]   = 'hC;
    data_set.DATA_8x4[3]   = 'hD;
  end
  else if(...) begin
    data_set.CMD.opcode    = 'b1111_1111_0000_0001; 
    data_set.CMD.data1     = 100; 
    data_set.CMD.data2     = 200;
  else if(...) begin
    data_set.ADD_DATA.addr = 'hB5;
    data_set.ADD_DATA.data = 'h33;
  end
  else if (...)
    data_set.COLOR         = '{mode : 0, R : 255, G :  0, G : 255};
  else if (...)
    data_set.COMPONENT     = '{mode : 1, Y : 100, U : 30, V :  50};
```
これらはすべて同じ32ビットの信号線のdata_setに対して、場合によって違う名前や方法で代入しているのである。
ここでは使用しなかったが以下で説明する[enum](#-enum)も入れる事もできる。opcodeやmodeには[enum](#-enum)を使用すべきであろう。そして当然[struct](#-struct)同様packageに入れる事ができる。

## ■ enum
enumは列挙(enumeration)タイプの事である。C言語やVHDLにもありSystemVerilogでも導入された。信号の値を数値で表すのではなく名前で表したいときに使う。具体的には何かのモードやステートマシーンのステートを記述するのが典型的な使い方だ。

```verilog:enumの記述例１
enum logic[1:0] {READ, WRITE, SLEEP, NOP}  command_mode;

always_comb begin
  command_mode = NOP;
  if     (xxx) command_mode = READ;
  else if(xxx) command_mode = WRITE;
```
このようにenumの後にその信号に必要なビット数をlogicタイプで書いてその後にそのenumで識別する任意の名前を列挙していく。そしてその後にこれを使う信号名を書く。この例ではREAD, WRITE, SLEEP, NOPの4つの状態を識別する信号command_modeをenumで宣言した。４つの状態なので2ビットのlogic[1:0]とした。このlogic[1:0]を省略するとint(2値,32ビット)になるのでテストベンチではそのような記述でも良いがデザイン向けには必ず指定するようにしよう。
enumで信号を宣言すると、その信号への代入や参照には数値ではなく列挙した名前で行う。この例ではcommand_modeに`NOP`,`READ`,`WRITE`を代入している。
これらの列挙名には実際の数値が左から0,1,2,3...と自動的に割り当てられる。もしその値の割り当てを変えたい場合には以下の様にする。

```verilog:マニュアルでの数値割り当て
enum logic[1:0] {READ = 'b10, WRITE = 'b01, SLEEP = 'b11, NOP = 'b00}  command_mode;
```
特に決まった数値があるわけでは無ければあえてマニュアルで割り当てる必要はない。
以下はステートマシーンの記述にenumを使用した例。

```verilog:ステートマシーンでのenum
enum logic[2:0] {READY, WAIT, LOARD, EXEC, ABNORMAL } state;

always_ff@(posedge clk or negedge rst_n)
  if      (rst_n)                state <= READY;
  else if (clr)                  state <= READY;
  else
    case (state)
      READY    : if      (run)   state <= WAIT;
      WAIT     : if      (start) state <= LOAD;
      LOAD     :                 state <= EXEC;
      EXEC     : if      (term)  state <= WAIT;
                 else if (done)  state <= WAIT;
                 else if (abnml) state <= ABNORMAL;
      ABNORMAL :                 state <= READY;
      default  :                 state <= READY;
    endcase
```
どうだろうか。このようにモードやステートを数値で書くより意味ある文字で表した方が意図が分かりやすいのではないのだろうか。丁度0/1の機械語の代わりに人間にとって意味の分かりやすいアセンブリ言語で書くのと同様である。やはり、ここでもenumで人間にとって意味のない数値を文字列にと言う意味のあるものに置き換えて「***抽象度***」を上げているのである。parameter/localpramを使っても同様に文字表示的にする事はできるが、数値の割り当て記述は人間が行わなくてはならず、いろいろとミスを誘発する原因になるのでenumを使用する事をお勧めする。機械が得意な事は機械にやらせておけば良いのである。
このenumも[struct](#-struct)と同様に複数個所で宣言するには[typedef](#-typedef)が使われる。ステートマシーンの様な物では一か所での宣言で済むだろうからあえて[typedef](#-typedef)をする必要性もないが、モードの様な信号では[typedef](#-typedef)が必要となってくる場合が多いのではないだろうか。特にmodule間にまたがってモードを知らせるような場合も多いだろう。その場合も[struct](#-struct)と同様にやはりpackageに入れて定義することができる。

```verilog:common_pkg.sv
package common_pkg;

  typedef enum logic[1:0] {READ, WRITE, SLEEP, NOP}  command_e; // <-- enum type definition inside package

  typedef struct packed { command_mode_e cmd_md; logic[3:0] addr; logic[7:0] bit_en; logic write_en; }  bus_str;

endpackage
```
そして、この例の様にenum自体を[struct](#-struct)に入れる事もできる。packageで定義されたenumのmoduleでの使い方も[struct](#-struct)と同様にimportや`::`でアクセスできる。

```verilog:package内で定義されたenumの使い方
import  common_pkg::*;
command_mode_e  md;

always_comb
  if     (rd)        md = READ ;
  else if(md == NOP) md = SLEEP;
```
又、package内でexportで他のpackageからenumを取り込んでいる場合には、列挙メンバ名の参照、代入はexportされた先のpackageではなくexport元のpackageをスコープ演算子で指定する必要がある。

```verilog:common_pkgからenumをexport
package  another_pkg;
  export  common_pkg::command_mode_e;  // <-- export from common_pkg
endpackage
```
```verilog:他のpackage内で定義されたenumのをexportされた場合の使い方
import  another_pkg::*;  // import another_pkg
command_mode_e  md;

always_comb
  if     (rd)                    md = common_pkg::READ ;
  else if(md == common_pkg::NOP) md = common_pkg::SLEEP;.
```

因みにデザインでは関係ないが、テストベンチで使うclass内で定義されたenumの他の場所(moduleやclass)からのアクセスにもスコープ演算子`::`を使う。

```verilog:class内でのenum
class pkt_ctrl;
  typedef  enum {SEND, RECEIVE, DISCARD, HOLD}  pkt_ctrl_e;
```
```verilog:他のclassからのenum参照
class flow_control;
  pkt_ctrl::pkt_ctrl_e  cmd_1, cmd_2;  // <-- Use enum defined in another class with "::".
  
  function  void copy_pkg();
    if(cmd_1 == pkt_ctrl::DISCARD) cmd_2 = pkt_ctrl::SEND;  // <-- "::" is used to assing and refer enumerated names.
    else                           cmd_2 = cmd_1;
```
あともう１点余談だが、テストベンチでenumで宣言した変数をプリントしたい場合には%pで表示する方法と、.name()を使ってstringにして出力する方法２つある。

```verilog:
module tb;
  enum  {RED, GREEN, BLUE} color;

  initial  begin
    color = RED   ;  $display( "%p  %s", color, color.name() );
    color = GREEN ;  $display( "%p  %s", color, color.name() );
    color = BLUE  ;  $display( "%p  %s", color, color.name() );
  end
endmodule
```
```:実行結果
# RED  RED
# GREEN  GREEN
# BLUE  BLUE
```

## ■ 多次元Vector/Array
System Verilogになって多次元配列がサポートされた。これもUnpackedとPackedの２種類ある。UnpackedとPackedの違いは[struct](#-struct)のそれと同様で、メモリ上に一続きのデータとして配置されるか、一続きになっていないかの違い。
以下、それぞれ8ビットのベクター信号が4つある場合、つまりの8x4の２次元配列の例。

```verilog:Unpacked
  logic[7:0]  data0,data1,data2,data3;
  logic[7:0]  data_8x4[4];    // <- 8x4 array, [0:3] is same.
//logic[7:0]  data_8x4[0:3];

  always_comb
    if(valid) begin
      data_8x4[0] = data0;
      data_8x4[1] = data1;
      data_8x4[2] = data2;
      data_8x4[3] = data3;
    end
    else
      data_8x4 = '{default : 8'h00, 3 : 8'hFF};
```
```verilog:Packed
  logic     [7:0]  data0,data1,data2,data3;
  logic  [4][7:0]  data_8x4;  // <-- 8x4 array, [0:3][7:0] is same.
//logic[0:3][7:0]  data_8x4;

  always_comb
    if(valid) begin
      data_8x4[0] = data0;
      data_8x4[1] = data1;
      data_8x4[2] = data2;
      data_8x4[3] = data3;
    end
    else
      data_8x4 = '{default : 8'h00, 3 : 8'hFF};
    //data_8x4 = {{3{8'h00}}, 8'hFF };  // This is also O.K.
```
Unpackedはベクターで宣言された信号名の右に配列の要素数を[4]と書く。要素数ではなくてベクター表記[0:3]の様に書いても同様だが要素数で書いた方が分かりやすいだろう。
PackedはVerilogでやっていたベクター表記[7:0]の左側に配列の要素数を[4]と書く。或いはベクター表記[0:3]でも同様。
ビットの参照、代入にはPacke/Unpackedとも同様に、data_8x4[0][7:0]の様に信号名[要素番号]の右にカッコを付けて表す。一番右のカッコがVerilogでのベクターと同様。その左側のカッコ[要素番号]はそれが何番目のベクターなのかを表す。例で示したようにそのベクターのカッコを省略するとそのベクターの全てのビットである。なのでdata_8x4[0][7:0]はdata_8x4[0]と書いたのと同じである。これもVerilogのベクターと同様。
何番目のベクターかを表すカッコも省略し、dataの様に書くとその配列名全体となる。
配列全体への代入はpackedとunpacked共に`'{}`を使う。その時`defalut :`で基本の値を指定できる。要素番号 :で基本以外の値を設定できる。
packedは切れ目ない一続きのデータなので、代入に連接演算`{}`も使える。当然、1次元の大きなベクターへの直接代入やその逆も可能。又、data_8x4[1:2]の様にすべてのベクターではなくて一部のベクターを選択することも可能。

```verilog:Packed配列のVectorへの代入
logic     [ 7:0]  data0, data1, data2, data3;
logic[0:3][ 7:0]  data_8x4;
logic     [31:0]  data_4byte_all;
logic     [15:0]  data_2byte_lsb, data_2byte_msb;

assign data_8x4 = {data0, data1, data2, data3};
assign data_4byte_all = data_8x4;       // <-- data0, data21 data2, data3
assign data_2byte_lsb = data_8x4[0:1];  // <-- data0, data1
assign data_2byte_msb = data_8x4[2:3];  // <-- data2, data3
```
このようにpackedの方ができることが多く使い勝手が良いので、デザインではなるべくpackedの多次元配列を使うようにしよう。お馴染みSTARCの設計スタイルガイドでもunpackedでの使用を禁止している[（参照）](https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7#212-%E3%83%87%E3%83%BC%E3%82%BF%E3%82%BF%E3%82%A4%E3%83%97%E3%81%AE%E6%8B%A1%E5%BC%B5systemverilog-%E7%B7%A8)。
この多次元配列だが、思っている以上に有用で、役に立つ事が多い。例えばデータセレクトの様な事もこの多次元配列をうまく使うと簡潔に書ける。

```verilog:２次元ベクターによるデータセレクト
logic[3:0][ 7:0]  data_8x4;
logic     [ 1:0]  sel;
logic     [ 7:0]  data_out;

assign  data_out = data[sel];  
```
これを```logic[31:0]  data_all;```や```logic[7:0]  data0, data1, data2, data3;```の様な1次元ベクターでやろうとするとcase文ですべて羅列とベクターのビット選択を書かなくてはならないので結構大変で、当然記述ミスが多くなる。このような人間によるエラーはなるべく避けて、面倒な事は機械にやらせたい。

又、インデックスの割り当てを[3:0]の様な0から始まる右から左への昇順だけでなく[4:1]の様に1から始めたり、[0:3]の様に降順のインデックスを振る事もできる。

```verilog:Packed_1から4へのインデックス割り当て
logic     [7:0]  data1, data2, data3, data4;
logic[4:1][7:0]  data_8x4;  // <-- 8x4 array

assign  data_8x4 = {data4, data3, data2, data1};
// data_8x4[4] <- data4
// data_8x4[3] <- data3
// data_8x4[2] <- data2
// data_8x4[1] <- data1

```
```verilog:Packed_3から0へのインデックス割り当て
logic     [7:0]  data1, data2, data3, data4;
logic[0:3][7:0]  data_8x4;  // <-- 8x4 array

assign  data_8x4 = {data0, data1, data2, data3};
// data_8x4[0] <- data0
// data_8x4[1] <- data1
// data_8x4[2] <- data2
// data_8x4[3] <- data3
```
これをうまく使うとマッピングの変換等も簡潔に行う事もできる。

```verilog:Packed_マッピングの変換
logic     [7:0]  data0, data1, data2, data3;
logic[3:0][7:0]  data_3_0;  // <-- 8x4 array
logic[0:3][7:0]  data_0_3_reverse_index; //  <-- 8x4 array
logic[0:3][7:0]  data_0_3_reverse_order;  // <-- 8x4 array

assign  data_3_0 = {data3, data2, data1, data0};
// data_3_0[3] <- data3
// data_3_0[2] <- data2
// data_3_0[1] <- data1
// data_3_0[0] <- data0

assign data_0_3_reverse_index = data_3_0;
// Index number is reversed. Order is kept. 
// data_0_3_reverse_index -> {data3, data2, data1, data0}
// data_0_3_reverse_index[0] <- data3
// data_0_3_reverse_index[1] <- data2
// data_0_3_reverse_index[2] <- data1
// data_0_3_reverse_index[3] <- data0

always_comb  for(int i=0; i<4; i++) data_0_3_reverse_order[i] = data_3_0[i];
//  Index number is kept. Order is reversed.
// data_0_3_reverse_order -> {data0, data1, data2, data3}
// data_0_3_reverse_order[0] <- data0
// data_0_3_reverse_order[1] <- data1
// data_0_3_reverse_order[2] <- data2
// data_0_3_reverse_order[3] <- data3
```

この多次元配列はpackedでもunpackedでも当然moduleの入出力信号タイプにも使える。interfaceや[struct](#-struct)や[enum](#-enum)と合わせて使って行ってもらいたい。特にこの多次元配列はinterfaceや[struct](#-struct), [enum](#-enum)と違い別途何か用意する必要もなく、信号を配列で宣言するだけなので、より気軽にどんどん使って行けばよい思う。
又、上記では2次元配の例で説明したが、３次元以上の配列も同様に可能。

## ■ $clog2(), $bits()
`$clog2()`, `$bits()`はそれぞれ2の底のlogの整数への切り上げ値と変数のビット幅を返すシステムタスク。`$clog2()`はVerilog2005の時点で導入された。
`$clog2()`は数値の最大値から必要なビット数を求めたり、FIFO段数などメモリの深さから必要なアドレスのビット幅を求めたりするのに役立つ。[「$clog2によるビット幅算出のよくある間違い」](https://qiita.com/vega77/items/9eeffd4f08435d1a490f)も参考にされたし。
`$bits()`は信号名の他にタイプ名も引数にすることができる。なので[typedef](#-typedef)で定義したタイプのビット数算出にも使う事ができる。

```verilog:使用例
parameter  MAX_VAL = 10;
parameter  WIDTH = $clog2(MAX_VAL+1);  // Bit Width Calculation
typedef struct packed
  {
    logic[7:0]  data;
    logic[4:0]  addr;
    logic[4:0]  kind;
  }  my_st;

my_st  my_packet;

logic[     WIDTH-1:0]       val;
logic[$bits(val)-1:0]         a;  // Bit Width of Signal val
logic[$bits(my_packet)-1:0]   b;  // Bit Width of Struct Name my_packet
logic[$bits(my_st)    -1:0]   c;  // Bit Width of Defined Struct type my_st

assign a = val;
assign b = my_packet;
assign c = my_packet;
```
どちらもシステムタスクなので回路の合成自体に使用するのではなく、パラメータの値の計算や変数のビット幅の指定の様にコンパイル時に値が確定している所に使う。値が確定している所ならどこでも使えるので[キャスティング](#%E3%82%AD%E3%83%A3%E3%82%B9%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0)で信号のビット幅を変更する場合にも使える。

## ■ generate
generate文はVerilog 2001の段階で取り入れられた。VHDLにも同じくgenerateがある。これは基本的にはmodule等のインスタンス化の制御を行う時に使う。具体的にはfor文でparameterで指定した数だけmoduleをインスタンス化したり、if文／case文でmoduleをインスタンス化したり、しなかったりやインスタンス化するmoduleを変えたりを行う事が出来る。moduleの他assign, always, assert等にも使う事が出来る。

```verilog:generateの例
parameter  TYPE = 0;
parameter  NUM = 10;

logic [NUM-1:0][7:0]  in_data, out_data;
generate

if(TYPE == 0) begin : GEN_TYPE0
  for(genvar i; i<NUM; i++) begin : GEN_NUM
    block_a  i_block(.clk, .rst, .in_data(in_data[i]), .out_data(out_data[i]) );
    a_check_out_data : assert ( out_data[i] == $past(in_data[i]) );
  end
end

else if (TYPE == 1) begin : GEN_TYPE1
  assign out_data = in_data;
end

else if (TYPE == 2) begin : GEN_TYPE2
  always_ff@(posedge clk or negedge rst_n)
    if(!rst_n)  out_data <= '0;
    else        out_data <= in_data;
end

endgenerate
```

このように、通常if文、forループ文にラベル名を付ける。この例ではGEN_TYPE0/1/2, GEN_NUMとした。そうする事によりgenerateでインスタンス化されたmoduleのスコープ名が明示的にGEN_TYPE0.GEN_NUM[i].i_blockとなる。ラベル名を省略するとgenblk1.genblk1[i].<module name>となる事が言語仕様で決められている。generate内のラベルブロックの順番にgenblk<n>の様に1から順番に番号が振られる。generate内のforループの変数には通常のintではなくgenvarを用いる。System Verilogではforループのかっこ内でループ変数を定義する事が出来るようになった。なのでこの例ではそうしている。genvarをfor文のかっこの外に出して変数を定義しても構わない。
因みに実はgenerate, endgenerateただのお飾りで、省略する事もできる。しかし、分かりやすくするためになるべく書くようにしよう。他人の書いた記述でmodule内にいきなりif文やfor文があるのを見たらgenerateが省略されていると理解しよう。
generateを使うとこの様にパラメータによって回路構成を変えることができる。なのでRTLコードを使い回すことができ、回路のIPとしての価値がより高める事ができる。
尚、for文での複数インスタンス化以外、条件によるインスタンス化の制御はdefineやifdefを使用すればVerilogでも同様な事は可能である。

## ■ 数値のビット幅省略
System Verilogでは数値を表す時にビット幅を省略できるようになった。又、区切り記号"_"を使えるようになった。

```verilog:Verilogでの数値
logic[ 7:0] valA;
logic[31:0] valB;
logic[15:0] ValC;
always_comb begin
  valA =  7'd1000000;
  valB = 32'hAAAABBBB;
  valC = 16'b1010111100001010;
```

```verilog:SystemVerilogでの数値
logic[ 7:0] valA;
logic[31:0] valB;
logic[15:0] ValC;
always_comb begin
  valA = 'd1_000_000;
  valB = 'hAAAA_BBBB;
  valC = 'b1010_1111_0000_1010;
```
小技だが覚えておくと意外に便利な事もある。

## ■ 可変長リテラル
System Verilogでは可変長リテラルと言う物が導入された。これは一言でいうと信号のビット幅によらずall 1, all 0, all x, all zの代入を行う方法である。以下その記述。

```verilog:可変長リテラルでの代入
logic[ 7:0] all_0;
logic[ 8:0] all_1;
logic[ 9:0] all_x;
logic[10:0] all_z;

assign all_0 = '0;  //      8'b0000_0000
assign all_1 = '1;  //    9'b1_1111_1111
assign all_x = 'x;  //  10'bxx_xxxx_xxxx
assign all_z = 'z;  // 11'bzzz_zzzz_zzzz
```
デザインで使用するのは主にall 0かall 1であろう。特にall 0はFFのリセットの記述になんかに使うと便利である。この可変長リテラル地味だがとても便利で使う機会も非常に多いので是非覚えて積極的に使って行こう。何が便利かと言うと、0や最大値を代入する際に、信号のビット幅や、タイプを一切気にする必要が無いと言う事である。ここでもやはり0とか最大値と言う少し抽象度が高まった概念を使っているのである。

```verilog:FFリセット0
logic[WIDTH-1:0]  data;
always_ff@(posedge clk or negedge rst_n)
  if(!rst_n)  data <= '0;  // All 0 for any width of signal.
```
この例の様に信号のビット幅がパラメータで可変であってもなにも考えずに`'0`としておけば良いので大変便利である。
代入だけなく比較演算にも使用できる。

```verilog:比較での使用
logic[WIDTH-1:0]  data;
wire all_0 = (data == '0);
wire all_a = (data == '1);
```
これらを利用すると例えば最大値で止まるカウンターなんかが非常に簡潔に書ける。

```verilog:最大値で止まるカウンター
logic[WIDTH-1:0]  cnt;
always_ff@(posedge clk or negedge rst_n)
  if(!rst_n)          cnt <= '0;
  else if(clr)        cnt <= '0;
  else if(cnt != '1)  cnt <= cnt + 'b1;
```
又、[struct](#-struct)の初期化等の代入にも有効。

```verilog:structの初期化
typedef  struct packed {
  logic[      7:0]  data_A;
  logic[     15:0]  data_B;
  logic[     31:0]  data_C;
  logic[WIDTH-1:0]  data_D;
} my_struct_st;

my_struct_st  values;
always_ff@(posedge clk or negedge rst_n)
  if(!rst_n)     values <= '0;                           // Clear to all 0
  else if(init)  values <= '{default : '0, data_D = '1}; // Clear to all 0 except data_D
  .
  .
  .
```
この様に可変長リテラルはちょっとした事なのだが、非常に有用で、使用する頻度も高いと思う。

## ■ キャスティング（`'`）
キャスティングとは信号の種類を変換する事で、通常はタイプの変換の事を指す。Cや他の言語でもあるが、Verilogでは代入や比較演算の際の信号のタイプが一致していなくて良いのでタイプキャスト自体が不要であった。基本的にSystemVerilogでもそれは変わらないのだが、SystemVerilogではタイプキャストに加えてビット幅、符合のキャストができるようになった。キャスト演算子には`'`を用いる。

### ・タイプキャスト
上述のようにSystemVerilogでは通常タイプのキャスティングは使用する機会は殆ど無いが、[typedef](#-typedef) [enum](#-enum)で定義したタイプの信号に数値を直接代入する必要がある場合には使用される。[enum](#-enum)で宣言された信号は通常は列挙した文字しか代入できないが、タイプキャストにより数値を直接代入する事ができるようになる。

```verilog:enumへのタイプキャスティング
typedef enum logic[1:0]  {SLEEP, RUN, WAIT, READY}  mode_e;
mode_e      mode;
always_comb
  mode = mode_e'(2'b11);
//mode = 2'b11;  // NG
```
この様に`<type name>'()`で変換する。この例では2'b11と言う数値をmode_eと言うタイプに無理やり変換した。[enum](#-enum)で宣言された信号をlogicで宣言された信号に代入する場合にはタイプキャストは必要ない。

```verilog:タイプキャスティング不要
typedef enum logic[1:0]  {SLEEP, RUN, WAIT, READY}  mode_e;
mode_e      mode;
logic[1:0]  mode_val;
always_comb
  mode_val = mode    ; // OK
```
### ・ビット幅キャスト
ビット幅のキャスティングは代入や比較演算での左右の数値のビット幅をそろえたりするのに使える。

```verilog:数値のビット幅のキャスティング例
logic[7:0] a, b, c;

assign a = 8'(b + c);
```
この様に`<bit width>'()`でビット幅を変換する。この例の様に8ビットの足し算では本来オバーフローが１ビットあり、結果は9ビットだが、8ビットのままで良い場合がある。その場合8ビットの変数で結果を受ければ上の1ビットが捨てられるが、Lintチェッカによっては左右のビット幅が合っていないとErrorやWarningをレポートする場合がある。その場合ビット幅キャスティングで明示的にビット幅をそろえる事でError, Warningを回避できる。
ビット幅の指定にはパラメータや$bits()等のシステムタスクの結果など整数を指定できる。又、ビット幅を変換するのは演算結果だけでなく当然数値そのものでも良い。

```verilog:数値のビット幅キャスティング例２
parameter WIDTH = 16;
logic[WIDTH-1:0]  a;
logic[      7:0]  b, c;
always_comb begin
  a = '0
  case(case_sel_e)
    CASE1 : a = WIDTH'(100);
    CASE2 : a = $bits(a)'(200);
    CASE3 : a = $bits(a)'(b + c);
  endcase
end
```
### ・符合キャスト
符合のキャスティングには`singed'()`, `unsigned'()`を用いる。

```verilog:符合のキャスティング
logic signed [7:0]   s_valA, s_valB;
logic signed [8:0]   s_sum;
logic        [7:0]   u_valA, u_valB;
logic        [8:0]   u_sum;

assign s_sum =   signed'(u_valA) +   signed'(u_valB);
assign u_sum = unsigned'(s_valA) + unsigned'(s_valB);
```
の様に符合の変換を行う。符合ビット拡張している訳でなくビット幅は変わらずキャスティングにより数値の認識を変えているに過ぎないので注意。
尚、同様の事がシステムタスク`$singned()`, `$unsigned()`を使ってもできる。

```verilog:符合のキャスティング（システムタスク使用）
logic signed [7:0]   s_valA, s_valB;
logic signed [8:0]   s_sum;
logic        [7:0]   u_valA, u_valB;
logic        [8:0]   u_sum;

assign s_sum =   $signed(u_valA) +   $signed(u_valB);
assign u_sum = $unsigned(s_valA) + $unsigned(s_valB);
```

## ■ parameterのタイプ指定
確かVerilogではパラメーターのタイプの指定はできなくて32ビットinteger扱いで、System Verilogでパラメータのタイプを指定できるようになった様な気がする。間違っていたらすみません。省略すると32bit（おそらくint）になる。
タイプを指定できるので当然packed多次元配列や[struct](#-struct)や[enum](#-enum)も指定できる。Unpacked配列もparameter宣言できるが、その場合にはタイプの指定を省略せずきちんとする必要がある。

```verilog:parameterのタイプ指定
typedef  enum logic[1:0] {RED, GREEN, YELLOW, BLACK} color_e;
typedef  struct packed {logic[15:0] addr; logic[31:0] payload; logic[3:0] kind;}  packet_st

parameter  int              p_INT_0123[4] = '{  0,   1,   2,   3}; // int Unpacked Array
parameter  logic[3:0][3:0]  p_2D_ABCD     =  {'hA, 'hB, 'hC, 'hD}; // 2D Packed Array
parameter  color_e          p_MY_COLOR    =  RED;                  // enum
parameter  packet_st        p_ZERO_PKT    = '{default : '0};       // struct
```

## ■ localparam
localparamもVerilog2001で既に導入されていた。基本的にparameterと同じだが、違いはparameterが上位から書き換え可能なのに対しlocalparamはそのmodule内のみで参照が可能で上位から書き換えはできない。なのでむしろparameterは`#(parameter ...)`のみでの使用にしてmoduleおよびpackage内の定数にはparameterではなくlocalparamを使うべきなのかもしれない。

## ■ Variable Bit Part Select(`+:`, `-:`)
`+:`や`-:`を使ってベクター内の一部のビットを可変で選択する事が出来る。選択するビット幅は固定である必要がある。選択してくる位置が可変。これはVerilog2001の時点で既に導入された。以下も参照。

https://qiita.com/triggerfish/items/b63151cf6e3bdc17549e#%E3%83%99%E3%82%AF%E3%82%BF%E3%81%AE%E3%83%93%E3%83%83%E3%83%88%E9%81%B8%E6%8A%9E

例えば32ビットのビット列の中から8ビットを可変的に取り出す場合を考える。
以下ビットの位置に可変な値を指定した以下の記述はNGである。

```verilog:NGな記述
logic[31:0]  data_4B;
logic[ 7:0]   sel_1B;
logic[ 4:0]        i; // Variable, 0~24

assign  sel_1B = data_4B[(i+7):i];
```
これをやるにはcase文で全部のケースを場合分けして書く必要があった。

```verilog:OKな記述
always_comb
  case(i)
    0 : sel_1B = data_4B[ 7:0];
    1 : sel_1B = data_4B[ 8:1];
    2 : sel_1B = data_4B[ 9:2];
    3 : sel_1B = data_4B[10:3];
    .
    .
    .
  endcase
```
あるいはビットシフト`>>`でも記述できる。

```verilog:OKな記述（>>を使用）
assign sel_1B = data_4B >> i;
```

これをBit Part Selectでは以下のように記述する。

```verilog:Bit_Part_Selectでの記述
assign  sel_1B = data_4B[i +: 8];  // [(i+7):i], 8bit plus from bit position i(0~24) 
```
`[<Start Index> +: <Bit Width> ]`の様に指定する。Bit Widthは固定値である必要がある。数値でなくてもパラメータの様な固定値であればOK。`+:`は起点の位置からインデックスのプラス方向への選択であったが、`-:`はインデックスのマイナス方向への選択。

```verilog:Bit_Part_Selectでの記述（起点からマイナス方向）
assign  sel_1B = data_4B[i -: 8];  // [i:(i-7)], 8bit minus from bit position i(31~7) 
```

尚、[2次元Packed Array](#-多次元vectorarray)を使用しても類似な事は可能。

```verilog:Packed_Arrayを使用
logic[31:0]     data_4B;
logic[3:0][7:0] data_4B_array;
logic[ 7:0]     sel_1B;
logic[ 1:0]           i; // Variable, 0~3

assign  data_4B_array = data_4B;
assign  sel_1B = data_4B_array[i];
```
ただし、この場合Bit Part Selectと違い取り出してくる位置が8bitの単位に限られる。

又、Bit part Selectはベクター（１次元配列）のインデックスにだけでなく多次元配列のインデックスにも適用可能。
以下は4bit毎に0~7および7~0のインデックスで区切られた２次元配列から2インデックス分の8bitをselで選択する例。

```verilog:２次元配列のインデックスに適用
module top;

  localparam bit [0:7][3:0] data_0_7 = 'h01234567;
  localparam bit [7:0][3:0] data_7_0 = 'h76543210;

  bit[2:0]  sel;

  initial begin
    $display("data[0:7], [%h] ( (sel) --> + )", data_0_7); for (sel=0; sel<8; sel++) $display("  [%d +: 2] = [%h]", sel, data_0_7[sel+:2]);
    $display("data[0:7], [%h] ( - <-- (sel) )", data_0_7); for (sel=0; sel<8; sel++) $display("  [%d -: 2] = [%h]", sel, data_0_7[sel-:2]);
    $display("data[7:0], [%h] ( + <-- (sel) )", data_7_0); for (sel=0; sel<8; sel++) $display("  [%d +: 2] = [%h]", sel, data_7_0[sel+:2]);
    $display("data[7:0], [%h] ( (sel) --> - )", data_7_0); for (sel=0; sel<8; sel++) $display("  [%d -: 2] = [%h]", sel, data_7_0[sel-:2]);
  end

endmodule
```
```text:Log
data[0:7], [01234567] ( (sel) --> + )
  [0 +: 2] = [01]
  [1 +: 2] = [12]
  [2 +: 2] = [23]
  [3 +: 2] = [34]
  [4 +: 2] = [45]
  [5 +: 2] = [56]
  [6 +: 2] = [67]
  [7 +: 2] = [7x]
data[0:7], [01234567] ( - <-- (sel))
  [0 -: 2] = [x0]
  [1 -: 2] = [01]
  [2 -: 2] = [12]
  [3 -: 2] = [23]
  [4 -: 2] = [34]
  [5 -: 2] = [45]
  [6 -: 2] = [56]
  [7 -: 2] = [67]
data[7:0], [76543210] ( + <-- (sel))
  [0 +: 2] = [10]
  [1 +: 2] = [21]
  [2 +: 2] = [32]
  [3 +: 2] = [43]
  [4 +: 2] = [54]
  [5 +: 2] = [65]
  [6 +: 2] = [76]
  [7 +: 2] = [x7]
data[7:0], [76543210] ( (sel) --> - )
  [0 -: 2] = [0x]
  [1 -: 2] = [10]
  [2 -: 2] = [21]
  [3 -: 2] = [32]
  [4 -: 2] = [43]
  [5 -: 2] = [54]
  [6 -: 2] = [65]
  [7 -: 2] = [76]
```
インデックスが左から右に大きくなっている[0:7]では[sel+:2]で[sel:sel+1]が選ばれ[sel-:2]では[sel-1:sel]が選ばれる。逆にインデックスが右から左に大きくなっている[7:0]では[sel+:2]で[sel+1:sel]が選ばれ[sel-:2]では[sel:sel-1]が選ばれる。この様に同じBit Part Selectの表記でもインデックスの数字の増減の方向が逆だと指定される箇所が異なるので注意。+/-はインデックスの数字の増減に対する方向の意味であって、コードのテキスト記述上の左右の方向に対しての意味ではない。１次元ベクターのBit Part Selectでも同じである。

## ■ Bit Stream Operator（`<<`）
ベクターのビット順を入れ替え反転されるにビットストリームオペレータ`<<`が使える。1ビット単位の入れ替えだけでなく任意の単位での入れ替えを指定できる。`<<`自体はビット列を右から順に読み出すという意味。右から順に読み出して（左から順に）置くのでビットの入れ替えができる。
以下を参考。

https://qiita.com/triggerfish/items/b63151cf6e3bdc17549e#streaming-operator

これを使えばエンディアン変換等も簡潔に記述できる。ただし、やはり[2次元Packed Array](#%E5%A4%9A%E6%AC%A1%E5%85%83vectorarray)を使っても同様な事は可能。
2次元Packed Arrayで順序を入れ替える場合はforループを回していたが、`<<`を使えばfor文を書かなくて済む。`<<`自体がfor文と同等の事をしているからである。

```verilog:２次元Packed_Arrayのマッピングの変換（Bit_Strem_Operator使用）
  logic[31:0]      data_4B;

  wire[3:0][7:0]  data_4B_array = data_4B; // <-- 8x4 array
//logic[0:3][7:0]  data_4B_array_reverse;  // <-- 8x4 array
//always_comb  for(int i=0; i<4; i++) data_4B_array_reverse[i] = data_4B_array[i];
// Order are reversed.
// data_4B_array_reverse[0] <- data_array[0] <- data_4B[ 7: 0]
// data_4B_array_reverse[1] <- data_array[1] <- data_4B[15: 8]
// data_4B_array_reverse[2] <- data_array[2] <- data_4B[23:16]
// data_4B_array_reverse[3] <- data_array[3] <- data_4B[31:24]
  wire[0:3][7:0]  data_4B_array_reverse = { <<8 {data_4B_array} };

//wire[31:0]  data_4B_reverse = {data_4B[ 7: 0], data_4B[15: 8], data_4B[23:16],data_4B[31:24]};
//wire[31:0]  data_4B_reverse = data_4B_array_reverse;
  wire[31:0]  data_4B_reverse = { <<8 {data_4B} };
```

## ■ 比較演算でのワイルドカード（`==?`, `!=?`）
SystemVerilogでは値の等号／不等号比較演算でビットの一部をマスクして、比較対象から外したい場合に、ワイルドカードが使えるようになった。

```verilog:比較演算のワイルドカード
logic[15:0] val;
always_comb
  if      (val ==? 'hF??F) ...
  else if (val ==? 'hEXXE) ...
  else if (val !=? 'hDxxD) ...
  else if (val ==? 'hCZZC) ...
  else if (val !=? 'hBzzB) ...
  else if (val ==? 'b0000_????_0000_????) ...
  else if (val ==? 'b1111_XXXX_ZZZZ_1111) ...
  else if (val !=? 'b1111_xxxx_zzzz_0000) ...
  else ...
```
比較対象から外すビットの位置に一文字のワイルドカード記号`の?`或いは `X`, `x`, `Z`, `z`にする。
Verilogではワイルドカード比較は`casex`, `casez`でのみ行えたが、SystemVerilogでは`==?`, `!=?`を使ってどこでも行える。ただし、`==?`, `!=?`でのワイルドカード比較は`casex`, `casez`でのワイルドカード比較と異なり、左辺の変数に含まれる`x`や`z`はワイルドカードではく評価される値である。なので例えば以下のように比較対象のビットに`x`が含まれると比較結果は`x`となる。

```verilog:
   logic[3:0] val;
   // val =   4'b0xxx   ==> True
   // val =   4'bx111   ==> x (False)
   // val =   4'bz111   ==> x (False)
   if(val ==? 4'b0???)
```

`casex`では比較対象側のビットに`x`が含まれてもワイルドカードとされ、比較判定されない。`casez`では`x`だと比較判定されるが、`z`の場合のみワイルドカード扱いになり、比較判定されない。

```verilog:
   logic[3:0] val;
   casex (val)
         4'b0??? : ...
// val = 4'b0xxx   ==> True
// val = 4'bx111   ==> True
// val = 4'bz111   ==> True

   casez (val)
         4'b0??? : ...
// val = 4'b0xxx   ==> True 
// val = 4'bx111   ==> False
// val = 4'bz111   ==> True
```

比較演算の違いについては以下も参照。

https://qiita.com/vega77/items/cc329be60cb34f2d931a


## ■ inside
insideはある信号の値がとある範囲や、値の集合の中にマッチる値があるかを判定する演算子。SystemVerilogのランダム検証のランダム制約の部分でよく見るかと思うが検証専用と言う訳ではなく、実はデザインでも使える。以下の様に使用する。

```verilog:inside使用例
logic[7:0]  val;
logic       flag;
always_comb
  if(val inside {[0:100],254,255}) flag = 'b1;
  else                             flag = 'b0;
```
この例ではvalが0~100か254か255の値に入っているかを判定している。ひとつひとつ比較演算で書く事もできるが、範囲が複雑になってきたり集合の数が多くなると大変。
insideでは==?での等号比較演算なので、比較する値にワイルドカードも使える。

```verilog:insideでワイルドカード使用例
logic[7:0]  val;
logic       flag;
always_comb
  if(val inside {8'b00??_????,[64:100], 8'b1111_111?}) flag = 'b1;
  else                                                 flag = 'b0;
```
{8'b00??_????}は{[0:63]}と、{8'1111_111?}は{254,255}と同じである。

このinsideはcase文でも使える。

```verilog:insideのcase文での使用
logic[7:0]  val;
logic       flag;
always_comb
  case(val) inside
    [0:100],254,255 : flag = 'b1;
    default         : flag = 'b0;
  endcase  
```
なので当然case文でワイルドカードが使える。

```verilog:case文でのワイルドカードの使用
logic[7:0]  val;
logic       flag;
always_comb
  case(val) inside
    8'b00??_????, [0:100],8'b1111_111? : flag = 'b1;
    default                            : flag = 'b0;
  endcase  
```
case文でのワイルドカードはVerilogではcasex,casezでできた。

```verilog:Verilogでのワイルドカード
reg[3:0] code;
reg[1:0] out;
always@*
  casex (code)
    4'b1??? : out = 2'd3;  // <---- 1xxx or xxxx
    4'b01?? : out = 2'd2;
    4'b001? : out = 2'd1;
    4'b0001 : out = 2'd0;
    default : out = 2'bxx;
  endcase
```
しかしこのcasexおよびcasezでのワイルドカードによるビットマスク比較には問題がある。ビット比較のマスクが両方に適用されるので、入力信号のビットにx或いはzが含まれるとそのビットの比較演算がマスクされてしまうのである。なので上記の記述では例えばcode = 4'bx000の場合、最初の条件がTrueとなりout=2'd3;が実行されてしまう。しかし合成後のGate Simではそうならず、RTL SimとGate Simで結果が異なってしまう。
一方case insideでのワイルドカードによるビット比較のマスクではRTL SimとGate Simで動きが一致する。なぜならcase insdeでは==?での比較で、ワイルドカードによるビットマスクは==?の右側にのみ適用だからで、入力信号のビットにxが入ったとしてもそのビットの比較はマスクされないからである。

```verilog:case()insideでxの一致
logic[3:0] code;
logic[1:0] out;
always_comb
  case (code) inside
    4'b1??? : out = 2'd3;  // <---- Only 1xxx
    4'b01?? : out = 2'd2;
    4'b001? : out = 2'd1;
    4'b0001 : out = 2'd0;
    default : out = 2'bxx; // <---- xxxx
  endcase
```
なのでワイルドカードのcaseはcasex,casezは使わずこれからはcase() insdeを使うようにしよう。

insideに関しては以下Qiita記事も参考に。

https://qiita.com/taichi-ishitani/items/d5bb34273fce8d4b0385

## ■ Assertion
アサーションはSystemVerilogの検証向けの強化項目として導入された。「な～んだ検証向けならRTL設計しかしないし関係ないや。」とか思ってしまったそこのあなた。給料の半分を会社に返納してください。確かにアサーション自体は検証向けの記述なのだが、むしろRTL設計者が積極的に取り組むべきものである。その辺に関しては参考資料で紹介している[Who Put Assertions In My RTL Code? And Why?](http://www.sutherland-hdl.com/papers/2015-SNUG-SV_SVA-for-RTL-Designers_presentation.pdf)とか是非見てもらいたい。設計者がアサーションを記述する意味がないとか言う人を時々見受けるが、そのような人は以下の事を理解できていない。設計者がアサーションを記述する利点は以下である。

- 設計者の意図を記述
- 曖昧さなく仕様を記述
- 設計ブロックへの入力の前提条件を記述
- 異常動作の検出の局所化と早期発見

アサーションはこれまでこのページで紹介してきたSystemVerilogの記述の中でも最も開発効率の向上が期待できるのではないかと思う。それぐらい重要なのである。

アサーション自体は元々ソフトウェア開発で用いられてきのだが、それをHDLでのハードウェア開発にも取り入れたのである。SystemVerilogではSVA（SystemVerilog Assertion）と呼ばれたりする。因みにVHDLでは別のアサーション言語であるPSLを統合している。余談だがアサーションに限らず大概のHDLでのハードウェア開発手法はソフトウェア開発からの転用である。

アサーションは期待する信号の挙動を言語で表現し、シミュレーション中に期待動作と違った動きが観測されたらエラーメッセージが表示される。要するに局所領域での期待動作モデルと考える事ができる。RTL自体文字通りRegister Transfer Levelでの動作モデリングなので、アサーションではそれより高い抽象度レベルでの表現でないとあまり意味がない。なので別の言い方をするとアサーションは回路の動作仕様を記述言語で表現した物なのである。アサーションとは何なのかを良く分かっていない人は[「アサーション活用の手引き」](https://ednjapan.com/edn/articles/0909/01/news150.html)等の記事を参考にすると良いだろう。
アサーション記述自体の情報は割と世の中に溢れているので、ここでは主にデザインへの適用方法に関してのみ紹介する。以下の様な単純な回路の具体的な例で見て行く。

`仕様：入力信号in_aの1クロック後に出力信号out_bにin_aの値が出力される。`
RTL記述は以下のようになるだろう。

```verilog:RTL記述
module block (  input logic  clk, rst_n, in_a, output logic  out_b);

  always_ff@(posedge clk or negedge rst_n)
    if(!rst_n)  out_b <= 'b0;
    else        out_b <= in_a;

endmodule
```
これにいくつかアサーションを追加してみる。

```verilog:アサーション追加
module block (  input logic  clk, rst_n, in_a, output logic  out_b);

  always_ff@(posedge clk or negedge rst_n) begin
    `ifndef ASSERTION_OFF
    //------------------ Immediate Assertions ----------------------------
    asm_rst_n_x : assume ( !$isunknown(rst_n) ) else $error("rst_n is X!");
    asm_in_a_x  : assume ( !$isunknown( in_a) ) else $error("in_a is X!" );
    //--------------------------------------------------------------------
    `endif
    if(!rst_n)  out_b <= 'b0;
    else        out_b <= out_a;
  end

  `ifndef ASSERTION_OFF
  //-----------------------------Concurrent Assertions ----------------------------------
  asm_a_pulse : assume property ( @(posedge clk) !in_a ##1 $rose(in_a) |=> $fell(in_a) )
                else $error("in_a is not a single pulse!");

  ast_a_to_b  : assert property ( @(posedge clk)  1 |-> ##1 (out_b == $past(in_a)) )
                else $error("out_b is not equal to in_a!");

  ast_b_pulse : assert property ( @(posedge clk) !out_b ##1 $rose(out_b) |=> $fell(out_b) )
                else $error("out_b is not a single pulse!");
  //------------------------------------------------------------------------------------
  `endif
endmodule
```
と、この様にRTL記述のmoduleの中に直接アサーションを書くことができる。always_ffの中にimmediateアサーションを書き、moduleの直下にはconcurrentアサーションを書いた。assertの他にassumeを使っているがシミュレーション上は特に違いは無い。フォーマル検証と言う物をやる場合にはassumeは制約として扱われる。ここでは入力信号に対する仮定をしていると言う事を示す為に使い分けてみた。RTLファイルに直接アサーション書いてしまってちゃんと合成できるのか？と思うかもしれないが、合成ツールはきちんとassert,assumeの記述を無視して回路合成してくれる。合成ツールやLintツールが対応していない場合にはこの例の様に\`ifdefや\`ifndefを使ってアサーションの部分を記述から除くように制御できるようにしておくと良いだろう。合成ツールでのみ暗黙的に定義される\`define SYNTHESISを使って\`ifndef SYNTHESIS, \`endifで囲む手もある。因みに`ifndefはVerilog-2001で導入された。
ここではasm_a_pulseのように入力信号の仮定をアサーションで記述した。実はこれはかなり重要である。このモジュールでは実は入力信号in_aを1パルスで来ることを想定していたのである。初めの仕様ではそのような事は一言も言及されていない。バグと言うのは大体このような仕様の曖昧さや担当者間の解釈や認識の相違で起こる。アサーションはコンピュータ言語なので自然言語と違い仕様や設計者の意図を曖昧さなく表現するのである。こんな簡単な回路でさえこんな所にバグが入り込む隙があるのである。アサーションはそれに対抗する強力な手段だと言う事がよく分かると思う。
ast_b_pulseの方はどうだろうか。これは出力信号out_bがやはりパルスだというアサーションである。これも初めの仕様には言及されていない。やはり設計者はout_bもパルスで出す事を意図していたのである。
ast_a_to_bはどうだろうか。これらはin_aの値が1クロック後にout_bに出ると言う仕様を表したアサーションだがこれくらい簡単な回路では殆ど意味がない。しかし、これが１クロック後ではなくて何クロックか後と言う仕様だったらどうだろうか。回路はカウンターやステートマシーンが入ってもう少し複雑になる筈である。それに対してアサーションはin_aの値が何クロック後かにout_bに出ると言う仕様の動作レベルで表現するので入れる価値が十分出てくる。
アサーションとはこの様に、設計者の想定や設計意図、仕様を整理し曖昧さなく表現し、設計情報であるRTL記述自体の中に組み込んだ物だと言う事が分かったと思う。[「アサーション活用の手引き」のメリット・デメリット](https://ednjapan.com/edn/articles/0909/01/news150_2.html)でも以下の様に述べられている。
> アサーションの記述は、仕様をブレークダウンする作業である。アサーション言語はコンピュータ言語なので、あいまいな記述は許されない。アサーションを記述/検討する工程において、仕様に対する深い理解、あいまいな点の把握、問題の指摘が行える

アサーションをRTLファイルに組入れる際に便利な方法をもう少し紹介しておこうと思う。Concurrent Assertionsの各propertyでは@(posedge clk)を使ってアサーション評価の基準のクロックを指定していた。実はこれは一回default clockingで宣言すれば以降省略が可能となる。propertyの数が多くなってくると便利だと思う。propertyの抽象度が少し高くできたとも見る事ができる。

```verilog:clockingの使用
  default clocking def_clk @(posedge clk); endclocking

  asm_a_pulse : assume property ( !in_a ##1 $rose(in_a) |=> $fell(in_a) )
                else $error("in_a is not a single pulse!");

  ast_a_to_b  : assert property ( 1 |-> ##1 (out_b == $past(in_a)) )
                else $error("out_b is not equal to in_a!");

  ast_b_pulse : assert property ( !out_b ##1 $rose(out_b) |=> $fell(in_b) )
                else $error("out_b is not a single pulse!");
```
尚、このdefault clockingは某ASICでの市場独占合成ツールでは問題なく受け付けるが、同じ会社の某有名Lintチェックツールでは対応していなかった。別の会社のLintツールは対応してたのに。ツールが対応していない場合は諦めて@(posedge clk)を使うか、先述の通り\`ifndef/`ifdefで、Lintチェックの時にアサーション記述を除くようにしよう。
因みに某会社にLintツールでも対応するよう改善要望をしたが却下となってしまった。ユーザーの要望が多くなれば対応すると思うのでこれに限らずツールベンダーへのユーザー要望はどんどん出してもらいたい。
asm_a_pulseとast_b_pulseは両方同じパルスである事をチェックするアサーションである。なのでそのpropertyは同じである。このように同じpropertyを何度も書くのは手間なのでまとめて一回書くだけにしたい。その場合にはpropertyを別宣言してまとめる事ができる。さらにast_a_to_bのpropertyも含めて他のmoduleでも使えるようにしたい。module間で共有したいと言えばそう、既に紹介した[package](#-package)に入れて使う事ができるのである。

```verilog:propertyのpackage化
package prop_pkg;

  property p_pulse(sig);
    !sig ##1 $rose(sig) |=> $fell(sig)
  endproperty

  property prop_1clk(siga, sigb);
    1 |-> ##1 (sigb == $past(siga))
  endproperty
  
endpackage
```

```verilog:propertyの使用
  import prop_pkg::*;
  default clocking def_clk @(posedge clk); endclocking

  asm_a_pulse : assume prop_pulse(in_a)        else $error("in_a is not a single pulse!");
  ast_a_to_b  : assert prop_1clk (in_a, out_b) else $error("out_b is not equal to in_a!");
  ast_b_pulse : assert prop_pulse(out_b)       else $error("out_b is not a single pulse!");
```
この様に良く使うpropertyは[package](#-package)に入れてライブラリ化しておくと何度も使い回しができて便利である。
propertyは基準クロックを含めて書く事もできる。

```verilog:propertyのpackage化（clk含む）
package prop_pkg;

  property p_pulse(clk, sig);
    @(posedge clk)  !sig ##1 $rose(sig) |=> $fell(sig)
  endproperty

  property prop_1clk(clk, siga, sigb);
    @(posedge clk)  1 |-> ##1 (sigb == $past(siga))
  endproperty
  
endpackage
```

```verilog:propertyの使用（clkをpropertyに含む）
  import prop_pkg::*;

  asm_a_pulse : assume prop_pulse(clk, in_a)        else $error("in_a is not a single pulse!");
  ast_a_to_b  : assert prop_1clk (clk, in_a, out_b) else $error("out_b is not equal to in_a!");
  ast_b_pulse : assert prop_pulse(clk, in_b)        else $error("in_b is not a single pulse!");
```
この場合はdefault clockは書かずにassert/assumeでproperty()にclk信号を渡す。
アサーションの効果的な適用箇所としてすでに紹介した[interface](#-interface)がある。アサーションはmoduleに限らず[interface](#-interface)内にもを書く事ができるのである。使用方法もmoduleでの使用と同じである。

```verilog:interfaceでのアサーション使用例
interface #(parameter width=32) bus_if(input logic clk, rst_n);
  logic[ 7:0]      addr;
  logic            wr_rq  , rd_rq  , rd_en;
  logic[width-1:0] wr_data, rd_data;
  modport mst_port(                  output addr, wr_rq, wr_data, rd_rq, input  rd_en, rd_data);
  modport slv_port(input clk, rst_n, input  addr, wr_rq, wr_data, rd_rq, output rd_en, rd_data);

  //---------------- Assertions --------------------------//
  ast_wr_rq_pulse : assert prop_pkg::prop_pulse(clk, wr_rq);
  ast_rd_rq_pulse : assert prop_pkg::prop_pulse(clk, rd_rq);
  ast_rd_en_pulse : assert prop_pkg::prop_pulse(clk, rd_en);
  //------------------------------------------------------//

endinterface
```
いろんな所で使う汎用バスの様な物は信号とそのプロトコルが決まっているので、入出力信号定義とそのアサーションチェックをinterfaceに入れておいてどこでも使い回しができるようにしておくと非常に効果的である。

## ■ 最後に
以上、デザイン向けのSystemVerilogの記述を紹介してきた。最初にも書いたが、開発効率が段違いに向上するので是非取り入れて行ってもらいたい。これらの記述を全て一気に覚える必要もないし、いっぺんに適用する必要もないので少しづつ使ってみてもらいたい。又、ここで紹介した記述方法を単体で使うのではなく是非複数組み合わせてより高い効果発揮させてほしい。
最後に以下に[参考資料２](http://www.sutherland-hdl.com/papers/2014-DVCon_ASIC-FPGA_SV_Synthesis_paper.pdf)のSutherland HDLのプレゼン資料に載っているいろいろな合成ツールのSystemVerilog対応状況の表を引用する。2014年時点の情報なので少し古いが、各合成ツールがどれくらいサポートしているか分かると思う。
![Synthesis_Support.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471497/f171d0df-2c05-a809-af2d-bf50473a2ead.png)
若干ツールによってはサポートしていない物もあるが、その当時でもほぼ対応している。これから数年経った現在ではさらにサポート状況が改善されていると思われる。

---
## ■ 参考資料・サイト
<DL>

  <DT>
  1. SystemVerilog from Zero to One <A HREF= "http://www.artgraphics.co.jp/PublicDownloads/Lecture/JEVecDay_SystemVerilog_Tutorial.pdf">(フル版)</A> <A HREF = "http://www.artgraphics.co.jp/PublicDownloads/Lecture/JEVecDay_SystemVerilog_Tutorial_Digest.pdf">(ダイジェスト版)</A> by <A HREF = "http://www.artgraphics.co.jp">アートグラフィックス</A>
  </DT>
  <DD>
  検証向け含めたSystemVerilogの記述について細かいところまでかなり網羅的に載っている。量が多いが良くまとまっていて読みやすい。既にSystemVerilogをよく知っている人でも知らない事とか載っていると思うので一読をお勧めする。
  </DD>
  <BR>

  <DT>
  2. Can My Synthesis Compiler Do That? <A HREF = "http://www.sutherland-hdl.com/papers/2014-DVClub-Austin_SV_Synthesis_presentation.pdf">(Slides)</A> <A HREF = "http://www.sutherland-hdl.com/papers/2014-DVCon_ASIC-FPGA_SV_Synthesis_paper.pdf">(Paper)</A> by <A HREF = "http://www.sutherland-hdl.com">Sutherland HDL</A>
  </DT>
  <DD>デザイン向けの合成可能なSystemVerilog記述をまとめたプレゼン資料。ほぼこのページの元ネタ。
  </DD>
  <BR>

  <DT>
  3. Who Put Assertions In My RTL Code? And Why? <A HREF = "http://www.sutherland-hdl.com/papers/2015-SNUG-SV_SVA-for-RTL-Designers_presentation.pdf">(Slides)</A> <A HREF = "http://www.sutherland-hdl.com/papers/2015-SNUG-SV_SVA-for-RTL-Designers_paper.pdf">(Paper)</A> by <A HREF = "http://www.sutherland-hdl.com">Sutherland HDL</A>
  </DT>
  <DD>設計者向けのアサーションに関するプレゼン資料。これを見ると何故設計者がアサーションを使うべきか理解できると思う。</DD>
  <BR>

  <DT>
  4. <A HREF = "https://www.paltek.co.jp/techblog/techinfo/220711-01">検証を楽にするSystemVerilogコーディング術</A>
  </DT>
  <DD>PALTEKの技術ブログ記事。検証を楽にするとなっているが内容はデザイン向けのSystemVerilogの記事。本ページの最初の方のいくつかの項目を簡潔に紹介している。本ページにインスパイアされて書いたんじゃないかと疑っている。</DD>

</DL>