VivadoのSystemVerilog対応状況(合成編)
Xilinx の最新開発環境 Vivado における System Verilog 対応状況を調べてみました†
System Verilog を学ぶにあたって、とりあえず使える範囲から学ばないと無駄になりそうなので、 という意味合いで、対応状況を確認してみました。
参考資料†
"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 / 01XZ | type | bits | default |
---|---|---|---|
2-state | shortint | 16-bit | signed |
int | 32-bit | signed | |
longint | 64-bit | signed | |
byte | 8-bit | signed | |
bit | user defined vector size | unsigned | |
4-state | logic | user defined vector size | unsigned |
reg | user-defined vector size | unsigned | |
integer | 32-bit | signed | |
time | 64-bit | unsigned |
むむぅ。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 に固有なものとして重要そうなのは†
- 配線型 (logic / bit など)
- enum (ステートマシンのステートに使えそう)
- struct> (interface との違いがよく分かっていない・・・)
- casting
- Block内での変数定義
- モジュール配線名の省略
- Interface (優れた規約が欲しい)
- Packages (優れた規約が欲しい)
くらいでしょうか。
メモ†
interface のいけない使い方†
各モジュールにデバッグ用の interface を配線しておくと、 どうしても覗いてみたい内部の信号線を一時的に interface に追加することで、 外まで引き出して観察するようなことができそう。