本記事では加算器を例としてVerilogでのモジュールの書き方について説明する.
モジュールの記述
この記事では次の加算器のモジュールを例にして説明していく.
加算器は2進数の入力信号を足し合わせ,結果を出力する.
入力信号のbit数はパラメータにして変更できるようにしている.
module adder #(
parameter bit_p = 32
) (
input clk_i,
input reset_i,
input [bit_p-1:0] a_i,
input [bit_p-1:0] b_i,
output [bit_p-1:0] z_o
);
reg [bit_p-1:0] z_r;
assign z_o = z_r;
always @(posedge clk_i) begin
if (~reset_i)
z_r <= a_i + b_i;
else
z_r <= 0;
end
endmodule
入出力ポートの宣言
まず,モジュールの宣言をし入出力ポートの宣言を行う.
#マークつきの()内にはビット数など入出力ポートの宣言に必要なパラメータを宣言することができる.
module adder #( parameter bit_p = 32 ) ( input clk_i, input reset_i, input [bit_p-1:0] a_i, input [bit_p-1:0] b_i, output [bit_p-1:0] z_o );
多ビット信号のときは,並びが2進数の向きと同じになる[MSB:LSB]の形で宣言するのが一般的である.
もちろん,[LSB:MSB]でも宣言は可能だ.
また,a_i[2]
のようにして信号のあるビット信号を記述できる.
ワイヤ・レジスタの宣言と接続記述
次に必要なワイヤとレジスタの宣言を行う.
今回の例ではレジスタのみだが,ワイヤの例も合わせておく.
wire [bit_p-1:0] z; reg [bit_p-1:0] z_r;
Verilogではwire型とreg型がある.
入出力ポートはワイヤとして扱う.
- wire : ただのワイヤー,名前の付いた金属配線をイメージ
- reg : レジスタ,より具体的にはフリップフロップ
ワイヤやレジスタを接続するときにassignを用いる.
assignは配線を繋ぐイメージで使用すれば良い.
assign z_o = z_r;
クロック同期の記述
多くのディジタル回路はクロックに同期して動作する.
次のようにalways文の中にクロック同期の処理を記述できる.
always @(posedge clk_i) begin
// process
end
always @(negedge clk_i) begin
// process
end
always @(posedge clk_i or negedge clk_i) begin
// process
end
ブロックの記述
begin end
はC言語でいう{}
に対応し,ブロックの記述に用いる.begin end
内の論理が1行で記述できる場合はbegin end
は省略可能である
always文内の記述
次のコードはクロック同期の論理を記述している.
ifやcaseによって条件分岐ができるのはC言語のような通常のプログラムと同様である.
always @(posedge clk_i) begin
if (~reset_i)
z_r <= a_i + b_i;
else
z_r <= 0;
end
always内ではレジスタに値を代入し,クロックの立ち上がりまたは立ち下りの後の値を決める.
always内での代入には記号<=
を用いて代入する.
これはノンブロッキング代入といい,通常のブロッキング代入と違ってコードにおける順序に左右されない代入のことである.
ノンブロッキング代入とブロッキング代入の詳しい説明については次 ↓
ここで注意したいのはワイヤに値は代入できないことだ.
ワイヤはただの配線金属で数値ではないからである.
では,次のコード(加算器のサンプルコード上部)はどうか
assign z_o = z_r;
一見,配線に値を代入しているようにも思える.
しかし,assignが配線を接続するイメージで捉えれば,z_rというレジスタの出力とz_oというワイヤを配線していると解釈できる(次の図).
よって,上記のコードは正しいことになり,回路的にはレジスタの出力が駆動側(信号源)として配線の電圧を変化させるということになる.
まとめ
本記事では加算器を例としてVerilogでのモジュールの書き方について書いた.
wireは配線導体,regはレジスタ(フリップフロップ),assignは配線接続のイメージで実際の回路を想像しながら書けるようになると良い.
モジュールを作成した後は,本当に自分が意図した動作になっているか検証を行うテストベンチを作成する必要がある.
次の記事ではテストベンチの書き方について説明する.
次の記事 ↓↓↓
コメント