verilog~module内パラメーターの階層間受け渡し

こんにちは、お久しぶりです。Keymaleです。
今回は verilogのパラメータについて説明します。
以前の記事で説明したDividerを例にして進めようと思います。以下に以前紹介したdividerのプログラムを紹介します。


module divider(
input  div_in,
output div_out
);

reg [7:0]div_number;
reg [7:0]cnt_p;
reg [7:0]cnt_n;
reg out_p;
reg out_n;
assign div_out = out_p ^ out_n;

initial begin
    div_number = 8'd3;
    cnt_p      = 8'd1;
    cnt_n      = 8'd1;
    out_p      = 0;
    out_n      = 0;
end

always@(posedge div_in)begin
    cnt_p <= cnt_n + 8'd1;
    if(cnt_n == div_number)begin
        cnt_p <= 8'd1;
        out_p <= ~out_p;
    end
end

always@(negedge div_in)begin
    cnt_n <= cnt_p + 8'd1;
    if(cnt_p == div_number)begin
        cnt_n <= 8'd1;
        out_n <= ~out_n;
   end
end

endmodule

この中でdiv_numberをregで記述していますが、いろんな値に変えたいと思うとします。その時に、regのままでもいいのですが、わかりやすくするために

parameter div_number

と記述することができます。parameterは32bitのintで扱われます。
このままだったら別にparameterの良さがわからないと思います。
parameterの真価を発揮するのはmodule化した時です。module化した際に様々なdiv_numberのdividerを作りたくなった時には、上位階層から下位階層であるdividerのparameterをいじることができるのですが、少し工夫が必要です。
まず以下のようにparameterを記述する位置を変更しましょう。


module divider #(
paramter div_number = 5,
paramter div_test   = 1
)
(
input  div_in,
output div_out
);

reg [7:0]cnt_p;
reg [7:0]cnt_n;
reg out_p;
reg out_n;
assign div_out = out_p ^ out_n;

initial begin
    cnt_p      = 8'd1;
    cnt_n      = 8'd1;
    out_p      = 0;
    out_n      = 0;
end

always@(posedge div_in)begin
    cnt_p <= cnt_n + 8'd1;
    if(cnt_n == div_number)begin
        cnt_p <= 8'd1;
        out_p <= ~out_p;
    end
end

always@(negedge div_in)begin
    cnt_n <= cnt_p + 8'd1;
    if(cnt_p == div_number)begin
        cnt_n <= 8'd1;
        out_n <= ~out_n;
   end
end

endmodule

変化した場所はわかりましたか?moduleと宣言した後に変化場所があります。
今までは


module module名(
input input名,
output output名
);

として、このmodule宣言後のかっこで囲われた中でinput outputを宣言し、上位階層のmoduleとの信号の受け渡し部分になっていましたが、ここにさらにparameterの受け渡し部分を


module module名 #(
parameter paramter名
)(
input input名,
output output名
);

inputやoutput宣言の前にmodule名の後に#をつけてかっこ内にparameterを宣言することで、上位モジュールからここで宣言したparameterを操作することができます。また、上位モジュールで下位モジュールのparamterをいじらないときは、下位モジュールで宣言したparameter値が読み込まれるので、どっちにしろparameterの宣言はこの場所にしておいてよさそうです。何より、parameterをいろんなところで宣言するとわかりにくいので、module宣言の後に宣言すると決めておくといいでしょう。他にもdefparamで行う方法もあるようですが、私はこの方法を推奨します。
上位moduleからこのmoduleを呼び出すときは以下のように記述します。


divider #(
    .div_number (8),
    .div_test	(0)
)divider1(
    .div_in	(clk),
    .div_out	()
);

上記のようになります。一般的に書くと以下のようになります。


モジュール名 #(
    .モジュール内でのパラメータ名 (パラメータ値)
)呼び出し階層でのモジュール名(
    .モジュール内での信号名	(信号値)
);

パラメータ値には直接数字を入れてもいいですし、変数でも問題ないです。
以上でパラメータの階層間での受け渡しの説明を終わりにします。
最後まで見ていただいてありがとうございますした。
次回はfor文とgenerate文について説明したいと思います。