電子錶設計與驗證(時鐘頻率選擇模組驗證)
阿新 • • 發佈:2021-02-02
電子錶設計與驗證(時鐘頻率選擇模組驗證)
利用UVM搭建簡單驗證平臺
package div_pkg;
import uvm_pkg::*;
`include "uvm_macros.svh"
class div_trans extends uvm_sequence_item;
rand int div_n;
rand int clk_out;
constraint divc{
div_n inside {[10:50]};
};
`uvm_object_utils_begin (div_trans)
`uvm_field_int(div_n,UVM_ALL_ON)
`uvm_field_int(clk_out,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "div_trans");
super.new(name);
endfunction
endclass
class div_driver extends uvm_driver #(div_trans);
virtual div_inter intf;
`uvm_component_utils (div_driver)
function new(string name = "div_driver", uvm_component parent);
super.new(name,parent);
endfunction
function void set_interface(virtual div_inter intf);
this.intf = intf;
endfunction
task run_phase (uvm_phase phase);
super.run_phase(phase);
fork
this .do_driver();
this.do_reset();
join
endtask
task do_driver();
div_trans req,rsp;
forever begin
repeat (100) @(posedge intf.clk)
seq_item_port.get_next_item(req);
this.write(req);
void'($cast(rsp,req.clone()));
rsp.set_sequence_id(req.get_sequence_id());
seq_item_port.item_done(rsp);
end
endtask
task write(input div_trans t);
intf.div_cb.div_n <= t.div_n;
endtask
task do_reset();
forever begin
@(negedge intf.rstn);
intf.div_cb.div_n <= 10;
end
endtask
endclass
class div_sequencer extends uvm_sequencer #(div_trans);
`uvm_component_utils(div_sequencer)
function new(string name = "div_sequencer", uvm_component parent);
super.new(name,parent);
endfunction
endclass
class div_sequence extends uvm_sequence #(div_trans);
virtual div_inter intf;
rand int div_n = -1;
rand int clk_out = -1;
`uvm_object_utils_begin(div_trans)
`uvm_field_int(div_n,UVM_ALL_ON)
`uvm_field_int(clk_out,UVM_ALL_ON)
`uvm_object_utils_end
function new (string name = "div_sequence");
super.new(name);
endfunction
function void set_interface (virtual div_inter intf);
this.intf = intf;
endfunction
task body();
repeat (50) gen();
endtask
task gen();
div_trans req,rsp;
`uvm_do_with(req, {
local::div_n >= 0 -> div_n == local::div_n;
local::clk_out >= 0 -> clk_out == local::clk_out;
})
get_response(rsp);
endtask
endclass
typedef struct packed {
int clk_out;
} div_mon;
class div_monitor extends uvm_monitor;
local virtual div_inter intf;
`uvm_component_utils(div_monitor)
function new(string name = "div_monitor", uvm_component parent);
super.new(name,parent);
endfunction
function void set_interface (virtual div_inter intf);
this.intf = intf;
endfunction
task run_phase (uvm_phase phase);
super.run_phase(phase);
this.do_mon();
endtask
task do_mon();
div_mon mon;
forever begin
@(posedge intf.clk);
mon.clk_out = intf.div_cb.clk_out;
`uvm_info(get_type_name(),$sformatf("monitored TIME hour 'h%8x ",mon.clk_out ),UVM_HIGH)
end
endtask
endclass
class div_agent extends uvm_agent;
virtual div_inter intf;
div_driver driver;
div_monitor monitor;
div_sequencer sequencer;
`uvm_component_utils(div_agent)
function new (string name = "div_agent", uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
driver = div_driver::type_id::create("driver",this);
monitor = div_monitor::type_id::create("monitor",this);
sequencer = div_sequencer::type_id::create("sequencer",this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
driver.seq_item_port.connect(sequencer.seq_item_export);
this.set_interface(intf);
endfunction
function void set_interface(virtual div_inter intf);
this.intf = intf;
driver.set_interface(intf);
monitor.set_interface(intf);
endfunction
endclass
class div_test extends uvm_test;
div_agent agent;
virtual div_inter intf;
`uvm_component_utils(div_test)
function new (string name = "div_test", uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase (uvm_phase phase);
super.build_phase(phase);
agent = div_agent::type_id::create("agent",this);
if(!uvm_config_db#(virtual div_inter)::get(this,"","intf",intf)) begin
`uvm_fatal("GETINTF","cannot get intf handle from config DB")
end
endfunction
function void set_interface(virtual div_inter intf);
this.intf = intf;
agent.set_interface(intf);
endfunction
function void connect_phase (uvm_phase phase);
super.connect_phase(phase);
this.set_interface(intf);
endfunction
task run_phase (uvm_phase phase);
div_sequence seq;
phase.raise_objection(this);
seq = new("seq");
seq.start(agent.sequencer);
phase.drop_objection(this);
endtask
endclass
endpackage
頂層模組
`timescale 1ns/1ps
import uvm_pkg::*;
`include "uvm_macros.svh"
interface div_inter(input clk, input rstn);
logic clk_out;
logic [31:0]div_n;
clocking div_cb @(posedge clk);
default input #1ns output #1ns;
input clk_out;
output div_n;
endclocking
endinterface
module div_tb();
logic clk;
logic rstn;
int_div dut(
.clk (clk)
,.rstn (rstn)
,.clk_out (intf.clk_out)
,.div_n (intf.div_n)
);
initial begin
clk <= 0;
forever begin
#5 clk <= ~clk;
end
end
initial begin
rstn <= 0;
repeat (10) @(posedge clk)begin
rstn <= 1;
end
end
import div_pkg::*;
div_inter intf(.*);
initial begin
uvm_config_db #(virtual div_inter)::set(uvm_root::get(),"uvm_test_top","intf",intf);
run_test("div_test");
end
endmodule
模擬結果