VivadoのSystemVerilog対応状況(合成編)

(3089d) 更新


公開メモ

Xilinx の最新開発環境 Vivado における System Verilog 対応状況を調べてみました

System Verilog を学ぶにあたって、とりあえず使える範囲から学ばないと無駄になりそうなので、 という意味合いで、対応状況を確認してみました。

電気回路/HDL/VivadoのSystemVerilog対応状況(シミュレーション編) もあります。

参考資料

"Vivado Design Suite User Guide - Synthesis" UG901 (v2015.3) September 30, 2015 の "Chapter 7: SystemVerilog Support" を参考にしています。

http://www.xilinx.com/support/documentation/sw_manuals/xilinx2015_3/ug901-vivado-synthesis.pdf

かなり頻繁に更新されているようなので、常に最新の情報を追う必要がありそうです。

  • 2015/04/01 2015.1
  • 2015/06/24 2015.2
  • 2015/09/30 2015.3

同資料の、Chapter 3: HDL Coding Techniques も、非常に有用な内容が含まれているようですね。 別途熟読してみたいと思います。

Data Type

  • integer_vector_type: bit, logic, or reg
  • integer_atom_type: byte, shortint, int, longint, integer, or time
  • non_integer_type: shortreal, real, or realtime
  • struct
  • enum

変数宣言の際の var は省略可能。

Integer Data Types

01 / 01XZtypebitsdefault
2-stateshortint16-bitsigned
int32-bitsigned
longint64-bitsigned
byte8-bitsigned
bituser defined vector sizeunsigned
4-statelogicuser defined vector sizeunsigned
reguser-defined vector sizeunsigned
integer32-bitsigned
time64-bitunsigned

むむぅ。int と integer は違うのか・・・

Real Numbers

  • real
  • shortreal
  • realtime

パラメータとして与えることはできても、計算する回路を生成することはできない。

Void Data Type

値を返さない function を定義する際にだけ使える。

User-Defined Types

typedef により定義可能。

typedef data_type type_identifier {size};
typedef [enum, struct, union] type_identifier;

Enum Types

enum [type] {enum_name1, enum_name2,...enum_namex} identifier

type のデフォルトは int なので、それ以外にしたい場合に指定する。

数字の割り当ては enum_name1 = 0 であり、それ以降1ずつ増える。

Cと同様に enum_name2=3 などとして数値を指定することも可能。

enum {day[7]} day_of_week;  // これは次の行と同じ意味
enum {day0, day1, day2, day3, day4, day5, day6} day_of_week;

enum {day[1:7]} day_of_week; // creates day1,day2...day7
enum {day[7] = 5} day_of_week; //creates day0=5, day1=6... day6=11

Constants

  • parameter
  • localparam
  • specparam : Synthesis では無視される
  • const

パラメータには type やビット幅、符号のありなしを指定できる。

Casting

System Verilog では異なる type 間での代入はエラーになるので明示的にキャストしなければならない

casting_type'(expression)

Aggregate Data Types - structure

struct {struct_member1; struct_member2;...struct_memberx;} structure_name;

Aggregate Data Types - union

typedef union {int i; logic [7:0] j} my_union;
my_union sig1;
my_union sig2;
sig1.i = 32; //sig1 gets the int format
sig2.j = 8’b00001111; //sig2 get the 8bit logic format

レジスタのビットをばらばらにするのに使ったりする。

Aggregate Data Types - Packed and Unpacked Arrays

logic [5:0] sig1; //packed array
logic sig2 [5:0]; //unpacked array

integer sig3; //equivalent to logic signed [31:0] sig3

Processes

Always Procedures

  • always
  • always_comb
  • always_latch
  • always_ff
always_comb out1 = in1 & in2;
//  always @(in1 or in2)
//    out1 = in1 & in2;

always_latch
  if(gate_en) q <= d;

always_ff@(posedge clk)
  out1 <= in1;

Block Statements

begin : my_block
  logic temp;
  temp = in1 & in2;
  out1 = temp;
end : my_block

end の後のブロック名は省略可能

Parallel blocks (あるいは fork join blocks) は Vivado synthesis ではサポート外。

Procedural Timing Controls

Delay Control は Synthesis では無視される

Event Control は always に与える形で使う。

always@(posedge clk)
always@(a or b or c)
always@(a,b,c)
always@*

Operators

代入演算子
=, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, <<<=, >>>=
単項演算子
+, -, !, ~, &, ~&, |, ~|, ^, ~^, ^
増減演算子
++, --
二項演算子
+, -, *, /, %, ==, ~=, ===, ~==, &&, ||, **, < , <=, >, >=, &, |, ^, ^~, ~^, >>, <<, >>>, <<<
三項演算子
? :
連接演算子
{ }
  • 単項演算子の &, ~&, |, ~|, ^, ~^, ^~ はCには無いので注目に値する
  • 二項演算子の ===, ~==, **, ^~, ~^, >>>, <<< も特殊
  • A**B は A が 2 の累乗であるか、B が定数であるときに限り有効である
  • 引数の type によって符号付き・符号なし演算が適切に行われる

Procedural Programming Assignments

Conditional if-else Statement

If (expression1)
  command1;
else if (expression2)
  command2;
else if (expression3)
  command3;
else
  command4;

Case Statement

case (expression)
  value1: statement1;
  value2: statement2;
  value3: statement3;
  default: statement4;
endcase

条件検査は順に行われる。
つまり、value1 と value3 が両方 true でも statement1 のみが実行される。

if-else と case には parallel_case / full_case の属性を指定可能っぽい

Loop Statements

for / repeat / for-each / while / do-while / forever が使える。

Verilog で for-each って見たこと無いかも。

Tasks and Functions

Task

task [automatic/static] name (ports);
  [optional declarations];
  statements;
endtask

static task というのは前回呼ばれた値を参照可能な task で、
automatic task というのは毎回値が初期化される task、
ということで合っている?

Vivado の synthesis ではすべての task は automatic として扱われる。

他の多くの simulator では static task がデフォルトなので気をつけること。

というか、常に "task automatic" と宣言しておくことにした方がよさそう。
#エラーにはならないんだよね?→ 要チェック

Functions (Automatic and Static)

function [automatic/static] data_type function_name(inputs);
  declarations;
  statements;
endfunction [: function_name]

最後の function_name はオプション。enttask の後ろに task_name は書けないのかしら?

function_name = .... の形か、return で返り値を指定する。

Vivado の synthesis ではすべての function は automatic として扱われる。

simulator によっては static function がデフォルトなので気をつけること。

Modules and Hierarchy

Connecting Modules

宣言時と同じ名前の信号線を繋ぐ際には記述を省略できる。

module lower (
  output [4:0] myout;
  input clk;
  input my_in;
  input [1:0] my_in2;
  ... ...
endmodule

// in the instantiating level.
lower my_inst1 (.myout, .clk, .my_in, .my_in2);
// works as same as below
lower my_inst2 (.myout(myout), .clk(clk), .my_in(my_in), .my_in2(my_in2));

Connecting Modules with Wildcard Ports

名前すら省略できる。

// in the instantiating module
lower my_inst3 (.*);

lower my_inst4 (.myout(my_sig), .my_in(din), .*);

Interfaces

// interface の宣言
interface my_int
  logic sel;
  logic [9:0] data1, data2, result;
endinterface : my_int

// 下位モジュール1
//    my_int.result を利用する
module bottom1 (
  my_int int1,
  input clk,
  input [9:0] d1, d2,
  input s1,
  output logic equal
);
  ...

endmodule

// 下位モジュール2
//    my_int.result を設定する
module bottom2 (
  my_int int1,
  input clk
);
  
  ...
  if (int1.sel)
    int1.result <= int1.data1;
  ...

endmodule

// 上位モジュール
module top(
  input clk,
  input s1,
  input [9:0] d1, d2,
  output equal
);
  my_int int3(); // instantiation
  bottom1 u0 (int3, clk, d1, d2, s1, equal);
  bottom2 u1 (int3, clk);
endmodule

Modeports

普通に使うと interface に含まれる信号線はすべて inout になってしまうため、 方向を持たせたければ、

interface my_int;
  logic sel;
  logic [9:0] data1, data2, result;
  modport b1 (input result, output sel, data1, data2);
  modport b2 (input sel, data1, data2, output result);
endinterface : my_int

module bottom1 (
  my_int.b1 int1,

のようにすれば良い。

あんまり分かりやすくはない気がするけれど、 名前を上手に付ければいいのかもしれない。

上記の例だと、set_result と use_result とか???

良い規約が欲しくなる。

Miscellaneous Interface Features

interface に task, function を持たせることができる

interface に parameter を持たせることができる

Packages

package package_name;
  items
endpackage : package_name

使うときは、

import package_name::item or *;

System Verilog に固有なものとして重要そうなのは

くらいでしょうか。

メモ

interface のいけない使い方

各モジュールにデバッグ用の interface を配線しておくと、 どうしても覗いてみたい内部の信号線を一時的に interface に追加することで、 外まで引き出して観察するようなことができそう。

コメント・質問





Counter: 15261 (from 2010/06/03), today: 1, yesterday: 0