在目录下建立文件夹,将DUT和Testbench添加进去,文件夹内容如下所示:
功能很简单,即将接受到的数据原封不动发送出去。
module dut(clk,
rst_n,
rxd,
rx_dv,
txd,
tx_en);
input clk;
input rst_n;
input[7:0] rxd;
input rx_dv;
output [7:0] txd;
output tx_en;
reg[7:0] txd;
reg tx_en;
always @(posedge clk) begin
if(!rst_n) begin
txd <= 8'b0;
tx_en <= 1'b0;
end
else begin
txd <= rxd;
tx_en <= rx_dv;
end
end
endmodule
定义一个driver类,它派生自uvm_driver。driver的主要功能在main_phase task中实现,主要功能为向rxd管脚上发送随机数。`uvm_info(“my_driver”, “data is drived”, UVM_LOW)为打印信息的宏。
`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;
function new(string name = "my_driver", uvm_component parent = null);
super.new(name, parent);
endfunction
extern virtual task main_phase(uvm_phase phase);
endclass
task my_driver::main_phase(uvm_phase phase);
top_tb.rxd <= 8'b0;
top_tb.rx_dv <= 1'b0;
while(!top_tb.rst_n)
@(posedge top_tb.clk);
for(int i = 0; i < 256; i++) // 开始循环256次
begin
@(posedge top_tb.clk);
top_tb.rxd <= $urandom_range(0, 255); // 随机向rxd 上发送一个0~255的随机数
top_tb.rx_dv <= 1'b1; // 有效位,置1
`uvm_info("my_driver", "data is drived", UVM_LOW)
end
@(posedge top_tb.clk);
top_tb.rx_dv <= 1'b0; // 完成后有效位拉低
endtask
`endif
`timescale 1ns/1ns
`include "uvm_macros.svh" // 包含宏定义
import uvm_pkg::*; // 导入UVM库
`include "F:/modelsim_workspace/uvm_learning/test0/my_driver.sv"
module top_tb;
reg clk;
reg rst_n;
reg[7:0] rxd;
reg rx_dv;
wire[7:0] txd;
wire tx_en;
dut my_dut(.clk(clk),
.rst_n(rst_n),
.rxd(rxd),
.rx_dv(rx_dv),
.txd(txd),
.tx_en(tx_en));
initial begin // 定义drv 并进行实例化
my_driver drv;
drv = new("drv", null);
drv.main_phase(null); // 调用drive的 main_phase
$finish();
end
initial begin
clk = 0;
forever begin
#1 clk = ~clk;
end
end
initial begin
rst_n = 1'b0;
#10;
rst_n = 1'b1;
end
endmodule
编写command.do脚本。
cd F:/modelsim_workspace/uvm_learning/test0
vlib work
set UVM_HOME F:/modelsim_workspace/uvm_learning/uvm-1.1d/uvm-1.1d
set WORK_HOME F:/modelsim_workspace/uvm_learning/test0
vlog +incdir+$UVM_HOME/src -L mtiAvm -L mtiOvm -L mtiUvm -L mtiUPF $UVM_HOME/src/uvm_pkg.sv $WORK_HOME/dut.sv top_tb.sv
vsim -sv_lib F:/tools/Modelsim/setup/uvm-1.2/win64/uvm_dpi work.top_tb
4.vlog命令用于编译verilog代码,编译systemverilog或者vhdl的命令参考modelsim user guide。
5.vsim表示运行仿真,-sv_lib 对应uvm的一个路径。其中参数“-c”表示进入命令行模式,如果没有该参数,则表示进行GUI模式。vsim -sv_lib F:/tools/Modelsim/setup/uvm-1.2/win64/uvm_dpi work.top_tb ,uvm_dpi是modelsim安装目录下的动态链接库。
在modelsim命令窗口键入, do F:/modelsim_workspace/uvm_learning/test0/command.do运行脚本。仿真界面和结果如下所示:
下载modelsim安装包解压安装后,在modelsim安装目录下已经有编译好的uvm_dpi.dll(有不同版本的可以根据需要调用),为了避免麻烦和出错,不需要手动编译uvm_dpi.dll也可以在uvm框架下实现仿真。
1.安装modelsim se 10.1a
2.下载uvm_1.1d
然后解压缩后,拷贝到modelsim安装目录的../verilog_src/目录下,我的目录是C:\software\modeltech_10.1a\verilog_src.这里注意,拷贝过来之后,打开uvm_1.1d文件夹,应该能直接看到bin/docs/examples/src/等文件夹和几个txt文件。
3.配置系统环境变量。打开modelsim,在vsim>命令行下输入
vsim n>set UVM_HOME c:/software/modeltech_10.1a/verilog_src/uvm-1.1d
vsim n>set MODEL_TECH c:/software/modeltech_10.1a/win32
(也可以设置为系统环境变量)
4.编译uvm_1.1d库文件。所谓编译库文件,我的理解是将uvm_1.1d编译成windows中modelsim可以加载的dll文件,因此这一个步骤是生成一个.dll文件的过程。这里需要GCC的编译命令,最新的是(modelsim-gcc-4.2.1-mingw32vc9)
解压缩后,复制到modelsim安装目录下,我的复制目录是(C:\software\modeltech_10.1a\gcc-4.2.1-mingw32vc9),打开该文件后能够直接看到bin/doc/include/info/lib/libexec/man/share文件夹,上面这些基本工作做完后,就可以编译.dll文件了。
5.在vsim命令行下输入
vsim n>c:/software/modeltech_10.1a/gcc-4.2.1-mingw32vc9/bin/g++.exe -DQUESTA -W -shared -Bsymbolic -I $MODEL_TECH/../include $UVM_HOME/src/dpi/uvm_dpi.cc -o $UVM_HOME/lib/uvm_dpi.dll $MODEL_TECH/mtipli.dll -lregex
注意,要先在$UVM_HOME目录下创建lib文件夹。
6.下载hello_world.sv
创建modelsim工程,添加hello_world.sv文件。假设工程目录为 C:/modelsim_uvm/
7.编译Hello_world_example源文件
vsim n>vlog +incdir+$UVM_HOME/src -L mtiAvm -L mtiOvm -L mtiUvm -L mtiUPF C:/modelsim_uvm/hello_world.sv
8.仿真Hello_world_example(需要调用刚刚编译的uvm_dpi.dll)
vsim n>vsim -c -sv_lib $UVM_HOME/lib/uvm_dpi work.hello_world_example
选run 100ns
参考:UVM仿真环境搭建_fpga uvm_FPGA硅农的博客-CSDN博客
参考:https://www.cnblogs.com/love29850706/p/6079367.html