搭建 Verilog 仿真环境
对于 Verilog 的初学者,有一个仿真环境是必要的。这就好比是刚开始接触 C 语言,连 C 语言的开发环境都没有,怎么学习 C 语言呢,难道靠大脑模拟运行吗?
本文介绍如何在 Linux 操作系统(以 Ubuntu 为例)下搭建一个轻量级的 RTL 仿真环境。
安装软件
要安装 2 个软件
sudo apt-get install iverilog
sudo apt-get install gtkwave
准备代码
安装好后可以做个实验。
先准备两个文件
count.v
module count4(out,reset,clk);
output[3:0] out;
input reset,clk;
reg[3:0] out;
always @(posedge clk) begin
if (reset)
out<=0; //同步复位
else
out<=out+1; //计数
end
endmodule
tb_count.v
`timescale 1ns/1ns
module coun4_tp;
reg clk, reset; //测试输入信号定义为 reg 型
wire[3:0] out; //测试输出信号定义为 wire 型
parameter DELY=100;
count4 mycount(out,reset,clk); //调用测试对象
always #(DELY/2) clk = ~clk; //产生时钟波形
initial begin //激励信号定义
clk=0;
reset=0;
#DELY reset=1;
#DELY reset=0;
#(DELY*20) $finish; // initial 块执行一次,inital 块里面是顺序执行的
end
//定义结果显示格式
initial $monitor($time,,"clk=%d reset=%d out=%d", clk, reset, out);
//注意这里的 ,, 代表空参数,空参数在输出时显示为空格。
initial begin
$dumpfile("test.vcd"); // 指定 VCD 文件的名字为 test.vcd ,仿真信息将记录到此文件
$dumpvars(0, coun4_tp); //指定层次数为0,则 coun4_tp 模块及其下面各层次的所有信号将被记录
end
endmodule
代码中有几处要解释:
$dumpfile
和 $dumpvar
是 verilog 语言中的两个系统任务。
$dumpfile
系统任务:为所要创建的 VCD 文件指定文件名。
VCD 文件是在对设计进行的仿真过程中,记录各种信号取值变化情况的信息记录文件。EDA 工具通过读取
VCD 格式的文件,显示图形化的仿真波形,所以,可以把 VCD 文件简单视为波形记录文件。
$dumpvar
系统任务:指定需要记录到 VCD 文件中的信号,可以指定某一模块层次上的所有信号,也可以单独指定某一个信号。
典型语法为
$dumpvar(level, module_name);
参数 level 为一个整数,用于指定层次数,参数 module_name 则指定要记录的模块。
举例:
initial
$dumpvar (0, top); //指定层次数为0,则top模块及其下面各层次的所有信号将被记录
initial
$dumpvar (1, top); //记录模块实例top以下一层的信号
//层次数为1,即记录top模块这一层次的信号
//对于top模块中调用的更深层次的模块实例,则不记录其信号变化
initial
$dumpvar (2, top); //记录模块实例top以下两层的信号
//即top模块及其下一层的信号将被记录
代码就讲到这里,我们看看怎么仿真。
如何仿真
$ iverilog -o testname count.v tb_count.v
-o 选项用来指定输出的文件名,这里是 testname,你可以换成别的
这样之后,就会生成可执行文件 testname
我们运行它,就会生成 .vcd 波形文件
$ ./testname
VCD info: dumpfile test.vcd opened for output.
0 clk=0 reset=0 out= x
50 clk=1 reset=0 out= x
100 clk=0 reset=1 out= x
150 clk=1 reset=1 out= 0
200 clk=0 reset=0 out= 0
250 clk=1 reset=0 out= 1
300 clk=0 reset=0 out= 1
350 clk=1 reset=0 out= 2
400 clk=0 reset=0 out= 2
450 clk=1 reset=0 out= 3
500 clk=0 reset=0 out= 3
550 clk=1 reset=0 out= 4
600 clk=0 reset=0 out= 4
650 clk=1 reset=0 out= 5
700 clk=0 reset=0 out= 5
750 clk=1 reset=0 out= 6
800 clk=0 reset=0 out= 6
850 clk=1 reset=0 out= 7
900 clk=0 reset=0 out= 7
950 clk=1 reset=0 out= 8
1000 clk=0 reset=0 out= 8
1050 clk=1 reset=0 out= 9
1100 clk=0 reset=0 out= 9
1150 clk=1 reset=0 out=10
1200 clk=0 reset=0 out=10
1250 clk=1 reset=0 out=11
1300 clk=0 reset=0 out=11
1350 clk=1 reset=0 out=12
1400 clk=0 reset=0 out=12
1450 clk=1 reset=0 out=13
1500 clk=0 reset=0 out=13
1550 clk=1 reset=0 out=14
1600 clk=0 reset=0 out=14
1650 clk=1 reset=0 out=15
1700 clk=0 reset=0 out=15
1750 clk=1 reset=0 out= 0
1800 clk=0 reset=0 out= 0
1850 clk=1 reset=0 out= 1
1900 clk=0 reset=0 out= 1
1950 clk=1 reset=0 out= 2
2000 clk=0 reset=0 out= 2
2050 clk=1 reset=0 out= 3
2100 clk=0 reset=0 out= 3
2150 clk=1 reset=0 out= 4
2200 clk=0 reset=0 out= 4
这时候,又会多出一个 test.vcd 文件
使用 gtkwave 命令查看 .vcd 文件
$ gtkwave test.vcd
要把信号拖动到 Signals 里面
如果觉得前面敲那些命令太麻烦,可以来一个简单的 Makefile
TGT =main
SRC =$(wildcard *.v)
CC =iverilog
$(TGT): $(SRC)
$(CC) -o $@ $^
./$(TGT)
gtkwave test.vcd # 代码中指定 VCD 文件的名字为 test.vcd
clean:
$(RM) $(TGT) test.vcd
参考资料