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技术分析