微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 微电子和IC设计 > IC验证交流 > ovm学习的一点小积累

ovm学习的一点小积累

时间:10-02 整理:3721RD 点击:
学习可能始于模仿。学习新的软件工具往往先要借助一些实例,有时也急于见到结果,看看到底能得到了什么?

我们先介绍一个OVM实例,类似的例子可在网上找得到。可与本例比较一下,看看有什么不同。由于篇幅所限,注释可能过于简洁。参见的部分可要认真阅读才会有好的收获哟。

从www.ovmworld.com网站下载的OVM框架工具里有很多实例,可供学习了解OVM之用。有空可以去看看,现在uvm出世之后 好像变为了http://www.verificationacademy.com/verification-methodology,以下实例是我当时学习的时候在“杜蕾斯”网站上面看到的

`include "ovm_macros.svh"
interface io_if();
logic [7:0] address;
logic [7:0] data_i;
logic [7:0] data_o;
logic rw_n;
modport memory_if(input address, input data_i,
output data_o, input rw_n);// DUT接口
modport test_if(output address, output data_i,
input data_o, output rw_n);// 测试模块接口,本文没有用到

endinterface


//===============================================
module memory(io_if.memory_if io, input bit clock);
reg [7:0] mem [0:255];
always @(negedge clock)
if(io.rw_n)
io.data_o<=mem[io.address];
else
mem[io.address]<=io.data_i;
endmodule


//===================================================
package my_pkg;
import ovm_pkg::*;
//〖原则〗验证程序中的事件要继承ovm_transaction:
class my_transaction extends ovm_transaction;//

rand logic [7:0] address;
rand logic [7:0] data_i;
rand logic rw_n;

function new (string name = "");
super.new(name);
endfunction: new

constraint c_address { address >= 0; address < 256; }//产生随机事件的约束条件
constraint c_data_i{ data_i>= 0; data_i< 256; }

virtual function void randomize_();//如果randomize()函数不能用时,用此函数
address = $random & 8'hff;//$random产生32bit随机数,这里只需要8bit
data_i= $random & 8'hff;
rw_n= $random & 1'b1;
endfunction


`ovm_object_utils_begin(my_transaction)//在程序中注册此事件
`ovm_field_int(address, OVM_ALL_ON + OVM_DEC)//
`ovm_field_int(data_i,OVM_ALL_ON + OVM_DEC)
`ovm_field_int(rw_n,OVM_ALL_ON + OVM_BIN)
`ovm_object_utils_end

endclass: my_transaction
//〖建议〗验证程序中连接DUT的驱动器可继承ovm_driver:
class my_driver extends ovm_driver;//
`ovm_component_utils(my_driver)//注册本类,这个宏的结尾没有符号;
virtual io_if v_io;//装载虚拟接口
ovm_get_port #(my_transaction) get_port;//装载与激励发生器通信的通道接口:

function new(string name, ovm_component parent);
super.new(name, parent);
//〖建议〗验证程序中可写一些ovm_report_info的语句供提示用:
ovm_report_info("", "Called my_driver::new");//在测试结果显示此函数被调用
endfunction: new

function void build;
super.build();
ovm_report_info("", "Called my_driver::build");
get_port = new("get_port", this);//初始化
endfunction : build

virtual task run;
ovm_report_info("", "Called my_driver::run");
forever
begin
my_transaction tx;
#100 get_port.get(tx);//从通道中取一个事件
ovm_report_info("",$psprintf("Driving cmd = %s, address = %2h, data_i = %2h",
(tx.rw_n ? "R" : "W"), tx.address, tx.data_i));
v_io.memory_if.address = tx.address;//送到DUT
v_io.memory_if.data_i= tx.data_i;
v_io.memory_if.rw_n= tx.rw_n;
end
endtask: run

endclass: my_driver



//〖建议〗一般用继承ovm_env的类包装验证程序中的事件处理器-元件
class my_env extends ovm_env;//
`ovm_component_utils(my_env)//注册本类

ovm_random_stimulus #(my_transaction) env_stimulus;//装载激励器
tlm_fifo#(my_transaction) env_fifo;//装载通道
my_driverenv_driver;//装载驱动器

function new(string name = "my_env", ovm_component parent = null);
super.new(name, parent);
ovm_report_info("", "Called my_env::new");
endfunction: new

virtual function void build;
super.build();
ovm_report_info("", "Called my_env::build");
env_stimulus = new("env_stimulus", this);//初始化激励器
env_fifo= new("env_fifo",this);//初始化通道
env_driver= new("env.driver",this);//初始化驱动器
endfunction: build

virtual function void connect;//设定连接关系
ovm_report_info("", "Called my_env::connect");
env_stimulus.blocking_put_port.connect(env_fifo.put_export);//激励器侧接口-放事件
env_driver.get_port.connect(env_fifo.get_export);//驱动器侧接口-取事件
endfunction: connect


virtual function void configure;//
ovm_report_info("", "Called my_env::configure");
env_stimulus.set_report_id_action("stimulus generation", OVM_NO_ACTION);//限制显示信息
endfunction: configure//你可删除上一行,看看有什么变化?

task run();
ovm_report_info("","Called my_env::run");
endtask: run

virtual function void report;
ovm_report_info("", "Called my_env::report");
endfunction: report
//在运行下面的run_test()函数时,以上函数将自动依次运行
endclass: my_env
endpackage: my_pkg



`timescale 1ns/1ps
module top;
import ovm_pkg::*;
import my_pkg::*;
parameter clock_cycle = 100;
bit clock;

io_if my_io();//装载接口
memory memory1(.io(my_io), .clock(clock));//装载DUT


//〖建议〗在验证程序顶级模块中一般采用继承ovm_test的类包装继承 ovm_env的类
class my_test extends ovm_test;
`ovm_component_utils(my_test)//注册本类
my_env top_env;//装载环境-top_env


function new(string name = "my_test", ovm_component parent = null);
super.new(name,parent);
ovm_report_info("", "Called my_test::new");
endfunction: new


virtual function void build;
super.build();
ovm_report_info("", "Called my_test::build");
top_env=new();//初始化
//〖建议〗在验证程序中可设定看门狗
set_global_timeout(3us);
endfunction: build



virtual function void connect;
ovm_report_info("", "Called my_test::connect");
top_env.env_driver.v_io = my_io;//连接虚拟接口到驱动器的物理接口
endfunction: connect


task run;
my_transaction tx;
tx = new();
ovm_report_info("", "Called my_test::run");
top_env.env_stimulus.generate_stimulus(tx, 20);//激励器产生20个事件
endtask: run

endclass: my_test


initial
run_test("my_test");//全球函数-验证程序的起始点


initial begin
clock=0;
forever begin
#(clock_cycle/2)
clock = ~clock;//产生时钟信号,供模拟器作比对用
end
end

endmodule: top

谢谢小编的分享,我来顶一下!

小编的学习方法不错。谢谢分享。

好长啊,先顶后看

谢谢分享

谢谢分享

谢谢指导!

C++ 结合verilog

给小编赞一个

小编真有心

有点看不懂,先顶一个,慢慢看!

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top