#Verilog初心者の私が躓いたポイントと解決した手段について
大学の講義にてVerilogに触れる機会がありましたので、初心者のうちによく躓いたポイントと私なりの解決方法を列挙します。
##モジュール名,レジスタ名などのタイプミス
VSCodeのVerilogHDLやVerilog HDL/SystemVerilogといった拡張機能を使うと、ある程度タイプミスは減らせると思います。補完がめちゃくちゃ強力なわけではないのである程度自分で補完を書いてみるのがいいかもしれません。
##ブロックの指定がbegin/end
現在よく使用される高級言語の多くは{ }を使ってブロックを指定しますがVerilogはbegin/endを使ってブロックを指定します。その為if begin end else begin end・・・の様なコードとなってしまいます。初めて扱うと少し冗長な表現に見え、またbeginとendの対応が分かりずらくなってしまいます。そのため次のように書くと比較的対応が分かりやすいかと思います。
while(---) begin
if (---) begin
---;
end
else if (---) begin
---;
end
else begin
---;
end
end
##データのビット幅指定
Verilogのデータはwire型(ワイヤ)とreg型(レジスタ)にがあります(wireとregの違いについては別の記事で)。これらを使用する際、wire <変数名>;のように宣言すると1ビットのワイヤとして扱われます。多ビットのワイヤもしくはレジスタとして扱いたい場合はwire [3:0] <変数名>のように宣言する必要があります。この場合だと3~0ビットが用意されるため4ビットのワイヤが宣言されます。
また[3:0]と[0:3]はレジスタの取得時に明確な違いが発生しますから、よっぽどのことがなければどちらかに統一しましょう。1
module sample
(
input CLK,
output reg [7:0] LED_DEC
);
wire sample;
wire [3:0] mult;
endmodule //sample
##module, function内のビット幅指定
moduleやfunctionは再利用できる一つのモジュールとして定義されます。上位モジュールと信号線を接続するためにinputとoutputの記述を必要とします。その記述内でもビット幅指定を必要とするので注意してください。sample2.vの( )内のようにビット幅を指定しながらinputかoutputかを指定する必要があります。またoutputはwireかregかを選択できるのでなるべく明示的に宣言しておきましょう。
##alwaysの中で書き換えるのは1つの変数のみ
一般のプログラミング言語的にalways文で順序回路を書こうとすると、1つのalways内で複数の変数を書き換えたくなるかと思います。しかし、Verilogでは複数の入力⇔複数の出力と対応させてしまうと、中身が分かりづらくなり予期せぬ動作・エラーが発生してしまう可能性があります。
1つのalwaysで1つの出力を作り出すように記述することで変数の対応が分かりやすくなります。
##レジスタの初期化
回路記述を行っている際、initialでレジスタを初期化することはできません。書くならばレジスタを宣言した際に初期値として値を設定しましょう。しかし、初期値を使うのはあまり良いことではない(らしいソースは教員)のであまり使用しないようにしましょう。
reg foo;
reg bar = 1'b0; // どうしても初期化したいならこの方法を使う
init begin
foo = 1'b0; //initで初期化することはできない
end
参考文献
-
cf.リトルエンディアン・ビックエンディアン
https://qiita.com/kaizen_nagoya/items/4c02f1575db1f28310a7 ↩