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   抄错了. 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  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.


小米8和小米8探索版有什么区别?
解析工业机器人的主流离线编程软件
高云半导体车规级FPGA赋能ADAS | 2021 ICCAD
Google的研究人员开源了一个新框架
日本政府 “绿色增长战略”:2035 年左右以电动汽车取代汽油动力汽车的目标
verilog仿真工具编译
微信电纸书墨水屏样品曝光:预计春节前开放预订
74hc573锁存器怎么用?
槽型光电开关参数及应用
rk3568和rk3399的区别
大唐高鸿在琅岐岛完成智能网联观光车+智能网联站台琅岐智慧旅游专线
差模干扰与共模干扰的概念和开关电源EMI原理图详细概述
嵌入式内存数据库技术的现状如何?怎样设计一个嵌入式内存数据库引擎?
宏cer在印度推出了一款新的预算笔记本电脑Extensa 15
高校房产管理痛点频现!看广凌房产管理信息系统如何解决
比亚迪汽车计划推出新能源高端品牌
关于新能源电动汽车的一些争议
应用于无线传感器的LPWANs有哪几种
Astera Labs推出业界首个 CXL™ 2.0 Memory Accelerator SoC Platform
NPN/PNP传感器相互转换接入PLC技术分析