function [出力のビット幅] 関数名;
input [入力のビット幅] 入力名1, 入力名2, ...;
begin
関数名 = 計算式;
end
endfunction
ポイント
function キーワードで宣言する
関数名と同じ名前の変数が戻り値として使用される
input を使用して入力を宣言する(output や inout は使用不可)
begin ... end の中で計算処理を行う
always ブロックの外で定義する
シンプルなVerilog functionの例
以下に、8ビットの加算を行う関数を示します。
module example;
function [7:0] add_function;
input [7:0] a, b;
begin
add_function = a + b;
end
endfunction
reg [7:0] x, y, sum;
initial begin
x = 8'b00001100; // 12
y = 8'b00000101; // 5
sum = add_function(x, y);
$display("Sum: %d", sum); // Sum: 17
end
endmodule
解説
add_function は 8ビットの入力2つ(a, b)を受け取り、その和を返す 関数
sum = add_function(x, y); のように関数を呼び出し、計算結果を変数 sum に代入
initial ブロック内で $display を用いて結果を表示
Verilog functionの入力と出力の宣言方法
入力の宣言
Verilog functionは input のみ を引数として指定できます。
function [7:0] my_function;
input [7:0] in1, in2;
begin
my_function = in1 & in2; // AND演算
end
endfunction
注意:output は指定できません。出力は 関数名と同じ変数 で返します。
条件分岐を含むVerilog function
関数内で if や case を用いた条件分岐も可能です。
function [3:0] max_function;
input [3:0] a, b;
begin
if (a > b)
max_function = a;
else
max_function = b;
end
endfunction
module function_example;
function [7:0] xor_function;
input [7:0] a, b;
begin
xor_function = a ^ b;
end
endfunction
reg [7:0] x, y, result;
initial begin
x = 8'b11001100;
y = 8'b10101010;
result = xor_function(x, y); // functionを呼び出す
$display("XOR Result: %b", result); // XOR Result: 01100110
end
endmodule
always @(a or b) begin
function [7:0] my_function; // ❌ always内での関数定義は禁止
input [7:0] x, y;
begin
my_function = x + y;
end
endfunction
end
このコードはコンパイルエラーになります。
✅ 正しい方法
alwaysブロックの外で function を定義し、ブロック内で呼び出す。
function [7:0] add_function;
input [7:0] x, y;
begin
add_function = x + y;
end
endfunction
always @(a or b) begin
result = add_function(a, b); // ✅ functionを呼び出す
end
function [7:0] multiply;
input [3:0] a, b;
integer temp;
begin
temp = a * b;
multiply = temp;
end
endfunction
functionはどのような場面で使用すべきか?
Q. functionはどのような場面で使うのが適切ですか?
A. functionは「単純な演算処理」や「組み合わせ回路の記述」に適しています。
例えば、以下のような処理に使うと便利です:
演算処理(加算、減算、論理演算)
デコーダやエンコーダ
比較演算(最大値・最小値の判定)
エラーチェック(パリティチェックなど)
ただし、順序回路(フリップフロップを含む回路)には適していません。
function内で別のfunctionを呼び出せる?
Q. Verilog functionの中で、別のfunctionを呼び出せますか?
A. はい、可能です。ただし、関数の依存関係に注意が必要です。
function [7:0] add;
input [7:0] a, b;
begin
add = a + b;
end
endfunction
function [7:0] double_add;
input [7:0] x, y;
begin
double_add = add(x, y) * 2; // 他のfunctionを呼び出す
end
endfunction
functionとalways文の使い分け方を教えてください。
Q. functionとalways文はどのように使い分けるべきですか?
A. functionは「組み合わせ回路」、alwaysは「順序回路」に使います。
項目
function
always
遅延 (#10)
不可
可能
状態保持
不可(即時評価)
可(フリップフロップとして使用可能)
主な用途
組み合わせ回路(即時演算)
順序回路(フリップフロップやカウンター)
例えば、加算処理を行う場合:
✅ function(組み合わせ回路)
function [7:0] add;
input [7:0] a, b;
begin
add = a + b;
end
endfunction
✅ always(順序回路)
always @(posedge clk) begin
sum <= a + b; // フリップフロップとして動作
end
まとめ
✅ functionは単純な計算や組み合わせ回路に最適 ✅ taskとの違いを理解し、適切に使い分ける ✅ alwaysとの使い分けも重要(順序回路 vs 組み合わせ回路) ✅ 遅延(#10)や配列は使用できないため、taskやmoduleを活用する