专栏首页OpenFPGA一文学会使用全球第四大数字芯片仿真器iverilog!

一文学会使用全球第四大数字芯片仿真器iverilog!

作者:西南交通大学研究生导师邸志雄博士。

Icarus Verilog(以下简称iverilog )号称“全球第四大”数字芯片仿真器,也是一个完全开源的仿真器。由于Synopsys、Cadence、Mentor版权的关系,国外很多高校在数字芯片设计的教学中都采用iverilog。

GTKWave是一个开源的波形文件察看工具,支持Verilog VCD/EVCD文件格式。因此,通过“iverilog +gtkwave”的方式,可以很方便地实现商用仿真器的功能。

本文为我的学生整理自 iverilog 和 gtkwave 官方网站。

介绍

iverilog

Icarus Verilog是一个verilog仿真工具. 以编译器的形式工作, 将以verilog编写的源代码编译为某种目标格式. 如果要进行仿真的话, 它可以生成一个叫做vvp的中间格式. 这个格式可以由其所附带的vvp命令执行.

gtkwave

wave viewer. 可以用于查看标准的verilog VCD/EVCD, 以及其他的一些格式的波形文件。

安装

iverilog

  • windows http://bleyer.org/icarus/
  • linux a. 使用自带的包管理器下载:sudo pacman -S iverilog b. 从github上clone源码然后编译: https://github.com/steveicarus/iverilog

gtkwave

  • windows https://sourceforge.net/projects/gtkwave/files/
  • linux a. 包管理器安装下载:sudo pacman -S gtkwave b. 从上面的链接下载源码, 然后编译

使用

1. 示例:

 1// adder_rtl.v
 2module adder(clk, rst_n, a, b, c);
 3    input [3:0] a;
 4    input [3:0] b;
 5    output [7:0] c;
 6    input clk, rst_n;
 7
 8    wire [3:0] a;
 9    wire [3:0] b;
10    wire [7:0] c;
11
12    always @(posedge clk or negedge rst_m) begin
13        if (rst_n == 1'b0)
14            c <= 8'b0;
15        else
16            c <= a+b;
17    end
18endmodule

2. 编译:

1iverlog adder_rtl.v

抄错了. damn.

 1module adder(clk, rst_n, a, b, c);
 2    input [3:0] a;
 3    input [3:0] b;
 4    output [7:0] c;
 5    input clk, rst_n;
 6
 7    wire [3:0] a;
 8    wire [3:0] b;
 9    reg [7:0] c;
10
11    always @(posedge clk or negedge rst_n) begin
12        if (rst_n == 1'b0)
13            c <= 8'b0;
14        else
15            c <= a+b;
16    end
17endmodule

3. 编译:

1iverlog adder_rtl.v

无事发生.

tb:

 1// adder_tb.v
 2`timescale 1ns/1ns
 3module adder_tb();
 4       reg [3:0] a;
 5       reg [3:0] b;
 6       wire [7:0] c;
 7
 8       reg clk,rst_n;
 9
10       adder DUT (
11              .clk(clk),
12              .rst_n(rst_n),
13              .a(a),
14              .b(b),
15              .c(c)
16       );
17
18       always begin
19              #10 clk = 0;
20              #10 clk = 1;
21       end
22
23       initial begin
24              rst_n = 1;
25              test(4'b1111, 4'b1111, 5'b11110);
26              $finish;
27       end
28       task test;
29              input [3:0] in;
30              input [3:0] in2;
31              input [7:0] e;
32              begin
33                     a = in;
34                     b = in2;
35                     @(posedge clk);
36                     @(negedge clk);
37                     if (c == e) begin
38                            $display("Itworks");
39                     end else begin
40                            $display("opps%d + %d ~= %d, expect %d", in, in2, c, e);
41                     end
42              end
43       endtask
44endmodule

4. 编译运行:

1iverilog adder_rtl.v adder_tb.v

5. 使用-o选项指定输出文件的名称

1iverilog adder_rtl.v adder_tb.v -oadder_test

6. 在tb中添加dump:

1       initial begin
2        $dumpfile("wave.vcd"); //指定用作dumpfile的文件
3              $dumpvars; //dump all vars
4       end

7. 重新编译运行一遍, 生成了一个vcd文件, 使用gtkwave查看.

iverilog的一些选项:

  • -D: 定义宏
  • -P: 覆盖root module中的一个参数的值
  • -E: 只预处理(进行宏替换), 不编译
  • -g1995, -g2001, -g2005 ...: 选择支持的verilog语言版本.
  • -I includedir: 指定(添加)verilog中include指令的搜索路径
  • -s topmodule : 指定要建立的顶层模块. 默认是没有被实例化的哪些module

VPI:

Verilog Prodecure Interface(VPI), 最开始也称作PLI 2.0, 一个主要面向C语言的接口. 可以让行为级别的Verilog代码调用C函数, 让C函数调用标准Verilog系统函数.

 1  // adder.c
 2#include <vpi_user.h>
 3
 4static int sum_compiletf(char *user_data)
 5{
 6       fprintf(stderr, "Yes, youcompiled me\n");
 7       return 0;
 8}
 9
10static int sum (char *user_data)
11{
12       vpiHandle systfref, args_iter,argh;
13       // typedef struct t_vpi_values_vpi_value
14       struct t_vpi_value argval;
15       unsigned int value, value2;
16       char res[1024];
17
18       systfref = vpi_handle(vpiSysTfCall,NULL);
19       args_iter =vpi_iterate(vpiArgument, systfref); // 迭代所有参数.
20
21       argh = vpi_scan(args_iter); // 获取下一个参数
22       argval.format = vpiIntVal; // 设定格式为int
23       vpi_get_value(argh, &argval); //获取参数值
24       value = argval.value.integer;  // 读取获取到的参数值
25
26       argh = vpi_scan(args_iter); // 获取下一个参数
27       argval.format = vpiHexStrVal; // 以hex格式读入
28       vpi_get_value(argh, &argval);
29       sscanf(argval.value.str, "%x",&value2); // 将hex str格式读入的值转换为int
30
31       argh = vpi_scan(args_iter); // 获取第三个参数
32       argval.format = vpiHexStrVal; // 设置格式为hex str, verilog读取的时候会自动转换的.
33       sprintf(res, "%x", value+ value2); // 在C里计算两个值的和, 并将其转换为hex格式的字符串
34
35       argval.value.str = res;
36       vpi_put_value(argh, &argval, 0,vpiNoDelay); // 设置第三个参数的值
37
38       vpi_put_value(systfref,&argval, 0, vpiNoDelay);
39       vpi_free_object(args_iter);
40       return 0;
41}
42
43
44// 注册 $sum
45void sum_register() {
46       s_vpi_systf_data tf_data;
47
48       tf_data.type      = vpiSysTask; // 类型. 还有一个是SysFunc
49       tf_data.tfname    = "$sum"; // 在verilog中调用的名称
50       tf_data.calltf    = sum; // 被verilog调用时调用的函数
51       tf_data.compiletf = sum_compiletf; //被编译时调用的函数
52       tf_data.sizetf    = 0; // 不知道
53       tf_data.user_data = 0; // 不知道
54       vpi_register_systf(&tf_data); //注册
55}
56
57
58
59// 在这个函数数组里的函数会自动被调用.
60void (*vlog_startup_routines[])() = {
61       sum_register,
62       0
63};

修改tb来调用$sum:

 1  // adder_tb.v
 2`timescale 1ns/1ns
 3module adder_tb();
 4       reg [3:0] a;
 5       reg [3:0] b;
 6       wire [7:0] c;
 7
 8       reg clk,rst_n;
 9
10       integer i, n, nf;
11
12       adder DUT (
13              .clk(clk),
14              .rst_n(rst_n),
15              .a(a),
16              .b(b),
17              .c(c)
18       );
19
20       always begin
21              #10 clk = 0;
22              #10 clk = 1;
23       end
24
25       initial begin
26              $display("=============================");
27              $display("Tb start athere");
28              rst_n = 1;
29              n = 0;
30              nf = 0;
31              // $test($random%4,2);
32              for (i = 0; i < 20; i++)
33                     test($urandom%5'b10000,$urandom%5'b10000);
34              $display("%d total, %dfail", n, nf);
35              $finish;
36       end
37       task test;
38              input [3:0] in;
39              input [3:0] in2;
40              begin: test
41                     reg [7:0] e;
42                     a = in;
43                     b = in2;
44            $sum(a,b,e); // HERE
45                     @(posedge clk);
46                     @(negedge clk);
47                     n = n + 1;
48                     if (c == e) begin
49                            $display("Itworks, %d + %d = %d", in, in2, e);
50                     end else begin
51                            nf = nf + 1;
52                            $display("opps%d + %d ~= %d, expect %d", in, in2, c, e);
53                     end
54              end
55       endtask
56
57       // initial begin
58              //$dumpfile("wave.vcd");
59              // $dumpvars;
60       // end
61endmodule

编译运行:

1iverilog adder_rtl.v adder_tb.v -oadder.vvp
2iverilog-vpi adder.c
3vvp -M. -madder adder.vvp

iverilog-vpi: 自带的帮助生成库的脚本 -M path: 将path加入定位VPI模块的路径, .: 当前路径 -m module: 告诉vvp在执行simulation之前加载指定的module.

这里可以找到更多vpi使用的例子(扫描下方二维码):

参考书:

1)Static TimingAnalysis for Nanometer Designs: A Practical Approach. J. Bhasker, RakeshChadha. Springer Science Business Media, LLC 2009.

2)综合与时序分析的设计约束:Synopsys设计约束(SDC)实用指南。[美] 斯里达尔·甘加达兰(Sridhar Gangadharan),[印度] 桑杰·丘里瓦拉(Sanjay,Chur 著,韩德强 张丽艳 王宗侠等译 译

3)集成电路静态时序分析与建模. 刘峰, 机械工业出版社.出版时间:2016-07-01.

本文分享自微信公众号 - OpenFPGA(OpenFPGA)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-06-19

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • YCbCr422 转 RGB888 的 HDL 实现

    ITU-R BT.601 和 ITU-R BT.656 是 国 际 电 信 联 盟 ( International Telecommunication Unio...

    碎碎思
  • System Generator从入门到放弃(二)-Digital Filter

    System Generator是Xilinx公司进行数字信号处理开发的一种设计工具,它通过将Xilinx开发的一些模块嵌入到Simulink的库中,可以在Si...

    碎碎思
  • CORDIC算法详解(二)-CORDIC 算法之圆周系统之向量模式

    网上有很多类似的介绍,但是本文会结合实例进行介绍,尽量以最简单的语言进行解析。   CORDIC ( Coordinate Rotation Digital C...

    碎碎思
  • 一文学会使用全球第四大数字芯片仿真器iverilog!

    Icarus Verilog(以下简称iverilog )号称“全球第四大”数字芯片仿真器,也是一个完全开源的仿真器。由于Synopsys、Cadence、Me...

    网络交换FPGA
  • iOS学习——如何在mac上获取开发使用的模拟器的资源以及模拟器中每个应用的应用沙盒

    如题,本文主要研究如何在mac上获取开发使用的模拟器的资源以及模拟器中每个应用的应用沙盒。做过安卓开发的小伙伴肯定很方便就能像打开资源管理器一样查看我们写到手...

    mukekeheart
  • “无人店”热潮平息,“机器视觉+商业智能”以另类模式落地传统零售 | 活动

    走进一家便利店,随即响起提示音:“您好,会员,欢迎光临,今天XXX商品有打折哦。”

    镁客网
  • mapx实现热点效果

            当鼠标移动到图元上方时,标注改变样式(变色,加下划线等),移开后还原。通过vb+mapx基本实现这个效果,但由于mapx在label进行变化时的...

    用户1075292
  • java 实现棋盘覆盖问题

    问题描述:在一个2k*2k的棋盘中,有一个特殊方格,要求用L型骨牌覆盖满除特殊方格外的所有其他方格,且骨牌不得重叠.(骨牌可以旋转放置) 输入:棋盘的边长、特殊...

    yawn
  • 图卷积网络图深度学习(上)

    基于图的机器学习是一项困难的任务,因为图的结构非常复杂,而且信息量也很大。本文是关于如何利用图卷积网络(GCNs)对图进行深度学习的系列文章中的第一篇。GCNs...

    AiTechYun
  • css应知应会 第一集

    ================================================

    李才哥

扫码关注云+社区

领取腾讯云代金券