Icarus Verilog:开源 Verilog 一年多后

作者:Stephen Williams

大约 16 个月前,在 2001 年 2 月的 Linux Journal [参见 www.linuxjournal.com/article/4428],我们回顾了电子设计自动化 (EDA) 中开源的状况,并采访了领先的开源 EDA 项目 Icarus Verilog 编译器的作者 Stephen Williams [关于 Stephen Williams 的最新采访,请参见本期第 80 页]。

我们可以回顾并展望开源开发方法为像 Icarus Verilog 这样的项目带来的好处。本文提供了更多关于使用 Verilog 进行设计的技术细节,并探讨了 Icarus Verilog 编译器的一些技术基础。此外,在本文末尾,我们列出了一些关于 Verilog 的优秀参考书,以及您可以在其中找到有关众多替代开源 EDA 项目信息的网站地址。

Icarus Verilog 是一个命令行工具,可以将以 Verilog 编写的源设计编译为目标格式。通常,目标格式是 vvp 仿真引擎的输入,但也可以在命令行中选择其他目标格式。

最明显的第一个例子是无处不在的 “Hello, World.” 程序

module test;
initial $display("Hello, World.");
endmodule

这可以通过以下命令序列轻松编译和执行

% iverilog -oa.vvp hello.v
% vvp a.vvp
Hello, World
硬件工程师很快希望转向更能反映硬件设计问题的更有趣的例子。一个测试计数器模型的简单例子是典型的(参见清单 1)。在 hello.v 和 counter1.v 示例中,编译器都获得一个源文件,该文件被编译为 vvp 格式的输出文件,而 vvp 程序执行生成的文件。

清单 1. counter1.v 示例

在 Verilog 程序中,模块是设计者创建的对象类型,用于对硬件设备进行建模。模块实例化其他模块,并包含自己的代码来描述正在建模的设备。然后,设计者实例化根模块来表示正在建模的整个设备。

Verilog 编译器通常通过注意程序员提供的源代码中哪些模块未在其他任何地方实例化,来推断设计中哪些模块是根模块。在 hello.v 示例中,只有一个模块 “test”,它被设为根模块。在 counter1.v 程序中,模块 “counter” 由 test 实例化,并且只有 test 没有在其他地方实例化,因此 test 是根模块。

使用 Icarus Verilog,程序员可以允许这种启发式方法猜测根模块,也可以使用 -s 标志显式列出根模块。

随着程序变得更大,程序员需要创建多文件程序和库的能力。库也可用作供应商提供的商业可用设备的模型。Icarus Verilog 以可移植的方式支持自动库。

自动库格式是行业标准。它是一个 Verilog 源文件目录,每个文件包含一个模块,文件名以其包含的模块命名。例如,counter.v 包含 counter 模块。库的位置通过命令行或命令文件中的 -y 标志传递给 Icarus Verilog 编译器。

使用自动库,我们的 counter1.v 示例可以分为两个部分:库模块和主程序。在本示例中,将 counter 模块移动到 lib/counter.v 并将 test 模块保留在我们的 counter2.v 程序中是有意义的。有关如何在两部分中使用 counter2.v,请参见清单 2。

清单 2. counter2.v 示例

Icarus Verilog 首先尝试编译 counter2.v 程序。当它到达 counter 模块的实例化时,它注意到它没有 counter 模块定义,搜索它已知的库(来自 -y 标志)并找到 lib/counter.v 文件。它解析这个新的 Verilog 源代码,保存它找到的模块定义,并继续编译原始源代码。库查找会递归,因此库模块可以实例化其他库模块,编译器会累积模块定义,直到程序完成。

Icarus Verilog 还具有支持命令文件的进一步便利性。命令文件是文本文件,其中包含文件名、路径声明和其他编译指令。我们可以为我们的 counter2.v 示例创建一个如下所示的命令文件

counter2.txt:
  # this is a private library
  -y lib
  # project source files for this configuration
  counter2.v

并像这样运行程序

% iverilog -c counter2.txt -o a.vvp
% vvp a.vvp
对于这个小程序,命令文件没有太大用处,但随着设计变得更大(数百个源文件并不少见),命令文件变得不可或缺。

Icarus Verilog 还包含其他 Verilog 编译器不具备的独特功能:可加载目标 API。这是一个用于可加载模块的 C API,编译器可以调用它以生成新格式的输出。vvp 代码生成器本身是一个可加载目标模块,当请求 vvp 仿真时(默认)会调用它。还有 null 代码生成器和 fpga 代码生成器。

C 程序员可以通过 Icarus Verilog 包中包含和安装的 ivl_target.h 头文件来使用可加载目标 API。此 API 允许 C 程序员为 Icarus Verilog 编译器编写新的输出代码生成器。

vvp 运行时还支持标准 Verilog VPI 接口的子集。这是一个运行时 C API,允许程序员编写 Verilog 源代码可以调用的新系统任务。系统任务的现有示例是 counter2.v 示例源文件中的 $stop 和 $monitor 语句。所有标准核心系统任务都是使用 VPI API 在 Icarus Verilog 中编写的。

资源

Icarus Verilog: Open-Source Verilog More Than a Year Later
Stephen Williams 有一天在他的当地大学的计算机实验室里迷路了。他原本是一名电气工程专业的学生,但最终获得了计算机科学学位。十年后,在从事各种软件项目,尤其是大型和高度分布式系统之后,他发现自己与高速数码相机的电线纠缠在一起。从那时起,他将这些经验结合起来,致力于设备驱动程序、嵌入式系统和 EDA 工具。

Icarus Verilog: Open-Source Verilog More Than a Year Later
Michael Baxter (mabaxter@pacbell.net) 自九岁起就从事计算机技术工作,1969 年观看《2001:太空漫游》给他留下了深刻的印象。他是一位经验丰富的计算机架构师、系统、电路板和 FPGA 逻辑设计师。Michael 拥有十项美国计算机架构和逻辑专利,以及五项作为共同发明人的专利。他的兴趣还包括徒步旅行、业余无线电和 Lisp 编程。
加载 Disqus 评论