LRM読解(Chap.3 データタイプ~型の種類)

2008/09/02Verilog::文法import

データタイプ~型の種類[LRM Chap.3]

値 [3.1]

Verilog-HDLには下記の4つの値しか存在しません. *1ただし,NET型では論理値に強度(Strength)を与えることができます.(LRM Chap.7)

文字説明
0論理値0,もしくはfalse状態を示す
1論理値1,もしくはtrue状態を示す
x論理値不定を示す
zHigh Impedance状態を示す

NET型とVariable型 [3.2]

NET

値を保持することは無く,PAD間をつなぐための配線材相当である.syntaxを引用する.

net_declaration ::= (From Annex A - A.2.1.3)
    net_type [ signed ] [ delay3 ] list_of_net_identifiers ;
  | net_type [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
  | net_type [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
  | net_type [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;
  | trireg [ charge_strength ] [ signed ] [ delay3 ] list_of_net_identifiers ;
  | trireg [ drive_strength ] [ signed ] [ delay3 ] list_of_net_decl_assignments ;
  | trireg [ charge_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_identifiers ;
  | trireg [ drive_strength ] [ vectored | scalared ] [ signed ] range [ delay3 ] list_of_net_decl_assignments ;

net_type ::= (From Annex A - A.2.2.1)
    supply0 | supply1
  | tri | triand | trior | tri0 | tri1
  | wire | wand | wor

drive_strength ::= (From Annex A - A.2.2.2)
   ( strength0 , strength1 )
  | ( strength1 , strength0 )
  | ( strength0 , highz1 )
  | ( strength1 , highz0 )
  | ( highz0 , strength1 )
  | ( highz1 , strength0 )

strength0 ::= supply0 | strong0 | pull0 | weak0

strength1 ::= supply1 | strong1 | pull1 | weak1

charge_strength ::= ( small ) | ( medium ) | ( large )

delay3 ::= (From Annex A - A.2.2.3)
  # delay_value | # ( delay_value [ , delay_value [ , delay_value ] ] )

delay2 ::=
  # delay_value | # ( delay_value [ , delay_value ] )

delay_value ::=
    unsigned_number
  | parameter_identifier
  | specparam_identifier
  | mintypmax_expression

list_of_net_decl_assignments ::= (From Annex A - A.2.3)
  net_decl_assignment { , net_decl_assignment }

list_of_net_identifiers ::=
  net_identifier [ dimension { dimension }]
  { , net_identifier [ dimension { dimension }] }

net_decl_assignment ::= (From Annex A - A.2.4)
  net_identifier = expression

dimension ::= (From Annex A -A.2.5)
  [ dimension_constant_expression : dimension_constant_expression ]

range ::=
  [ msb_constant_expression : lsb_constant_expression ]

(かなりテキトウな理解)
要は,配線と思えばよい?.

  • wire - 単純に端子?間を結ぶ
  • tri - tri-state?何に使うんだろうな...

Variable

syntaxを引用する.値を保持できる器となります.

integer_declaration ::= (From Annex A - A.2.1.3)
  integer list_of_variable_identifiers ;

real_declaration ::=
  real list_of_real_identifiers ;

realtime_declaration ::=
  realtime list_of_real_identifiers ;

reg_declaration ::=
  reg [ signed ] [ range ] list_of_variable_identifiers ;

time_declaration ::=
  time list_of_variable_identifiers ;

real_type ::= (From Annex A - A.2.2.1)
    real_identifier [ = constant_expression ]
  | real_identifier dimension { dimension }

variable_type ::=
    variable_identifier [ = constant_expression ]
  | variable_identifier dimension { dimension }

list_of_real_identifiers ::= (From Annex A - A.2.3)
  real_type { , real_type }

list_of_variable_identifiers ::=
  variable_type { , variable_type }

dimension ::= (From Annex A - A.2.5)
  [ dimension_constant_expression : dimension_constant_expression ]

range ::=
  [ msb_constant_expression : lsb_constant_expression ]

変数としては,下記の種類がある.integer, real, realtime, reg, time.



Vector [3.3]

NET/Variable宣言時に,型とシンボルの間に記述する.書式では'range'と記していたもの.VectorのReg/Netは,2を法とする,2^nの演算に従う.(n=ベクタのビット長)

range ::=
  [ msb_constant_expression : lsb_constant_expression ]

MSB>LSBである必要は無い.,2^(abs(MSB-LSB)).Noteにて,ここで確保可能なサイズについて記されている.

1) Implementations may set a limit on the maximum length of a vector, but they will at least be 65536 (216) bits.
2) Implementations do not have to detect overflow of integer operations.

1)最低でも,ベクタ長は 2^16(65536) をサポートすること.
2)整数演算のオーバフローは検出する必要は無い.



Arrays [3.10]

net/variable宣言時に,シンボル名の後ろに"[mm:ll]"で指定する.また,LRM 3.10.noteより,

Implementations may limit the maximum size of an array, but they shall at least be 16777216 (224).

Parameters [3.11]

Parametersは,variable型にも,net型にも属さない.また,変数ではなく,定数である.
module parameters と specify parameters とがある.Parameter宣言は,net型/parameter型/variable型で,既に宣言された名称で再定義することはできない.

Parameters

syntax

local_parameter_declaration ::= (From Annex A - A.2.1.1)
  localparam [ signed ] [ range ] list_of_param_assignments ;
  | localparam integer list_of_param_assignments ;
  | localparam real list_of_param_assignments ;
  | localparam realtime list_of_param_assignments ;
  | localparam time list_of_param_assignments ;

parameter_declaration ::=
  parameter [ signed ] [ range ] list_of_param_assignments ;
  | parameter integer list_of_param_assignments ;
  | parameter real list_of_param_assignments ;
  | parameter realtime list_of_param_assignments ;
  | parameter time list_of_param_assignments ;

list_of_param_assignments ::= (From Annex A - A.2.3)
  param_assignment { , param_assignment }

param_assignment ::= (From Annex A - A.2.4)
  parameter_identifier = constant_expression

range ::= (From Annex A - A.2.5)
  [ msb_constant_expression : lsb_constant_expression ]
  • list_of_param_assignmentsは,module itemの中か,module_parameter_port_list*2の中のみ記述可能.
  • param_assignmentsが,module_parameter_port_list内に存在しない場合,param_assignmentsはlocal parameterとなり,どんな手段でもoverride不可能となる.

Parameterの定数再定義について

runtimeに書き換えることはできません.しかし,module parameterは,compilation時に,module定義時の値と異なる値に書き換えることは可能です.これはmodule instanceのカスタムを許容します.
parameterの修正は,defparam文か,module instance文で修正可能です.

parameter文の代表的な使い方は,delay(遅延時間)や変数のビット幅(width)を定義するのに使います.Chap..12で詳細に記します.


module parameterはタイプ指定とrange指定(range)を持つことができます。以下の規則に従って、module parameterのタイプとrange(range)があるものとします.

  • タイプもrange指定もないparameter宣言は,すべての値のオーバーライドも適用された後の,パラメタに割り当てられた最終値のタイプとrangeをデフォルトとするものとします。
  • range指定はあるが,タイプ指定のないパラメタは,符号なしのパラメタ定義rangeになるでしょう.
    符号とrangeは,値のオーバーライドによる影響を受けさせないものとします.
  • range指定が無い,タイプ指定を伴うパラメタは,タイプ指定になるでしょう。
  • 符号ありparameterは,全ての値のオーバーライドを適用した後に,パラメタに割り当てられた最終値のrangeをデフォルトとするものとします、。
  • 符号あり,型指定ありかつrange指定ありのparameterは,符号あり・定義されたrangeとなるでしょう.符号・rangeは,値のオーヴァーライドによる影響を受けない.
  • range指定が無く,かつ,(符号あり型指定されているか,型指定が無い)parameter宣言は,LSB=0, MSBは最終的にparametaにアサインされた値が収まる大きさ以下となるでしょう.
  • range指定が無く,かつ,(符号あり型指定されているか,型指定が無い),かつ最終的にparametaにアサインされた値が符号なしとなるようなparameter宣言は,LSB=0, MSBは31となるでしょう.

// an implied range with an lsb equal to 0 and an msb equal to an implementation-dependent value of at least 31.

※直訳すぎてスミマセン.宣言時に省略した場合や上書きしたときのコンパイラの挙動について仕様が切られているようです.



Local parameters - localparam [3.11.2]

Verilog HDL localparamについて.local parameterは,defparam文や,並び順または名前付きの直接書き換えができません.local parameterは, - local parameter(s) are identical to parameters except that they can not directly be modified with the defparam statement or by the ordered or named parameter value assignment.

Local parameters can be assigned to a constant expression containing a parameter which can be modified with the defparam statement or by the ordered or named parameter value assignment.

See 12.1.3 for details. The syntax for local parameter declarations is given in Syntax 3-4.


Specify parameters[3.11.3]
specparam_declaration ::= (From Annex A - A.2.2.1)
  specparam [ range ] list_of_specparam_assignments ;

list_of_specparam_assignments ::= (From Annex A- A.2.3)
  specparam_assignment { , specparam_assignment }

specparam_assignment ::= (From Annex A - A.2.4)
  specparam_identifier = constant_mintypmax_expression
  | pulse_control_specparam

pulse_control_specparam ::=
  PATHPULSE$ = ( reject_limit_value [ , error_limit_value ] ) ;
  | PATHPULSE$specify_input_terminal_descriptor$specify_output_terminal_descriptor
  = ( reject_limit_value [ , error_limit_value ] ) ;

error_limit_value ::=
  limit_value

reject_limit_value ::=
  limit_value

limit_value ::=
  constant_mintypmax_expression

range ::= (From Annex A - A.2.5)
  [ msb_constant_expression : lsb_constant_expression ]

Table 8. Differences between specparams and parameters

Specparams(specify parameter)Specparams(specify parameter)
Use keyword specparamUse keyword parameter
Shall be declared inside a module or specify blockShall be declared outside specify blocks
May only be used inside a module or specify blockMay not be used inside specify blocks
May be assigned specparams and parametersMay not be assigned specparams
Use SDF annotation to override valuesUse defparam or instance declaration parameter value passing to override values


Name spaces [3.12]

*1 : 例外としてevent型(LRM9.7.3)があります.

*2 : referto SS.12

LRM読解(Chap.2 字句定義/語彙規約)

2008/08/31Verilog::文法import

字句定義/語彙規約 ~ Lexical conventions (LRM-Chap.2)

LRMから,少し抜粋.

数値表現

| binary  | [size]*'[s|S]*(b|B)[01]+
| octal   | [size]*'[s|S]*(o|O)[0-7]+
| hexa    | [size]*'[s|S]*(h|H)[0-9a-fA-F]+
| decimal | ([size]*'[s|S]*(d|D)[0-9]+)|([0-9]+)

LRM 2.5.1 Integer constants

Example 3 Using sign with constant numbers

8'd-6   // 構文違反.
-8'd6   // 6の2の補数を示します.8bitサイズを保持します.
4'shf   // これはbinaryで 4bitの'1111'と書き直せます.
        // 2の補数表現では-1になります.
        // 即ち,これは -4'h1と等価です.
-4'sd15 // 同様にして,これは 4'd1と等価です.(-(-4'd1))

LRM 2.6 Strings

一行内で,double quotes("")で閉じられた部分を文字列とみなします.unsigned int定数として 8bit ASCII文字を取り扱うことができます.

文字列変数?の定義と使い方

stringvarというレジスタ変数を用意し,"Hello world!"を代入してみましょう.

 reg [8*12:1] stringvar;
 initial begin
   stringvar = "Hello world!";
 end

8bit widthの[12:1]配列,と見ればいいんですかねぇ.[8*(欲しい文字数):1]とすればよいようです.C言語と違い,NULL挿入はされない模様です.


LRM 2.6.2 の NOTE

意訳で敵どうだけれど,まぁ,こんなもんで.

When a variable is larger than required to hold a value being assigned,
the contents on the left are padded with zeros after the assignment.
This is consistent with the padding that occurs during assignment of nonstring values.

変数のほうが,文字列よりも大きい場合には,左側がゼロパディングされます.これは,定数のパディングと矛盾しないようになっているからである.(意訳)

If a string is larger than the destination string variable,
the string is truncated to the left, and the leftmost characters will be lost.
文字列のほうが長い場合には,文字列の左側が失われます.
LRM 2.6.3 特殊文字

C言語と同様に,下記の特殊文字が定義されます.エスケープ記号とか..

Escape Stringescape stringで示される文字
\n改行文字
\tタブ文字
\\\(バックスラッシュ, \x5C)
\"double quote(",\x22)
\dddキャラクタコード指定. dは0~7の数値を示す. ただし, 1~3個で構成する(3個必要なわけではない).

LRM 2.7 Identifiers, keywords, and system names

識別子は、それに参照をつけることができるようにユニークな名前をオブジェクトに与えるのに使用されます。識別子は、簡単な識別子かエスケープされた識別子(LRM 2.7.1参照)のどちらかです。簡単な識別子は 文字、数字、ドル記号($)、およびアンダースコア(_)の組み合わせである。簡単な識別氏の一文字目は,数値やドル記号にすべきではないです.英字か,アンダースコアなら可能です.識別子は大文字と小文字を区別するでしょう.

原文

An identifier is used to give an object a unique name so it can be referenced.
An identifier is either a simple identifier or an escaped identifier (see 2.7.1).
A simple identifier shall be any sequence of letters, digits, dollar signs ($), and underscore characters (_).
The first character of a simple identifier shall not be a digit or $;
it can be a letter or an underscore. Identifiers shall be case sensitive.

naming rule?
  • System task/functionの名前は,'$'で始まる.[LRM2.7.4]

2.8 Attribute[LRM 2.8]

syntax

attribute_instance ::= (From Annex A - A.9.1)
  (* attr_spec { , attr_spec } *)

attr_spec ::=
  attr_name = constant_expression
  | attr_name

attr_name ::=
  identifier

module

2008/08/20Verilog::文法import

module文(synthesizable/TestBench)

概要

階層化設計の一塊.入出力信号・パラメータを引数として、実体化する.
順序回路・組み合わせ回路の0個以上の組み合わせの回路ブロックを記述する.

書式

ANSI式*1を以下に示す.

module <module-name> (
   input foo,
   output bar,
   inout bus
  );
  // local signal/variable...
  begin
   // 式
  end
endmodule

それ以前の書式は以下のように記述する.

module <module-name> ;
   input foo,
   output bar,
   inout bus
// (略)
endmodule


*1 : ANSI-Cの関数記述相当.K&R時代は変数だけを並べて,型+変数名は後に記述した.Verilogでも、module名だけでセミコロンを打ち,信号名を並べてからbegin文を置く記述も可能.

moduleのパラメタ変更方法

パラメタの使い方を理解しておらず,つい最近に例を見かけて知ったので記載しておく.
defineとは違い、インスタンス化する際に値を変化させて利用することができる,と推測する.

  • defparam文
  • instance化する際に, 渡す.
     module-name #(
    		.paramete-name(value),
    		...
    	) instance-name (
    		.signal-name(symbol),
    		....
    	) ;
    

※インデントはxilinx webpack 10.1sp2の自動生成ツールの出力を真似た.

wait

2008/08/20Verilog::文法import

待ち処理(TestBench)

Test記述時に有効. 式の評価結果が TRUEになるまで待つ.
initial文でクロックに同期して処理をさせたい場合に使うとよさそう. @(posedge CLK)で十分です.

  always #20 CLK <= ~CLK;

  initial begin
   ...
   wait( CLK==0 );
   wait( CLK==1 );
→ @(posedge CLK);
  # 2  // CLK's posedge + 2 [nSec]
   hoge <= 1;
   ...
  end

wait(式?)

前述のとおり.


@ (式?)

式の状態を待つ?立ち上がり:posedge
立ち下り:negedge
などなど...と思う.調べてないけれども使ったものだけ記述.サイトではなく仕様書を見て転記してこないと、ですね.

task

2008/08/20Verilog::文法import

書式

task <name>;
	// input ; 値渡し. 呼び出しもとのreg等に影響を与えない.
	// output

	// process...
endtask

syntax

task_declaration ::= (From Annex A - A.2.7)
   task [ automatic ] task_identifier ;
     { task_item_declaration }
     statement
   endtask
 | task [ automatic ] task_identifier ( task_port_list ) ;
     { block_item_declaration }
     statement
   endtask

task_item_declaration ::=
  block_item_declaration
  | { attribute_instance } tf_input_declaration ;
  | { attribute_instance } tf_output_declaration ;
  | { attribute_instance } tf_inout_declaration ;

task_port_list ::=
  task_port_item { , task_port_item }

task_port_item ::=
  { attribute_instance } tf_input_declaration
  | { attribute_instance } tf_output_declaration
  | { attribute_instance } tf_inout_declaration

tf_input_declaration ::=
  input [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | input [ task_port_type ] list_of_port_identifiers

tf_output_declaration ::=
  output [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | output [ task_port_type ] list_of_port_identifiers

tf_inout_declaration ::=
  inout [ reg ] [ signed ] [ range ] list_of_port_identifiers
  | inout [ task_port_type ] list_of_port_identifiers

task_port_type ::=
  time | real | realtime | integer

block_item_declaration ::= (From Annex A - A.2.8)
  { attribute_instance } block_reg_declaration
  | { attribute_instance } event_declaration
  | { attribute_instance } integer_declaration
  | { attribute_instance } local_parameter_declaration
  | { attribute_instance } parameter_declaration
  | { attribute_instance } real_declaration
  | { attribute_instance } realtime_declaration
  | { attribute_instance } time_declaration

block_reg_declaration ::=
  reg [ signed ] [ range ]
  list_of_block_variable_identifiers ;

list_of_block_variable_identifiers ::=
  block_variable_type { , block_variable_type }

block_variable_type ::=
  variable_identifier
  | variable_identifier dimension { dimension }


概要

  • 記述はmoduleとほぼ同じ. 許容される型/process文が増える程度.
  • 引数は宣言した順に渡される.名前渡しも可能.(ドット+名前(信号))
  • input引数は値渡しになる.呼び出し元に影響はでない.
  • inout/outputは代入すると呼び元に値を返すことができる.[LRM 10.1]
  • 実回路としてsynthesize不可. simulation modelでのみ使用可能
  • "#値"による待ち処理を入れることができる. task呼び出し元は, task内で消費した時間の後に返ってくる.

その他メモ

if文を用いて、条件によって待ち時間を変化させることもできる.ex.

  if (t_AD > t_CS)  begin
    # (t_CS)
    CS_n <= 0;
    # (t_AD - t_CS)
    ADR <= ADR_buf;
  end
  else begin
    # (t_AD)
    ADR <= ADR_buf;
    # (t_CS - t_AD)
    CS_n <= 0;
  end

※CS_nとADRの変化時間が、パラメタt_ADとt_CSの大小関係により前後するため、分岐させた.後日,CPUバスの試験パターンを振るための例を示す.waveformを外部プログラムで吐いて,取り込んだほうが早かった気がするけれど。。。