パラメータ
CoddyのVerilogジャーニー「基礎」セクションの一部 — レッスン 11/90。
同じモジュールのコピーを多数作成し、それらを異なる場所で使用することができます。これは**マルチインスタンス**と呼ばれます。同じコードを何度も繰り返し書く代わりに、一度だけ書いて、必要な回数だけ再利用します。各インスタンスは、チップ上のそのハードウェアの個別のコピーです。
しかし、それぞれのコピーを異なるものにする必要がある場合はどうすればよいでしょうか?例えば、1つの8ビットカウンタ、1つの16ビットカウンタ、そして1つの32ビットカウンタといった具合です。パラメータがない場合、3つの別々のモジュールを記述する必要があります。
パラメータがこの問題を解決します。
パラメータは、インスタンスを作成するときに設定できる定数値です。これによって、モジュールの各コピーを個別に構成できます。
パラメータの宣言
module counter #(
parameter WIDTH = 8
)(
input clk,
output reg [WIDTH-1:0] count
);
always @(posedge clk) count <= count + 1;
endmodule#(parameter WIDTH = 8) は、デフォルト値が8の WIDTH という名前のパラメータを定義します。
パラメータを宣言する際、# 記号をモジュール名の直後かつポートリストの前に使用します。# は、その後に続くものがモジュールを構成するパラメータのリストであることを Verilog に伝えます。モジュールにパラメータがない場合は、単に # を完全に省略します。
パラメータの使用
パラメータは、定数が必要な場所であればどこでも使用できます:
reg [WIDTH-1:0] data; // ベクタサイズ
count <= count + 1; // 任意の幅で動作
assign out = data[WIDTH-1]; // MSBの位置パラメータのオーバーライド
モジュールを使用する際、パラメータの値を変更することができます:
// デフォルトの幅 (8ビット)
counter u1 (.clk(clk), .reset(reset), .count(count1));
// 16ビットにオーバーライド
counter #(.WIDTH(16)) u2 (.clk(clk), .reset(reset), .count(count2));複数のパラメータ
複数のパラメータを持つことができます:
module fifo #(
parameter DEPTH = 16,
parameter WIDTH = 8
)(
input clk, wr_en, rd_en,
input [WIDTH-1:0] data_in,
output [WIDTH-1:0] data_out
);
reg [WIDTH-1:0] memory [0:DEPTH-1];
endmoduleLocalparam
localparam は似ていますが、外部から上書きすることはできません:
module example;
localparam STATE_IDLE = 2'b00;
localparam STATE_RUN = 2'b01;
localparam STATE_STOP = 2'b10;
// これらの値はこのモジュール内で固定されています
endmodule変更すべきでない定数には localparam を使用します。
チャレンジ
デフォルト値が 4 の WIDTH という名前のパラメータを追加してください。
手順:
WIDTHという名前のパラメータを追加する- そのデフォルト値を
4に設定する - パラメータはモジュール名の後の
#( )内に記述する
チートシート
パラメータを使用すると、コードを書き換えることなく、モジュールインスタンスを異なる設定に構成できます。
パラメータの宣言
module counter #(
parameter WIDTH = 8 // default value
)(
input clk,
output reg [WIDTH-1:0] count
);
always @(posedge clk) count <= count + 1;
endmoduleインスタンス化におけるパラメータの上書き
counter u1 (.clk(clk), .count(count1)); // uses default (8)
counter #(.WIDTH(16)) u2 (.clk(clk), .count(count2)); // overridden to 16複数のパラメータ
module fifo #(
parameter DEPTH = 16,
parameter WIDTH = 8
)( ... );Localparam (上書き不可能な定数)
localparam STATE_IDLE = 2'b00;
localparam STATE_RUN = 2'b01;モジュールの外部から変更してはならない内部定数には、localparamを使用します。
自分で試してみよう
module counter #(
// ここにデフォルト値4のパラメータWIDTHを追加してください
)(
input clk,
input reset,
output reg [WIDTH-1:0] count
);
endmoduleこのレッスンには短いクイズがあります。レッスンを始めて解答し、進捗を記録しましょう。