编写好实现指定功能的Verilog模块后,需要对其进行仿真来验证模块的正确性,这需要用到EDA开发工具的仿真器,我们选择Xilinx公司的Vivado自带的仿真工具进行仿真。
1. 编写仿真模块
在前面的章节已经学习了为Verilog模块编写基本的测试模块,即testbench的基本步骤和方法。本文不再赘述,直接罗列代码如下。
- 组合逻辑版calc()模块
//用组合逻辑实现与calc_v2()函数相同的功能
module calc_wire(
input wire [31:0] a,
input wire [31:0] b,
input wire [31:0] c,
output wire [31:0] sum
);
wire [31:0] tmp;
assign tmp = (a+b) - c * 8;
assign sum = tmp;
endmodule
- 时序逻辑版calc()模块
//用时序逻辑实现与calc_v2()函数相同的功能,计算表达式((a+b) - c * 8)的值
module calc_reg(
input clk,
input wire [31:0] a,
input wire [31:0] b,
input wire [31:0] c,
output reg [31:0] sum
);
//声明一个位宽32bit的reg型变量tmp
reg [31:0] tmp;
//alway块用于对reg型变量赋值tmp
always @(posedge clk) tmp <= (a + b) - c * 8;
//又一个alway块用于对reg型变量赋值sum
always @(posedge clk) begin
sum <= tmp;
end
endmodule
- 综合测试模块
之前博文针对单个Verilog模块calc_reg和calc_wire分别编写了两个testbench,这是为了让大家了解组合逻辑和时序逻辑的区别。实际上,对一个模块而言,一般来说既包含组合逻辑,也会包含时序逻辑,对应的testbench也不会刻意在模块级区分组合逻辑或时序逻辑。下面,我们编写一个对calc_wire和calc_reg两个模块进行综合比对测试的模块,这样可以更好地理解组合逻辑和时序逻辑的区别。
//时间单位:1ns, 时间精度:1ps
`timescale 1ns/1ps
module calc_testbench();
//1. 时序逻辑需要至少一个时钟信号
// 因此,testbench必须生成一个虚拟的时钟信号
reg clk;
initial begin
clk = 0;
forever begin
#50; //50ns, 一个时钟周期为50ns*2 = 100ns
clk = ~clk;
end
end
//2. 给出待测模块需要的输入参数
reg [31:0] aa;
reg [31:0] bb;
reg [31:0] cc;
initial begin
aa = 30;
bb = 40;
cc = 2;
#10; //wait for 10ns, less than one clk period
bb = 90;
#5;
cc = 5;
#55;
aa = 20;
#206;
aa = 100;
bb = 10;
cc = 20;
end
//3. 调用待测试函数calc_reg,并将结果保存到整数dd中
// 将信号aa,bb,cc的值分别传递给模块的输入参数a,b,c
// 并将模块运算结果通过sum_0提取出来
// 时序逻辑需要时钟信号clk也由外部输入
wire [31:0] sum_0;
calc_reg dut_0(
.clk(clk), //时序逻辑必须输入时钟信号
.a(aa),
.b(bb),
.c(cc),
.sum(sum_0)
);
//4. 用相同的输入数据例化组合逻辑模块calc_wire
// 将信号aa,bb,cc的值分别传递给模块的输入参数a,b,c
// 并将模块运算结果通过sum提取出来
wire [31:0] sum_1;
calc_wire dut_1(
.a(aa),
.b(bb),
.c(cc),
.sum(sum_1)
);
//5. 显示函数计算的结果用于比对和验证
initial begin
#3000;
$display("reg: (%d + %d) - %d * 8 = %d",aa,bb,cc,sum_0);
$display("wire: (%d +%d) - %d * 8 = %d",aa,bb,cc,sum_1);
$finish;
end
endmodule
2. 建立Vivado工程并添加Verilog文件
-
打开Vivado,新建一个名为
simulation_demo
的项目
(1)点击菜单【File】–【Project】–【New】新建工程
(2)在弹出界面点击【Next】
(3)修改项目名称和存放位置Project Name: simulation_demo
Project Location: 选择某个容易找到的位置(/home/dayao/tmp
)
勾选Create project subdirectory(4)点击【Next】勾选RTL Project
(5)点击【Next】直到选择Parts也就是FPGA芯片型号的界面。
(6)选择一款FPGA芯片,比如Artix-7系列芯片xc7a100tfgg484-2
(7)点击【Next】,直到【Finish】 -
为新项目添加可综合设计模块(
Design module
)
(1)复制上面calc_wire()
和calc_reg()
模块的源码分别保存为文件calc_wire.v
和calc_reg.v
,将文件保存到项目所在文件夹下,比如文件夹/home/dayao/tmp/simulation_demo/
下。
(2)将文件calc_wire.v
和calc_reg.v
添加到Vivado工程, 注意添加文件时选择Add or Create design sources
,因为这两个文件是生成实际硬件模块的可综合设计模块。 -
添加仿真模块(
Simulation module
)
(1) 上面calc_testbench()
模块源码的内容为calc_testbench.v
,同样放在文件夹/home/dayao/tmp/simulation_demo/
下。
(2) 将文件calc_testbench.v
添加到Vivado工程, 注意添加文件时注意选择Add or Create simulation sources
,因为这个文件是仿真文件,并不会生成实际的硬件模块。
完成上面的步骤后,应该在Vivado的源码管理界面看到如下结构
3. 使用Vivado自带仿真器仿真
现在可以使用Vivado自带仿真器进行数据仿真了。
点击Vivado的【Flow Navigator】–【SIMULATION】-【Run Simulation】–【Run Behavioral Simulation】启动Vivado仿真界面,开始编译仿真模块并显示仿真结果,如果没有错误,应该出现下面的仿真结果界面。
注意:上面的波形图中,数据都是以十进制的形式表示的,Vivado默认的数据格式是十六进制,有时不方便观察。在仿真界面可以二进制、八进制、十进制和十六进制等多种形式表现。方法如下:
(1) 选中需要修改进制的信号(可以多选)点击右键弹出下拉菜单如下图所示;
(2) 下拉菜单中选择【Radix】–
文章来源:https://www.toymoban.com/news/detail-762530.html
Binary : 二进制
Hexadecimal: 十六进制
Octal: 八进制
ASCII: 字符
Unsigned Decimal: 无符号十进制数
Signed Decimal: 有符合十进制数文章来源地址https://www.toymoban.com/news/detail-762530.html
4. 扩展练习
- 编写一个计数器模块(couter),该计数器从0开始计数,计数到255时返回0,再次开始计数。
- 为这个**计数器模块(couter)**编写testbench,验证模块的功能是否正确。
到了这里,关于【0基础学会Verilog】004. 学会使用Vivado自带仿真器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!