HDL関係
(wiki contentsのtop treeにするため,暫定作成)
(wiki contentsのtop treeにするため,暫定作成)
渦巻きの人をさわることになり,ドキュメントを読むハメになりました.が,最新のdocumentは和訳が追いついていないため,語学力の弱い私としては苦労しております.
同じ境遇の方,また,どうやって学習してよいかわからないという方,共に勉強していきましょう….
翻訳ミスや,思い違い等あるかと思いますので,随時指摘いただけますと助かります.さて,これもどこまで伸びるか(ぇ-
前文は不可能なので,気になった部分等,部分的に抜粋していきます.
[altera][qsf] | "mnl_qsf_reference.pdf" |
[altera][Q2HB] | "quartusii_handbook.pdf" |
[altera][TSR] | "TclScriptRefMnl.pdf" |
10.3 Functions と function呼び出し ~ Functions and function calling functionの目的は,式中で使用するための値を返すことです.この節では,functionの定義の仕方と使い方について解説します.
syntax
function_declaration ::= (From Annex A - A.2.6) function [ automatic ] [ signed ] [ range_or_type ] function_identifier ; function_item_declaration { function_item_declaration } function_statement endfunction | function [ automatic ] [ signed ] [ range_or_type ] function_identifier ( function_port_list ) ; block_item_declaration { block_item_declaration } function_statement endfunction function_item_declaration ::= block_item_declaration | tf_input_declaration ; function_port_list ::= { attribute_instance } tf_input_declaration { , { attribute_instance }tf_input_declaration } tf_input_declaration ::= input [ reg ] [ signed ] [ range ] list_of_port_identifiers | input [ task_port_type ] list_of_port_identifiers range_or_type ::= range | integer | real | realtime | time 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 }
function定義は,'function'キーワードで始まり,オプショナルで'automatic'が続き,符号('signed')指定,rangeや関数の戻り値の型,function名と続いてから,セミコロン,または親で閉じたfunction port listにセミコロンとなり,'endfunction'で終わります.
'range_or_type shall'の使用はオプションです.'range'や'type'なしで定義されたfunctionは,戻り値はデフォルトで1bit reg型になります.もし使われたならば,'range_or_type'は,real型,integer型,time型,realtime型,[n:m] bit幅指定の値となるfunctionの戻り値を与えます.
A function shall have at least one input declared. functionは,たった一つの入力宣言を持ちます.keyworf 'automatic'は,各再帰呼び出しのために動的に確保される再帰可能なfunctionを宣言します.
function入力は,2つの方法のうちの1つで宣言されます.
1つ目の方法は,セミコロンに続いてfunction名を持ちます.セミコロンのあと,1つ以上のオプション的な入力は,後述するblock item宣言と混ざって宣言します.function item宣言のあと,ビヘイビア文とendfunction keywordがあります.
2つ目の方法は,function名のあと,開き丸括弧と1つ以上の入力宣言をコンマ区切りで持ちます.全ての入力宣言のあと,閉じ丸括弧とセミコロンがあります.セミコロンのあと,0以上のblock itemが宣言され,続けてビヘイビア文,endfunction keywordとなります.
例:
以下の例は,'range'定義を使った,getbyteという名のfunctinoを定義します.
function [7:0] getbyte; input [15:0] address; begin // code to extract low-order byte from addressed word . . . getbyte = result_expression; end endfunction
function宣言の2つ目の様式を使って,以下のように定義することができます.
function [7:0] getbyte (input [15:0] address); begin // code to extract low-order byte from addressed word . . . getbyte = result_expression; end endfunction
function定義は,暗黙的にfunctionと同じ名前で,関数内部の宣言をするものとします.この変数は,デフォルトで1bit reg変数か,function宣言中のtypeで与えられる型と同様になります.function定義は,function戻り値をfunction名と同じ名前の内部変数への代入によって,関数からの戻り値を初期化します.
function宣言と同じscopeにおいて,function名と同じ名前のobjectを宣言することはイリーガルです.関数内において,function内の式で使われる,function名の暗黙的な変数があります.これはまた,function内のscopeにおいても,function名と同じ名前のobjectを宣言することはイリーガルです.
以下のLRM 10.3.1の例の行は,このコンセプトを示します.
getbyte = result_expression;
function呼び出しは,式中のオペランドです.function呼び出しは,以下の様式です.
function_call ::= (From Annex A - A.8.2) hierarchical_function_identifier{ attribute_instance } ( expression { , expression } )
function呼び出しへの,引数の評価順序は,未定義です.
例)
以下の例は,LRM 10.3.1で定義されたgetbyte functionを2回呼び出した結果を結合して,wordを作ります.
word = control ? {getbyte(msbyte), getbyte(lsbyte)}:0;
functionはtaskよりも多くの制約があります.以下の6つのルールが,使用法を抑制します.a) function定義は,時間制御文(time-controlled statements,'#','@',"wait")を含んではならない.b) functionはtaskをenableにしてはならない.c) function定義は,少なくとも1つの入力引数を含みます.d) function定義は,output/inoutと宣言された引数を持ちません.e) function定義は,function名と同じ名称の内部変数への代入による戻り値の代入を含みます.f) functionは,ノンブロッキング代入を持ちません.A function shall not have any non blocking assignments.
例)
この例は,integer値を返す"factorial"と呼ばれるfunctionを定義します.この"factorial" functionは,反復して呼び出され,戻り値を表示します.
module tryfact; // define the function function automatic integer factorial; input [31:0] operand; integer i; if (operand >= 2) factorial = factorial (operand - 1) * operand; else factorial = 1; endfunction // test the function integer result; integer n; initial begin for (n = 0; n <= 7; n = n+1) begin result = factorial(n); $display("%0d factorial=%0d", n, result); end end endmodule // tryfact
The simulation results are as follows:
0 factorial=1 1 factorial=1 2 factorial=2 3 factorial=6 4 factorial=24 5 factorial=120 6 factorial=720 7 factorial=5040
"Constant function calls"は,"elaboration"時(LRM 12.1.3)において,複雑な値の計算の構築のサポート使われます."Constant function call"は,functionへの引数が定数式("constant expressions")である,呼び出しモジュールへのローカルな"constant function"のfunction起動です."Constant function call"は,以下の制約を満足する,通常のVerilog functionsのサブセットです.
i.e. "constant function"呼び出しの評価で使われるどんな"parameter"も, 元の"constant function"呼び出し位置で,その"parameter"の使用を構成する.(適用する?)
"constant function call"は,"elaboration"("綿密な仕上げ"の意)の時に評価されます."elaboration"実行は,simulation時やelaboration時の複数の関数呼び出し間で使われる,変数の初期値に影響を与えない.これらの場合において,その変数は,通常のsimulationのために初期化されます.
例)
This example defines a function called clogb2 that returns an integer which has the value of the ceiling of the log base 2.
module ram_model (address, write, chip_select, data); parameter data_width = 8; parameter ram_depth = 256; localparam adder_width = clogb2(ram_depth); //(訳コメント)定数項に対してfunctionを使う,てことですね.. やっと意味がわかった.. input [adder_width - 1:0] address; input write, chip_select; inout [data_width - 1:0] data; //define the clogb2 function function integer clogb2; input depth; integer i,result; begin for (i = 0; 2 ** i < depth; i = i + 1) result = i + 1; clogb2 = result; end endfunction reg [data_width - 1:0] data_store[0:ram_depth - 1]; //the rest to the ram model
An instance of this ram_model with parameters assigned:
ram_model #(32,421) ram_a0(a_addr,a_wr,a_cs,a_data);
taskは,taskに渡される変数の引数を定義して,結果を受ける変数定義の構文からenableにされます.
制御は,taskが完了した後で,processを有効に戻します.したがって,taskがタイミング制御を有した場合,taskをenableにした時刻と,制御が戻った時刻に差異が生じえます.taskは他のtaskをenableにすることができ,さらにそのtaskが別のtaskをenableにする数に上限は無いです.
どれだけのtaskがenableになろうとも,制御はすべてのenableにされたtaskが完了するまで返ってきません.
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 }
There are two alternate task declaration syntaxes. 2種類のtask宣言書式があります.
1つ目の書式は,"task"キーワードから始まり,オプション"automatic"やタスク名とセミコロンが続きます.そして,"endtask"で終わります."automatic"キーワードは,"automatic task"を宣言します.それは,ダイナミックにそれぞれの同時発生のタスクエントリーに割り当てられた,すべてのタスク宣言について再代入可能です.
"task item"宣言は,以下のように定義できます.
2つめの書式は,"task",続いて"task名",丸括弧で閉じた"task_port_list"で始まります."task_port_list"は,0以上のコンマ区切りの"task_port_items"です.丸括弧を閉じたあとにセミコロンがあります."task body"が続き,そして"endtask"がきます.
どちらの書式においても,ポート宣言は,"tf_input_declaration","tf_output_declaration","tf_inout_declaration"で定義されるように同じ書式です.
オプション"automatic"キーワードのないタスクは,"static task"で,全ての宣言されたアイテムは静的に確保されます.これらのitemは,同時実行する全てのtaskの使い方間で共有されます.
オプションキーワード"automatic"のあるtaskは,"automatic tasks"です."automatic task"内の全てのアイテムは,それぞれの呼び出しに対して動的に確保されます."automatic task"のアイテムは,階層的な参照によりアクセスされます."automatic task"は,それらの階層的な名前を使うことで,起動されます.
taskを有効にする書式は,丸カッコ内のコンマ区切りの式リストのような引数を渡すことです.正式な書式を以下に示す.
task_enable ::= (From Annex A - A.6.9) hierarchical_task_identifier [ ( expression { , expression } ) ] ;
task enableing書式のための引数リストは,オプショナルです.もし,引数リストが与えられるならば,そのリストは式のリスト順が,タスク定義内の引数リストの並び順と一致する必要があります.
タスクの引数がinputとして宣言された場合,関連する式はどのような式にもなれます.引数内の式評価順序は未定義です.タスクの引数がoutputまたはinoutとして宣言された場合は,厳密に手続き型代入(LRM9.2)の左辺として正しい式です.以下のitemsは,この要求を満たします.
task enabling構文の実行は,enabling構文でリストされた式から,task内で定義された引数へ,入力値が渡されます.
taskからの返り処理は,task output型とinput型の引数から,task enabling構文内の相当する変数へ,値が渡されます.
All arguments to the task shall be passed by value rather than by reference (that is, a pointer to the value). taskへの全ての引数は,参照(値へのポインタ)よりも値渡しのほうがよい.
例1) 以下の例は,5つの引数を持つタスク宣言の基本構造を表します.
task my_task; input a, b; inout c; output d, e; begin . . . // statements that perform the work of the task . . . c = foo1; // the assignments that initialize result regs d = foo2; e = foo3; end endtask
2つ目のタスク宣言様式を使うと,以下のように定義できます.
task my_task (input a, b, inout c, output d, e); begin . . . // statements that perform the work of the task . . . c = foo1; // the assignments that initialize result regs d = foo2; e = foo3; end endtask
以下の分はtaskをenableにします.
my_task (v, w, x, y, z);
task enabling引数 (v,w,x,y,z) は,タスク宣言時の(a,b,c,d,e)に相当します.task enablingの時刻において,inoput,inout型の引数(a,b,c)は,(v,w,x)で渡された値を受け取ります.例えば,task enablingの実行は,有効に以下の代入の原因を呼びます.
a = v; b = w; c = x;
task処理の一部のように,my_taskのためのtask定義は,c,d,eへ計算結果をおきます.task完了時,計算値をprocessを呼び出した元へ返すための以下の代入が適用されます.
x = c; y = d; z = e;
例2) 以下の例は,"traffic light sequencer"の記述をtsakを使って表します.
module traffic_lights; reg clock, red, amber, green; parameter on = 1, off = 0, red_tics = 350, amber_tics = 30, green_tics = 200; // initialize colors. initial red = off; initial amber = off; initial green = off; always begin // ライト制御用のシーケンス red = on; // 赤色on light(red, red_tics); // wait green = on; // 緑色on light(green, green_tics); // wait. amber = on; // 琥珀色on light(amber, amber_tics); // wait. end // task : 立ち上がりエッヂを'tics'回待って,'color'ライトをオフにする. task light; output color; input [31:0] tics; begin repeat (tics) @ (posedge clock); color = off; // ライトオフ end endtask always begin // クロック波形 #100 clock = 0; #100 clock = 1; end endmodule // traffic_lights.
タスクは,同時に1つ以上enableにされるかもしれません.automaticタスクの全ての変数は,その実施に特定の状態を保存するために,それぞれの同時発生のタスク実施で複製されるものとします.
staticタスクの全ての変数は,タスクの同時発生の起動の数にかかわらず,静的になるでしょう.なぜならば,モジュールインスタンスそれぞれで宣言している局所変数に対応するただ一つの変数があるので.しかし,モジュールインスタンスの異なるstaticタスクは,互いからの別々の格納場所があるものとします.
staticタスクで宣言された変数は,呼び出し間でそれらの値を保有するものとします.staticタスクで宣言された変数は,LRM 3.2.2で記述するように,デフォルト初期値に初期化されます.automaticタスクで宣言された変数は,変数のスコープに入ったときに,デフォルト初期値に初期化される.なぜならば,automaticタスクで宣言された変数は,task起動の終了時に,de-allocateされるので,変数はその後の場所では参照される所望の構造で使われない.*1
automatic taskのlocal variableに対してやってはいけないことを以下に示す.
TITLE: 10. Tasks and functions taskとfunctionは,記述中のあらゆる場所からの共通の手続きを実行するアビリティを提供する.ソースコードの可読性・デバッグ性を容易にするために,大きな手続きを小さな手続きに分解することも提供する(意訳).この節は,taskとfunctionの間の差異について議論し,taskとfunctionの定義の仕方と起動の仕方について記述し,それぞれの例を提供します.
以下の規則は,funtionとtaskとを区別します.
functionの目的は,1つの値を返すことによって,入力の値に対する応答をすることです.taskは複数のゴールをサポートすることができ,複数の返り値を計算することができます.しかし,outputまたはinput型の引数のみが,taskの呼び出しから返り値を渡すことができます.*1 functionは,式のオペランドのように使われます.オペランドの値は,関数による返り値です.
Example
taskまたはfunctionは,16bit wordを交換することとして定義することができます.taskは交換後のwordをoutput引数で返します.switch_bytesと呼ぶtaskを有効にするためのソースコードは,下記の例のように見えます.
switch_bytes (old_word, new_word);
task:switch_bytesは,old_wordにbytesをとり,byte orderを入れ替えて,new_wordにおきます.word-switching functionは,functionの返り値として入れ替え後の値を返します.なので,function:switch_bytesの関数呼び出しは,下記の例のように見えます.
new_word = switch_bytes (old_word);