Zynq开发实践(FPGA之verilog仿真)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

我们都知道,做fpga开发,可以用verilog,也可以用vhdl。开发完之后,如果需要实际验证,那么就可以综合一下,下载到fpga,看下效果。但是如果开发的内容比较多,或者开发的内容,是由很多人一起完成的,并且fpga验证平台也不多,这个时候应该怎么做呢?通常我们都是借助于verilog仿真来实现功能验证的。

1、verilog仿真工具

提起verilog仿真,大家都会想起modelsim。但是有一些开源工具也是可以完成verilog仿真的,这里面就有iverilog和verilator。其中verilator比较特殊,它是把verilog翻译成c语言来执行。

2、iverilog仿真

和verilator不同,iverilog工具本身是编译成一个中间语言,然后通过vvp执行中间语言,最后通过gtkwave生成波形。所以整个过程当中有三个工具,一个是iverilog,一个是vvp,一个是gtkwave。

3、功能代码

为了说明iverilog如何使用,我们先写一个简单的功能代码,即cnt.v,

复制代码
module count(rst, clk, out);
 
// input & output
input rst;
input clk;
output out;
 
// wire & reg
wire rst;
wire clk;
 
reg ce;
reg out;
 
// inner wire & reg
reg[5:0] cnt;
 
// clause defined
 
always @(posedge clk or posedge rst)
	if(rst)
		ce <= 1'b0;
	else
		ce <= 1'b1;
 
always @(posedge clk or posedge rst)
    if (rst) begin
        cnt <= 6'h00;
    end else if (ce == 1'b1)begin 
		if (cnt == 6'd59)
			cnt <= 6'h00;
		else
			cnt <= cnt + 1;
	end
 
always @(posedge clk or posedge rst)
	if(rst)
		out <= 1'b0;
	else if(out == 1'b1)
		out <= 1'b0;
	else if(cnt == 6'd59)
		out <= 1'b1;
endmodule

4、测试代码

功能代码一般需要外部的激励才能完成测试,所以我们还需要写一个激励文件,这就是testbench。可以把这个激励文件命名为tb.v,

复制代码
`timescale 1ns/1ps
module test();
 
reg rst;
reg clk;
wire data;
 
count tt(.rst(rst),
    .clk(clk),
    .out(data));
 
initial
    begin
        rst = 0;
        clk = 0;
        #12 rst = 1;
        #21 rst = 0;
        #1000 $finish;
    end
 
 
initial
begin
    while(1)
    clk = #5 !clk;
end
 
initial
begin
    $dumpfile("hello.vcd");
    $dumpvars(0, test);
end
 
endmodule

5、测试命令

实际的测试命令是iverilog、vvp、gtkwave依次执行。不过我们可以拼在一起,这样使用就非常方便,也就是把命令用&&连接在一起,

复制代码
C:\iverilog\bin\iverilog.exe -o tb tb.v cnt.v && C:\iverilog\bin\vvp.exe -n tb -lxt2 && C:\iverilog\gtkwave\bin\gtkwave.exe hello.vcd

6、查看波形

这里生成的波形文件就是hello.vcd,运行完命令之后,拖入信号,就可以看到波形了。并且后续开发的时候,也就只需要保留这个框架,修改cnt.v就好了。

7、中间文件tb

整个仿真过程还是比较简单,其中比较有意义的,就是生成的中间文件tb,

复制代码
#! /c/Source/iverilog-install/bin/vvp
:ivl_version "12.0 (devel)" "(s20150603-1539-g2693dd32b)";
:ivl_delay_selection "TYPICAL";
:vpi_time_precision - 12;
:vpi_module "C:\iverilog\lib\ivl\system.vpi";
:vpi_module "C:\iverilog\lib\ivl\vhdl_sys.vpi";
:vpi_module "C:\iverilog\lib\ivl\vhdl_textio.vpi";
:vpi_module "C:\iverilog\lib\ivl\v2005_math.vpi";
:vpi_module "C:\iverilog\lib\ivl\va_math.vpi";
S_000001792f479e10 .scope module, "test" "test" 2 2;
 .timescale -9 -12;
v000001792f476980_0 .var *"_ivl_0", 0 0; Local signal
v000001792f30d840_0 .var "clk", 0 0;
v000001792f30d8e0_0 .net "data", 0 0, v000001792f476840_0;  1 drivers
v000001792f30d980_0 .var "rst", 0 0;
S_000001792f476610 .scope module, "tt" "count" 2 8, 3 1 0, S_000001792f479e10;
 .timescale -9 -12;
    .port_info 0 /INPUT 1 "rst";
    .port_info 1 /INPUT 1 "clk";
    .port_info 2 /OUTPUT 1 "out";
v000001792f479fa0_0 .var "ce", 0 0;
v000001792f47b920_0 .net "clk", 0 0, v000001792f30d840_0;  1 drivers
v000001792f4767a0_0 .var "cnt", 5 0;
v000001792f476840_0 .var "out", 0 0;
v000001792f4768e0_0 .net "rst", 0 0, v000001792f30d980_0;  1 drivers
E_000001792f4792a0 .event posedge, v000001792f4768e0_0, v000001792f47b920_0;
    .scope S_000001792f476610;
T_0 ;
    %wait E_000001792f4792a0;
    %load/vec4 v000001792f4768e0_0;
    %flag_set/vec4 8;
    %jmp/0xz  T_0.0, 8;
    %pushi/vec4 0, 0, 1;
    %assign/vec4 v000001792f479fa0_0, 0;
    %jmp T_0.1;
T_0.0 ;
    %pushi/vec4 1, 0, 1;
    %assign/vec4 v000001792f479fa0_0, 0;
T_0.1 ;
    %jmp T_0;
    .thread T_0;
    .scope S_000001792f476610;
T_1 ;
    %wait E_000001792f4792a0;
    %load/vec4 v000001792f4768e0_0;
    %flag_set/vec4 8;
    %jmp/0xz  T_1.0, 8;
    %pushi/vec4 0, 0, 6;
    %assign/vec4 v000001792f4767a0_0, 0;
    %jmp T_1.1;
T_1.0 ;
    %load/vec4 v000001792f479fa0_0;
    %cmpi/e 1, 0, 1;
    %jmp/0xz  T_1.2, 4;
    %load/vec4 v000001792f4767a0_0;
    %cmpi/e 59, 0, 6;
    %jmp/0xz  T_1.4, 4;
    %pushi/vec4 0, 0, 6;
    %assign/vec4 v000001792f4767a0_0, 0;
    %jmp T_1.5;
T_1.4 ;
    %load/vec4 v000001792f4767a0_0;
    %addi 1, 0, 6;
    %assign/vec4 v000001792f4767a0_0, 0;
T_1.5 ;
T_1.2 ;
T_1.1 ;
    %jmp T_1;
    .thread T_1;
    .scope S_000001792f476610;
T_2 ;
    %wait E_000001792f4792a0;
    %load/vec4 v000001792f4768e0_0;
    %flag_set/vec4 8;
    %jmp/0xz  T_2.0, 8;
    %pushi/vec4 0, 0, 1;
    %assign/vec4 v000001792f476840_0, 0;
    %jmp T_2.1;
T_2.0 ;
    %load/vec4 v000001792f476840_0;
    %cmpi/e 1, 0, 1;
    %jmp/0xz  T_2.2, 4;
    %pushi/vec4 0, 0, 1;
    %assign/vec4 v000001792f476840_0, 0;
    %jmp T_2.3;
T_2.2 ;
    %load/vec4 v000001792f4767a0_0;
    %cmpi/e 59, 0, 6;
    %jmp/0xz  T_2.4, 4;
    %pushi/vec4 1, 0, 1;
    %assign/vec4 v000001792f476840_0, 0;
T_2.4 ;
T_2.3 ;
T_2.1 ;
    %jmp T_2;
    .thread T_2;
    .scope S_000001792f479e10;
T_3 ;
    %pushi/vec4 0, 0, 1;
    %store/vec4 v000001792f30d980_0, 0, 1;
    %pushi/vec4 0, 0, 1;
    %store/vec4 v000001792f30d840_0, 0, 1;
    %delay 12000, 0;
    %pushi/vec4 1, 0, 1;
    %store/vec4 v000001792f30d980_0, 0, 1;
    %delay 21000, 0;
    %pushi/vec4 0, 0, 1;
    %store/vec4 v000001792f30d980_0, 0, 1;
    %delay 1000000, 0;
    %vpi_call 2 18 "$finish" {0 0 0};
    %end;
    .thread T_3;
    .scope S_000001792f479e10;
T_4 ;
T_4.0 ;
    %pushi/vec4 1, 0, 32;
    %or/r;
    %flag_set/vec4 8;
    %jmp/0xz T_4.1, 8;
    %load/vec4 v000001792f30d840_0;
    %nor/r;
    %store/vec4 v000001792f476980_0, 0, 1;
    %pushi/vec4 5000, 0, 64;
    %ix/vec4 4;
    %delayx 4;
    %load/vec4 v000001792f476980_0;
    %store/vec4 v000001792f30d840_0, 0, 1;
    %jmp T_4.0;
T_4.1 ;
    %end;
    .thread T_4;
    .scope S_000001792f479e10;
T_5 ;
    %vpi_call 2 30 "$dumpfile", "hello.vcd" {0 0 0};
    %vpi_call 2 31 "$dumpvars", 32'sb00000000000000000000000000000000, S_000001792f479e10 {0 0 0};
    %end;
    .thread T_5;
# The file index is used to find the file name in the following table.
:file_names 4;
    "N/A";
    "<interactive>";
    "tb.v";
    "cnt.v";

这个文件其实是可以读懂的,比如每一部分的内容都是一个thread。

复制代码
    .scope S_000001792f479e10;
T_4 ;
T_4.0 ;
    %pushi/vec4 1, 0, 32;
    %or/r;
    %flag_set/vec4 8;
    %jmp/0xz T_4.1, 8;
    %load/vec4 v000001792f30d840_0;
    %nor/r;
    %store/vec4 v000001792f476980_0, 0, 1;
    %pushi/vec4 5000, 0, 64;
    %ix/vec4 4;
    %delayx 4;
    %load/vec4 v000001792f476980_0;
    %store/vec4 v000001792f30d840_0, 0, 1;
    %jmp T_4.0;
T_4.1 ;
    %end;
    .thread T_4;
    .scope S_000001792f479e10;
相关推荐
9527华安3 小时前
FPGA实现Aurora 64B66B数据回环传输,基于GTY高速收发器,提供4套工程源码和技术支持
fpga开发·aurora·高速收发器·gty·64b66b
希言自然也2 天前
FPGA 时序分析(一)
fpga开发
I'm a winner2 天前
基于FPGA的情绪感知系统设计方案:心理健康监测应用(一)
fpga开发·前沿研究
嵌入式-老费2 天前
Zynq开发实践(Verilog、仿真、FPGA和芯片设计)
fpga开发
hahaha60163 天前
pcie实现虚拟串口
stm32·单片机·fpga开发
9527华安3 天前
FPGA高端项目:图像采集+Aurora 8B10B+UDP图传架构,基于GTH高速收发器的光口转网口,提供工程源码和技术支持
fpga开发·架构·udp·aurora·gth·高速收发器·aurora 8b10b
徐晓康的博客3 天前
Verilog功能模块--SPI主机和从机(03)--SPI从机设计思路与代码解析
fpga开发·verilog·主机·spi·从机
listhi5204 天前
FPGA设计中的信号完整性量化与优化:探索高速数字系统的关键路径
fpga开发
hahaha60164 天前
xilinx的oddr原语是否可以直接使用verilog实现?
fpga开发