Verilog チートシート
最終更新
モジュール構造とポート
モジュールは基本的な構成要素で、名前とポートリストを持ちます。
| 構文 | 意味 |
|---|---|
module adder(...); ... endmodule | モジュールとその本体を定義 |
input clk; | 入力ポート |
output q; | 出力ポート |
output reg q; | always ブロックから駆動される出力 |
input [7:0] data; | 8 ビットの入力バス (ベクトル) |
inout sda; | 双方向ポート |
adder u1 (.a(x), .b(y), .sum(s)); | 名前付きポートでモジュールをインスタンス化 |
データ型
wire は接続を表し、reg は手続き的なコードが代入する値を保持します。
| 要素 | 機能 |
|---|---|
wire w; | assign またはモジュール出力で駆動されるネット |
reg r; | always/initial ブロック内で代入された値を保持 |
wire [3:0] bus; | 4 ビットのベクトル (ビット 3 から 0 まで) |
reg [7:0] count; | 8 ビットのレジスタ |
bus[2] | 1 ビットを選択 |
bus[3:1] | ビットのスライスを選択 (部分選択) |
reg mem [0:255]; | メモリ: レジスタの配列 |
parameter WIDTH = 8; | モジュール用の名前付き定数 |
数値リテラル
形式は <size>'<base><value> で、size はビット数、base は b/o/d/h です。
| 構文 | 意味 |
|---|---|
4'b1010 | 4 ビットの 2 進数、値は 10 |
8'hFF | 8 ビットの 16 進数、値は 255 |
8'hff | 同じ。16 進の数字は大文字小文字を区別しない |
16'd255 | 16 ビットの 10 進数、値は 255 |
3'o7 | 3 ビットの 8 進数、値は 7 |
8'b1010_1100 | アンダースコアは読みやすさのため桁を区切る |
1'bx | 不定 (x) のビット値 |
1'bz | ハイインピーダンス (z) のビット値 |
演算子
ビット、論理、比較、リダクションの演算子。
| 演算子 | 機能 |
|---|---|
& | ^ ~ | ビット単位の AND、OR、XOR、NOT |
&& || ! | 論理 AND、OR、NOT (1 ビットを返す) |
== != < > <= >= | 比較演算子 |
<< >> | 左シフトと右シフト |
+ - * / % | 算術演算子 |
&bus | リダクション AND (全ビットの AND) |
|bus | リダクション OR (全ビットの OR) |
^bus | リダクション XOR (全ビットのパリティ) |
{a, b} | 連結。{4{1'b1}} は 4'b1111 に複製する |
継続的代入
assign は wire を継続的に駆動します。組み合わせ論理に使います。
| 構文 | 意味 |
|---|---|
assign y = a & b; | a と b の AND で y を駆動 |
assign sum = a + b; | 和を継続的に計算 |
assign y = sel ? a : b; | 三項演算子。2 対 1 のマルチプレクサ |
assign {c, s} = a + b; | 桁上げと和をまとめて取得 |
assign y = ~en; | 反転した信号から wire を駆動 |
手続きブロック
always と initial は文を実行し、感度リストが実行のタイミングを制御します。
| 構文 | 意味 |
|---|---|
always @(*) begin ... end | 組み合わせ論理 (どの入力が変化しても) |
always @(posedge clk) | クロックの立ち上がりごとに実行 (順序論理) |
always @(negedge clk) | クロックの立ち下がりごとに実行 |
always @(posedge clk or posedge rst) | 非同期リセット付きのクロックブロック |
initial begin ... end | 時刻 0 で 1 度だけ実行 (テストベンチ、シミュレーション専用) |
begin ... end | 複数の文をまとめる |
#10 | 10 時間単位の遅延 (シミュレーション専用) |
ブロッキングと非ブロッキング
組み合わせ論理には =、クロック同期の順序論理には <= を使います。
| 構文 | 意味 |
|---|---|
a = b; | ブロッキング。順番どおりに即座に実行 |
a <= b; | 非ブロッキング。右辺をすべて先に読み、その後で代入 |
always @(*) y = a & b; | 組み合わせ: ブロッキング = を使う |
always @(posedge clk) q <= d; | フリップフロップ: 非ブロッキング <= を使う |
1 つのブロックで = と <= を混在 | 避けること。バグのよくある原因 |
制御フロー
手続きブロック内の条件分岐と多方向分岐。
| 構文 | 意味 |
|---|---|
if (cond) ... else ... | 条件文 |
if (a) x = 1; else x = 0; | 一行の if/else |
case (sel) ... endcase | 値による多方向分岐 |
2'b00: y = a; | case の項目 |
default: y = 0; | フォールバックの case 項目 |
for (i = 0; i < 8; i = i + 1) | ループ (多くは generate やシミュレーション内) |
repeat (4) @(posedge clk); | 文を N 回繰り返す |
よく使うパターン
繰り返し書く構成要素と、テストベンチ用のタスク。
| パターン | 構文 |
|---|---|
| D フリップフロップ | always @(posedge clk) q <= d; |
| リセット付きレジスタ | always @(posedge clk) if (rst) q <= 0; else q <= d; |
| カウンタ | always @(posedge clk) count <= count + 1; |
| FSM の状態レジスタ | always @(posedge clk) state <= next_state; |
| FSM の次状態論理 | always @(*) case (state) ... endcase |
| 値を表示 | $display("q = %b", q); |
| 変化時に表示 | $monitor("t=%0t q=%b", $time, q); |
| シミュレーションを終了 | $finish; |
よく使う Verilog の構文を 1 ページにまとめました。この Verilog チートシートは、このハードウェア記述言語のクイックリファレンスです。モジュールとポートの宣言、データ型の選択、組み合わせ論理と順序論理の記述、そして実際の回路を表す always ブロックのパターンを収録しています。
ここで紹介する構文は標準の Verilog (IEEE 1364) で、Icarus Verilog や Verilator のような一般的なシミュレータで動作します。必要なものをコピーするか、Verilog プレイグラウンドでその場で試してみてください。モジュールを書いてシミュレートし、出力をブラウザで確認できます。
Verilog チートシート よくある質問
この Verilog チートシートは無料ですか?
wire と reg の違いは何ですか?
wire は物理的な接続を表し、assign 文かモジュール出力によって継続的に駆動される必要があるので、組み合わせのネットに使います。reg は手続き的なコードが変えるまで値を保持するので、always や initial ブロック内で代入されるものに使います。名前に反して、reg が常にハードウェアのレジスタになるわけではなく、値が手続き的に設定されることを意味するだけです。ブロッキング代入と非ブロッキング代入の違いは何ですか?
=) は通常のプログラミング文のように即座に順番どおり実行されるので、always @(*) ブロックの組み合わせ論理に使います。非ブロッキング代入 (<=) はまず右辺をすべて評価し、その後で左辺をまとめて更新するため、フリップフロップを正しく表します。だからクロック同期の always @(posedge clk) ブロックで使います。1 つのブロックで両者を混在させるのは、シミュレーションのバグの典型的な原因です。