verilog仿真工具编译

描述

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

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   Verilog 抄错了. 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   Verilog 无事发生. 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 VerilogVerilog   5. 使用-o选项指定输出文件的名称

1iverilog adder_rtl.v adder_tb.v -oadder_test Verilog   6. 在tb中添加dump:

1       initial begin 2        $dumpfile("wave.vcd"); //指定用作dumpfile的文件 3              $dumpvars; //dump all vars 4       end 7. 重新编译运行一遍, 生成了一个vcd文件, 使用gtkwave查看. VerilogVerilogVerilog   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  3 4static int sum_compiletf(char *user_data) 5{ 6       fprintf(stderr, "Yes, youcompiled me "); 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. Verilog 
  
      审核编辑:彭静
打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分