multiplexer_16.v
multiplexer_16.vのコードは前ページのmultiplexer_8.vのコードとほとんど同じです。異なる点は入出力端子のビットサイズが16ビットになっているところだけです。
module multiplexer_16(mux_s, mux_in_a, mux_in_b, mux_out);
input mux_s;
input [15:0] mux_in_a;
input [15:0] mux_in_b;
output [15:0] mux_out;
assign mux_out = (mux_s == 1'b0) ? mux_in_a : mux_in_b;
endmodule
register_8.v
register_8.vのコードも短いコードですがVerilog HDLでの新しい文法がいくつか出てきます。最も重要なのはマルチプレクサ回路には出てこなかった記憶回路が含まれている点です。記憶回路、すなわちフリップフロップやレジスタの要素が回路の中に含まれる場合はVerilog HDLではassign文の代わりにalways文を使います。
module register_8(reg_e, rst, reg_in, reg_out);
input reg_e;
input rst;
input [7:0] reg_in;
output [7:0] reg_out;
reg [7:0] reg_out;
always @(posedge reg_e or negedge rst) begin
if(rst == 1'b0)
reg_out <= 8'b00000000;
else
reg_out <= reg_in;
end
endmodule
上記の回路は”reg_e”という名前のクロック入力端子が「0」から「1」に立ち上がった瞬間の入力端子”reg_in”の値を、”reg_out”という名前の8ビットレジスタに記憶する、という内容のものです。また、追加機能として”rst”というリセット入力端子が「0」の時に記憶内容が0にリセットされるという機能も持っています。
まずreg文についてですが、reg文は記憶機能を持ったフリップフロップやレジスタを定義するときに使用される文法で、文法的にはinput文、output文、wire文とよく似ています。(複数ビットの定義の仕方もinput文などと全く同じ。)1ビットの定義ならフリップフロップ、複数ビットならレジスタが作られるということになります。
reg文には1つ特殊な使い方があります。それはoutput文で定義した出力端子と同じ名前で記憶回路を定義するという使い方です。この使い方は非常によく出てくる使い方です。reg文で作ったレジスタやフリップフロップ回路に独自の名前を定義した場合それらの回路は独立した記憶回路として生成されますが、output文で定義した出力端子と同じ名前でreg文を定義した場合、そこで生成された記憶回路と出力端子は一体化して記憶機能を持った出力端子として生成されます。
reg文で生成されたレジスタや出力端子はassign文の左辺には使えなくなります。reg文で生成されたレジスタや出力端子に何らかの信号を接続して値を記憶する場合には必ずalways文を使用しなければならないというルールがあります。always文の後に続く”begin”から”end”で囲われた範囲の中でだけ記憶回路への代入が可能です。
スポンサーリンク
always文の中にある”<=”の記述は代入を表しています。ただし条件式として”<=”の記述が使用されることもあり、この場合は数学式と同様で”小なりイコール”の意味になります。
精確に言うとalways文の中で使用できる代入文には”<=”の記述を用いるものと、”=”の記述を用いるものがあります。”<=”は「ノンブロッキング代入」と呼ばれ、”=”は「ブロッキング代入」と呼ばれます。(assign文の中の”=”は全くの別物です。)両者には機能的にも違いがあるのですが、私の個人的な考えとしてはVerilog HDLの入門段階では”=”の「ブロッキング代入」は使わなくても良いのではないかと思っています。とりあえずはノンブロッキング代入だけでも回路の記述は可能ですので、このサイトではalways文の中で使用する代入文は”<=”の「ノンブロッキング代入」で統一したいと思います。
always文のアットマークに続く括弧の中には入力信号を記述します。この括弧の中に記述された信号に変化があるとalways文以下の内容が実行されます。入力信号は複数指定することができ、その場合は各信号名を”or”で区切って記述します。実行のきっかけとなる入力信号には信号名の前に”posedge”と指定することで、信号の立上りの変化が起きた時だけalways文を実行することができます。逆に信号の立ち下がりの時にだけ実行したい場合には”negedge”と指定します。
always文の中にあるif文は特定の条件が成り立った時にだけ実行する処理を記述するのに使われます。if文に続く括弧の中には条件式が記述され、この条件式が成り立つ時は”if”から”else”の間に記述された処理が実行されます。逆に条件式が成り立たない時には”else”から後の文が実行されます。
if文に続く括弧の中の”==”の記述は条件式としての”イコール”を意味する記述です。
今回のコードの場合は”reg_e”というクロック入力信号の立ち上がりの瞬間と、”rst”というリセット信号の立ち下がりの瞬間にalways文の中が実行され、実行時に”rst”というリセット信号が「0」の場合には”reg_out”というレジスタ兼出力端子に0が記憶され、逆に”rst”というリセット信号が「0」ではない場合(すなわち”reg_e”の立ち上がりでalways文が実行された場合)には”reg_out”というレジスタ兼出力端子に”reg_in”の内容が記憶される。という内容になります。簡単に言いますとクロック信号の立上りで入力信号が記憶される、リセット機能付きのレジスタです。
(”if”から”else”の間の処理や”else”の後の処理が複数行にわたって記述される場合はそれぞれの処理を”begin”と”end”で囲います。1行で記述できる場合は”begin”と”end”は省略できます。)
<戻る 次へ>