Verilog-HDL基礎
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
|
ログイン
]
開始行:
[[論理回路設計]]
*Verilog-HDL基礎 [#ma82e33a]
Verilog-HDLを用いた回路記述方法の基礎知識をまとめます。
----
#contents
**設定方法 [#c96d72fd]
Verilog-HDLを使って回路を設計するためには、まずは環境を整える必要があります。~
会津大学ワークステーション向けの設定方法を[[論理回路設計環境の設定]]にまとめました。
**テストベンチの記述方法 [#q9235777]
Verilog-HDL記述で設計した回路をシミュレーションするためには、テストベンチを用意する必要があります。~
ここでは、テストベンチの基本的な書き方をまとめます。
***テストベンチの基本構成 [#dfc25e62]
// 時間の単位と精度 (おまじないだと思ってください)
`timescale 1ns / 1ns
// テストするモジュールのインクルード
`include ...
module testbench;
// テストするモジュールの入力ポートをregとして宣言
reg ...
// テストするモジュールの出力ポートをwireとして宣言
wire ...
// テストするモジュールの宣言
...
// 入力するテストデータを指定
initial begin
...
...
$finish;
end
endmodule
***テストベンチで使う機能 [#ofe931d6]
-#[進める時間]
--指定した分だけ時間を進めます。~
記述例:
a = 1; b = 0;
#100
a = 0; b = 0;
-$display
--信号を表示するシステムタスクです。printfみたいなものだと思ってください。~
記述例:
$display("a = %b, b = %b, out = %b", a, b, out);
-$monitor
--$displayと同様に信号を表示するシステムタスクです。~
$displayと異なる点は、引数で指定した信号に変化があった場合に値を出力します。$display文のように複数並べて書く必要がないので便利です。~
記述例:
$monitor("a = %b, b = %b, out = %b", a, b, out);
-$finish
--シミュレーションを終了します。
-$dumpfile
--波形ファイルを生成する。~
記述例:
$dumpfile("testbench.vcd");
-$dumpvars
--出力する波形の開始時間とモジュール名を指定する。~
記述例:
$dumpvars(0, testbench);
***組み合わせ回路のテストベンチ [#vc811509]
全加算器を例にしたテストベンチを紹介します。
initial begin〜endには入力するテストデータと結果の表示部分を記述します。~
流れとしては、
+入力するテストデータを記述
+時間を進める
+$displayで結果を表示
を繰り返し記述していきます。
$monitorを使えば、引数に渡した信号線が変化したときに結果を表示してくれるので、~
$displayを何度も記述する方法と比べると、すっきりした記述ができます。
-displayを用いたテストベンチ
`timescale 1ns / 1ns
`include "./fa.v"
module fa_tb;
reg ina, inb, carry_in; // Input (regとして宣言)
wire carry_out, sout; // Output (wireとして宣言)
// テストするモジュール
fa fa1 (
// Outputs
.sout (sout),
.carry_out (carry_out),
// Inputs
.ina (ina),
.inb (inb),
.carry_in (carry_in)
);
// 入力するテストデータを指定
initial begin
ina = 1'b0; inb = 1'b0; carry_in = 1'b0;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
ina = 1'b0; inb = 1'b0; carry_in = 1'b1;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
/* 省略 */
ina = 1'b1; inb = 1'b1; carry_in = 1'b1;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
$finish;
end
endmodule // fa_tb
-monitorを用いたテストベンチ
`timescale 1ns / 1ns
`include "./fa.v"
module fa_tb;
reg ina, inb, carry_in; // Input (regとして宣言)
wire carry_out, sout; // Output (wireとして宣言)
// テストするモジュール
fa fa1 (
// Outputs
.sout (sout),
.carry_out (carry_out),
// Inputs
.ina (ina),
.inb (inb),
.carry_in (carry_in)
);
// 入力するテストデータを指定
initial begin
$monitor("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
ina = 1'b0; inb = 1'b0; carry_in = 1'b0;
#100 ina = 1'b0; inb = 1'b0; carry_in = 1'b1;
#100 ina = 1'b0; inb = 1'b1; carry_in = 1'b0;
#100 ina = 1'b0; inb = 1'b1; carry_in = 1'b1;
#100 ina = 1'b1; inb = 1'b0; carry_in = 1'b0;
#100 ina = 1'b1; inb = 1'b0; carry_in = 1'b1;
#100 ina = 1'b1; inb = 1'b1; carry_in = 1'b0;
#100 ina = 1'b1; inb = 1'b1; carry_in = 1'b1;
#100
$finish;
end
endmodule // fa_tb
***順序回路のテストベンチ [#j3e63566]
組み合わせ回路と大きく異なる部分は、クロック(clk)とリセット(rst)を扱う必要があることです。~
クロックは一定の時間ごとに1と0の状態を繰り返しているので、alwaysを用いて記述することができます。
always #[周期] clk = ~clk
のように記述することで、ある一定の周期ごとに反転する動作を繰り返します。~
このときのクロックサイクルは周期の2倍になります。
リセット信号は1クロックサイクル分だけイネーブル状態にしてやることで、回路の初期化を行うことができます。
あとは、1クロックサイクルの時間を進めながら、出力の変化を表示させることで、回路の動作を見ることができます。~
$monitorを使う際には、出力が変化しないと表示されない場合があるので注意してください。
-displayを用いたテストベンチ
`timescale 1ns / 1ns
`include "./counter.v"
module counter_tb;
reg clk, rst;
wire [3:0] value;
counter counter1 (
// Outputs
.value (value),
// Inputs
.clk (clk),
.rst (rst)
);
initial begin
clk = 1'b0;
rst = 1'b1;
$display("rst:%b value:%x", rst, value);
#100
rst = 1'b0;
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$finish;
end
always #50 clk = ~clk;
endmodule // counter_tb
-monitorを用いたテストベンチ
`timescale 1ns / 1ns
`include "./counter.v"
module counter_tb;
reg clk, rst;
wire [3:0] value;
counter counter1 (
// Outputs
.value (value),
// Inputs
.clk (clk),
.rst (rst)
);
initial begin
$monitor("rst:%b value:%x time:%t", rst, value, $time);
clk = 1'b0;
rst = 1'b1;
#100
rst = 1'b0;
#400
$finish;
end
always #50 clk = ~clk;
endmodule // counter_tb
***波形ファイルの生成 [#e0893083]
波形ファイルを生成するためには、dumpfileとdumpvarsというシステムタスクを使用します。
-記述例
`timescale 1ns / 1ns
`include ...
module testbench;
reg ...
wire ...
...
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
...
...
$finish;
end
endmodule
終了行:
[[論理回路設計]]
*Verilog-HDL基礎 [#ma82e33a]
Verilog-HDLを用いた回路記述方法の基礎知識をまとめます。
----
#contents
**設定方法 [#c96d72fd]
Verilog-HDLを使って回路を設計するためには、まずは環境を整える必要があります。~
会津大学ワークステーション向けの設定方法を[[論理回路設計環境の設定]]にまとめました。
**テストベンチの記述方法 [#q9235777]
Verilog-HDL記述で設計した回路をシミュレーションするためには、テストベンチを用意する必要があります。~
ここでは、テストベンチの基本的な書き方をまとめます。
***テストベンチの基本構成 [#dfc25e62]
// 時間の単位と精度 (おまじないだと思ってください)
`timescale 1ns / 1ns
// テストするモジュールのインクルード
`include ...
module testbench;
// テストするモジュールの入力ポートをregとして宣言
reg ...
// テストするモジュールの出力ポートをwireとして宣言
wire ...
// テストするモジュールの宣言
...
// 入力するテストデータを指定
initial begin
...
...
$finish;
end
endmodule
***テストベンチで使う機能 [#ofe931d6]
-#[進める時間]
--指定した分だけ時間を進めます。~
記述例:
a = 1; b = 0;
#100
a = 0; b = 0;
-$display
--信号を表示するシステムタスクです。printfみたいなものだと思ってください。~
記述例:
$display("a = %b, b = %b, out = %b", a, b, out);
-$monitor
--$displayと同様に信号を表示するシステムタスクです。~
$displayと異なる点は、引数で指定した信号に変化があった場合に値を出力します。$display文のように複数並べて書く必要がないので便利です。~
記述例:
$monitor("a = %b, b = %b, out = %b", a, b, out);
-$finish
--シミュレーションを終了します。
-$dumpfile
--波形ファイルを生成する。~
記述例:
$dumpfile("testbench.vcd");
-$dumpvars
--出力する波形の開始時間とモジュール名を指定する。~
記述例:
$dumpvars(0, testbench);
***組み合わせ回路のテストベンチ [#vc811509]
全加算器を例にしたテストベンチを紹介します。
initial begin〜endには入力するテストデータと結果の表示部分を記述します。~
流れとしては、
+入力するテストデータを記述
+時間を進める
+$displayで結果を表示
を繰り返し記述していきます。
$monitorを使えば、引数に渡した信号線が変化したときに結果を表示してくれるので、~
$displayを何度も記述する方法と比べると、すっきりした記述ができます。
-displayを用いたテストベンチ
`timescale 1ns / 1ns
`include "./fa.v"
module fa_tb;
reg ina, inb, carry_in; // Input (regとして宣言)
wire carry_out, sout; // Output (wireとして宣言)
// テストするモジュール
fa fa1 (
// Outputs
.sout (sout),
.carry_out (carry_out),
// Inputs
.ina (ina),
.inb (inb),
.carry_in (carry_in)
);
// 入力するテストデータを指定
initial begin
ina = 1'b0; inb = 1'b0; carry_in = 1'b0;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
ina = 1'b0; inb = 1'b0; carry_in = 1'b1;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
/* 省略 */
ina = 1'b1; inb = 1'b1; carry_in = 1'b1;
#100
$display("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
$finish;
end
endmodule // fa_tb
-monitorを用いたテストベンチ
`timescale 1ns / 1ns
`include "./fa.v"
module fa_tb;
reg ina, inb, carry_in; // Input (regとして宣言)
wire carry_out, sout; // Output (wireとして宣言)
// テストするモジュール
fa fa1 (
// Outputs
.sout (sout),
.carry_out (carry_out),
// Inputs
.ina (ina),
.inb (inb),
.carry_in (carry_in)
);
// 入力するテストデータを指定
initial begin
$monitor("ina:%b inb:%b carry_in:%b sout:%b carry_out:%b", ina, inb, carry_in, sout, carry_out);
ina = 1'b0; inb = 1'b0; carry_in = 1'b0;
#100 ina = 1'b0; inb = 1'b0; carry_in = 1'b1;
#100 ina = 1'b0; inb = 1'b1; carry_in = 1'b0;
#100 ina = 1'b0; inb = 1'b1; carry_in = 1'b1;
#100 ina = 1'b1; inb = 1'b0; carry_in = 1'b0;
#100 ina = 1'b1; inb = 1'b0; carry_in = 1'b1;
#100 ina = 1'b1; inb = 1'b1; carry_in = 1'b0;
#100 ina = 1'b1; inb = 1'b1; carry_in = 1'b1;
#100
$finish;
end
endmodule // fa_tb
***順序回路のテストベンチ [#j3e63566]
組み合わせ回路と大きく異なる部分は、クロック(clk)とリセット(rst)を扱う必要があることです。~
クロックは一定の時間ごとに1と0の状態を繰り返しているので、alwaysを用いて記述することができます。
always #[周期] clk = ~clk
のように記述することで、ある一定の周期ごとに反転する動作を繰り返します。~
このときのクロックサイクルは周期の2倍になります。
リセット信号は1クロックサイクル分だけイネーブル状態にしてやることで、回路の初期化を行うことができます。
あとは、1クロックサイクルの時間を進めながら、出力の変化を表示させることで、回路の動作を見ることができます。~
$monitorを使う際には、出力が変化しないと表示されない場合があるので注意してください。
-displayを用いたテストベンチ
`timescale 1ns / 1ns
`include "./counter.v"
module counter_tb;
reg clk, rst;
wire [3:0] value;
counter counter1 (
// Outputs
.value (value),
// Inputs
.clk (clk),
.rst (rst)
);
initial begin
clk = 1'b0;
rst = 1'b1;
$display("rst:%b value:%x", rst, value);
#100
rst = 1'b0;
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$display("rst:%b value:%x", rst, value);
#100
$finish;
end
always #50 clk = ~clk;
endmodule // counter_tb
-monitorを用いたテストベンチ
`timescale 1ns / 1ns
`include "./counter.v"
module counter_tb;
reg clk, rst;
wire [3:0] value;
counter counter1 (
// Outputs
.value (value),
// Inputs
.clk (clk),
.rst (rst)
);
initial begin
$monitor("rst:%b value:%x time:%t", rst, value, $time);
clk = 1'b0;
rst = 1'b1;
#100
rst = 1'b0;
#400
$finish;
end
always #50 clk = ~clk;
endmodule // counter_tb
***波形ファイルの生成 [#e0893083]
波形ファイルを生成するためには、dumpfileとdumpvarsというシステムタスクを使用します。
-記述例
`timescale 1ns / 1ns
`include ...
module testbench;
reg ...
wire ...
...
initial begin
$dumpfile("testbench.vcd");
$dumpvars(0, testbench);
...
...
$finish;
end
endmodule
ページ名: