如果你只是想检查Verilog文件的语法是否有错误,然后进行一些基本的时序仿真,那么Icarus Verilog 就是一个不错的选择。相比于各大FPGA厂商的IDE几个G的大小,Icarus Verilog 显得极其小巧,最新版安装包大小仅有17MB,支持全平台:Windows+Linux+MacOS,并且源代码开源。本文将介绍如何使用Icarus Verilog来进行verilog文件的编译和仿真。
Icarus Verilog是一个轻量、免费、开源的Verilog编译器,基于C++实现,开发者是 Stephen Williams ,遵循 GNU GPL license 许可证。简称iVerilog,是比较著名的开源HDL仿真工具。
iVerilog以编译器的形式工作,将以verilog编写的源代码编译为某种目标格式。如果要进行仿真的话,,它可以生成一个叫做vvp的中间格式.,这个格式可以由其所附带的vvp命令执行。
iVerilog的安装文件中已经包含 GTKWave支持Verilog/VHDL文件的编译和仿真,命令行操作方式,类似gcc编译器,通过testbench文件可以生成对应的仿真波形数据文件,通过自带的GTKWave可以查看仿真波形图,支持将Verilog转换为VHDL文件。
wave viewer,可以用于查看标准的verilog VCD/EVCD,,以及其他的一些格式的波形文件。
打开iVerilog官网下载链接,点击其中的iverilog-v11-20190809-x64_setup.exe [17.0MB]
,进行安装包下载
双击打开安装包,按照如下步骤进行安装:
验证是否安装成功,在cmd命令行通过where命令查看安装路径,若显示成功,则表示安装成功,如下图所示
where iverilog
where vvp
where gtkwave
Icarus Verilog编译器主要包含3个工具:
在cmd终端输入iverilog
回车,可以看到常用参数使用方法的简单介绍,如下图所示:
-o
这是比较常用的一个参数了,和GCC中-o的使用几乎一样,用于指定生成文件的名称。如果不指定,默认生成文件名为a.out。如:iverilog -o test test.v
-y
用于指定包含文件夹,如果top.v
中调用了其他的的led_demo_tb.v
模块,top.v
直接编译会提示
led_demo_tb.v:38: error: Unknown module type: led_demo
2 error(s) during elaboration.
*** These modules were missing:
led_demo referenced 1 times.
***
找不到调用的模块,那么就需要指定调用模块所在文件夹的路径,支持相对路径和绝对路径。
如:iverilog -y D:/test/demo led_demo_tb.v
如果是同一目录下:iverilog -y ./ led_demo_tb.v
,另外,iverilog还支持Xilinx、Altera、Lattice等FPGA厂商的仿真库,需要在编译时通过-y参数指定库文件的路径,详细的使用方法可以查看官方用户指南:
https://iverilog.fandom.com/wiki/User_Guide
如果程序使用include
语句包含了头文件路径,可以通过-i参数指定文件路径,使用方法和-y参数一样。
如:iverilog -I D:/test/demo led_demo_tb.v
iverilog还支持把verilog文件转换为VHDL文件,如iverilog -tvhdl -o out_file.vhd in_file.v
这一节来介绍Verilog的编译仿真实际应用,达到快速上手的目的!
新建led_demo.v
源文件,功能非常简单,每10个时钟周期,led翻转一次。
module led_demo(
input clk,
input rst_n,
output reg led
);
reg [7:0] cnt;
always @ (posedge clk)
begin
if(!rst_n)
cnt <= 0;
else if(cnt >= 10)
cnt <= 0;
else
cnt <= cnt + 1;
end
always @ (posedge clk)
begin
if(!rst_n)
led <= 0;
else if(cnt == 10)
led <= !led;
end
endmodule
仿真testbench文件led_demo_tb.v
`timescale 1ns/100ps
module led_demo_tb;
parameter SYSCLK_PERIOD = 10;
reg SYSCLK;
reg NSYSRESET;
initial
begin
SYSCLK = 1'b0;
NSYSRESET = 1'b0;
end
/*iverilog */
initial
begin
$dumpfile("wave.vcd"); //生成的vcd文件名称
$dumpvars(0, led_demo_tb); //tb模块名称
end
/*iverilog */
initial
begin
#(SYSCLK_PERIOD * 10 )
NSYSRESET = 1'b1;
#1000
$stop;
end
always @(SYSCLK)
#(SYSCLK_PERIOD / 2.0) SYSCLK <= !SYSCLK;
led_demo led_demo_ut0 (
// Inputs
.rst_n(NSYSRESET),
.clk(SYSCLK),
// Outputs
.led( led)
);
endmodule
注意testbench文件中有几行iverilog编译器专用的语句,如果不加的话后面不能生成vcd文件。
initial
begin
$dumpfile("wave.vcd"); //生成的vcd文件名称
$dumpvars(0, led_demo_tb); //tb模块名称
end
通过iverilog -o wave led_demo_tb.v led_demo.v
命令,对源文件和仿真文件,进行语法规则检查和编译。
由于本示例比较简单,只有1个文件,如果调用了多个
.v
的模块,可以通过前面介绍的-y
参数指定源文件的路径,否则编译报错。如果源文件都在同同一个目录,可以直接通过./
绝对路径的方式来指定。
例如,
led_demo_tb.v
中调用了led_demo.v
模块,就可以直接使用iverilog -o wave -y ./ led_demo.v led_demo_tb.v
来进行编译。
如果编译成功,会在当前目录下生成名称为wave的文件,如下图
使用vvp -n wave -lxt2
命令生成vcd
波形文件,运行之后,会在当前目录下生成.vcd
文件。
如果没有生成,需要检查testbench文件中是否添加了如下几行:
initial
begin
$dumpfile("wave.vcd"); //生成的vcd文件名称
$dumpvars(0, led_demo_tb); //tb模块名称
end
使用命令gtkwave wave.vcd
,可以在图形化界面中查看仿真的波形图。
然后点击工具栏的Zoom fit,可以使波形调整到合适比例,如下图
虽然VHDL和Verilog都诞生于20世纪80年代,而且都属于硬件描述语言(HDL),但是二者的语法特性却不一样。Icarus Verilog 还有一个小功能就是支持把使用Verilog语言编写的.v文件转换为VHDL语言的.vhd文件。
如把led_demo.v文件转换为VHDL文件led_demo.vhd,使用命令iverilog -tvhdl -o led_demo.vhd led_demo.v
-- This VHDL was converted from Verilog using the
-- Icarus Verilog VHDL Code Generator 11.0 (devel) (s20150603-642-g3bdb50da)
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Generated from Verilog module led_demo (led_demo.v:1)
entity led_demo is
port (
clk : in std_logic;
led : out std_logic;
rst_n : in std_logic
);
end entity;
-- Generated from Verilog module led_demo (led_demo.v:1)
architecture from_verilog of led_demo is
signal led_Reg : std_logic;
signal cnt : unsigned(7 downto 0); -- Declared at led_demo.v:8
begin
led <= led_Reg;
-- Generated from always process in led_demo (led_demo.v:10)
process (clk) is
begin
if rising_edge(clk) then
if (not rst_n) = '1' then
cnt <= X"00";
else
if Resize(cnt, 32) >= X"0000000a" then
cnt <= X"00";
else
cnt <= cnt + X"01";
end if;
end if;
end if;
end process;
-- Generated from always process in led_demo (led_demo.v:20)
process (clk) is
begin
if rising_edge(clk) then
if (not rst_n) = '1' then
led_Reg <= '0';
else
if Resize(cnt, 32) = X"0000000a" then
led_Reg <= not led_Reg;
end if;
end if;
end if;
end process;
end architecture;
通过批处理文件,可以简化编译仿真的执行过程,直接一键执行编译和仿真。新建文本文档,输入以下内容:
echo "开始编译"
iverilog -o wave led_demo.v led_demo_tb.v
echo "编译完成"
vvp -n wave -lxt2
echo "生成波形文件"
cp wave.vcd wave.lxt
echo "打开波形文件"
gtkwave wave.lxt
pause
文件扩展名需要更改,Windows系统保存为.bat
格式,然后双击即可运行!
从20040706版本,到现在的最新版本20190809,作者还在继续更新,有兴趣的朋友可以研究一下源代码是如何实现语法规则检查的,或者可以尝试编译源码,获得最新的版本。当然,和FPGA厂商的IDE相比,功能还是非常有限,GTKWave界面也比较简陋,如不支持宽度测量等,主要是小巧+全平台支持,可以配合IDE来使用。这个工具还支持主流FPGA厂商的IP核仿真,如Xilinx和Lattice,详细的使用方法可以参考官方使用指南。