uvm_model

很早之前就说写一个简单的uvm环境

首先是一个简单的dut

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
`timescale lns/10fs
module mul(
clk,
rst_n,
num_a,
num_b,
num_c
);

input clk;
input rst__n;
input [7:0] num__a;
input [7:0] num__b;
output [7:0] num__c;

reg [7:0] a;
reg [7:0] b;
reg [7:0] c;

assign num_c = c;

always @(posedge clk or negedge rst_n)begin
if (!rst_n == l'bl)begin
c <= 8'h0;
end else begin
c <= num_a + num_b;
end
end

endmodule
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
`timescale lns/10fs
module top(
clk,
rst_n,
num_a,
num_b,
num_c
);
input clk;
input rst_n;
input [7:0] num_a;
input [7:0] num_b;
output [7:0] num_c;
mul U_MUL(
. clk(clk),
. rst_n(rst_n),
. num_a(num_a),
. num_b(num_b),
. num_c(num_c)
);
endmodule

之后是harness

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
module harness;
logic elk;
logic rst_n;
logic [7:0] num_a;
logic [7:0] num_b;
logic [7:0] num_c;

initial begin
clk = 0;
rst_n = 0;
#100ns rst_n = 1;
end

always begin
#5ns clk = ~clk;
end

my_interface tx_if(clk,rst_n);
my_interface rx_if(clk,rst_n);

top dut(
.clk(clk),
.rst_n(rst_n),
.num_a(num_a),
.num_b(num_b),
.num_c(num_c)
);

initial begin
uvm_config_db #(virtual my_interface) :: set(null, "uvm_test_top.env_.rx_agt*", "vif", rx_if);
uvm_config_db #(virtual my_interface) :: set(null, "uvm_test_top.env_.tx_agt*", "vif", tx_if);
end

initial begin
run_test();
end

assign num_a = tx_if.a;
assign num_b = tx_if.b;
assign rx_if.c = num_c;

initial begin
$vcdpluson;
$fsdbDumpon;
end

endmodule

之后是interface

1
2
3
4
5
6
7
8
9
10
11
12
13
interface my_interface(input bit clk,input bit rst_n);

logic [7:0] a;
logic [7:0] b;
logic [7:0] c;

clocking mon_cb@(posedge clk);
inout a;
inout b;
inout c;
endclocking

endinterface

之后是transaction

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class my_transaction extends extends uvm_sequence_item; 
rand bit [7:0] a;
rand bit [7:0] b;
rand bit [7:0] c;
rand byte kk[];

constraint k_cons{
kk.size >= 10;
kk.size <= 90;
}

`uvm_object_utils_begin(my_transaction)
//'uvm_field_int(a,UVM_ALL_0N)
//'uvm_field_int(b,UVM_ALL_0N)
`uvm_field_int(c,UVM_ALL_0N)
`uvm_field_array_int(kk,UVM_ALL_0N)
`uvm_object_utils_end

extern function new(string name = "my_transaction");

endclass

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

之后是sequencer

1
2
3
4
5
6
7
8
9
10
class my_sequencer extends uvm_sequencer #(my_transaction);

`uvm_component_utils(my_sequencer)
extern function new(string name, uvm_component parent);

endclass

function my_sequencer::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

之后是tx部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class tx_driver extends uvm_driver #(my_transaction); 

virtual my_interface vif;

`uvm_component_utils(tx_driver)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task reset_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function tx_driver::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void tx_driver::build_phase(uvm_phase phase);
super.build_phase(phase);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
`uvm_fatal("tx_driver","virtual interface get fail !");
endfunction

task tx_driver::reset_phase(uvm_phase phase);

vif.a <= $urandom_range(8'hff,8'h0);
vif.b <= $urandom_range(8'hff,8'h0);

endtask

task tx_driver::main_phase(uvm_phase phase);

my_transaction tx_tr;

super.main_phase(phase);

while(l)begin
seq_item_port.get_next_item(req);
tx_tr = req;
vif.a <= tx_tr.a;
vif.b <= tx_tr.b;
seq_item_port.item_done();
end

endtask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class tx_monitor extends uvm_monitor;

virtual my_interface vif;
uvm_analysis_port #(my_transaction) tx_mon_ap;
`uvm_component_utils(tx_monitor)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function tx_monitor::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void tx_monitor::build_phase(uvm_phase phase);

super.build_phase(phase);
tx_mon_ap = new("tx_mon_ap", this);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
`uvm_fatal("tx_monitor","virtual interface get fail !");

endfunction

task tx_monitor::main_phase(uvm_phase phase);

my_transaction tx_tr;
super.main_phase(phase);

while(l)begin
tx_tr = new();
tx_tr.a = vif.a;
tx_tr.b = vif.b;
tx_mon_ap.write(tx_tr);
@(posedge vif.clk);
end

endtask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class tx_agent extends uvm_agent;

tx_monitor mon;
tx_driver drv;
my_sequencer sqr;
uvm_analysis_port #(my_transaction) ap;
`uvm_component_utils(tx_agent)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function tx_agent::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void tx_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
mon = tx_monitor ::type_id:: create ("mon", this);
drv = tx_driver ::type_id:: create ("drv", this);
sqr = my_sequencer ::type_id:: create ("sqr", this);
endfunction

function void tx_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap = mon.tx_mon_ap;
drv.seq_item_port.connect(sqr.seq_item_export);
endfunction

task tx_agent::main_phase(uvm_phase phase);
super.main_phase(phase);
endtask

之后是rx部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
class rx_monitor extends uvm_monitor; 

virtual my_interface vif;
uvm_analysis_port #(my_transaction) rx_mon_ap;
`uvm_component_utils(rx_monitor)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function rx_monitor::new(string new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void rx_monitor::build_phase(uvm_phase phase);
super.build_phase(phase);
rx_mon_ap = new("rx_mon_ap", this);
if (!uvm_config_db#(virtual my_interface)::get(this,"","vif",vif))
'uvm_fatal("rx_monitor","virtual interface get fail !");
endfunction

task rx_monitor::main_phase(uvm_phase phase);
my_transaction rx_tr;
super.main_phase(phase);
while(l)begin
rx_tr=new();
@(posedge vif.clk);
rx_tr.c = vif.c;
rx_mon_ap.write (rx_tr);
end
endtask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class rx_agent extends uvm_agent; 

rx_monitor mon;
uvm_analysis_port #(my_transaction) ap;
`uvm_component_utils(rx_agent)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function rx_agent::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void rx_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
mon = rx_monitor::type_id::create("mon",this);
endfunction

function void rx_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
ap = mon.rx_mon_ap;
endfunction

task rx_agent::main_phase(uvm_phase phase);
super.main_phase(phase);
endtask

之后是env

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class env extends uvm_env;

rx_agent rx_agt;
tx_agent tx_agt;
rm rm_;
scoreboard sc;
`uvm_component_utils(env)

uvm_tlm_analysis_fifo #(my_transaction) mon_rm_fifo;
uvm_tlm_analysis_fifo #(my_transaction) rm_sc_fifo;
uvm_tlm_analysis_fifo #(my_transaction) sc_mon_fifo;

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task configure_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function env::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void env::build_phase(uvm_phase phase);

super.build_phase(phase);

rx_agt = rx_agent ::type_id:: create ("rx_agt", this);
tx_agt = tx_agent ::type_id:: create ("tx_agt", this);
rm_ = rm ::type_id:: create ("rm_ " , this);
sc = scoreboard ::type_id:: create ("sc " , this);
mon_rm_fifo = new("mon_rm_fifo", this);
rm_sc_fifo = new("rm_sc_fifo", this);
sc_mon_fifo = new("sc_mon_fifo", this);

endfunction

function void env::connect_phase(uvm_phase phase);

super.connect_phase(phase);

tx_agt.ap. connect(mon_rm_fifo.analysis_export);
rm_.port. connect(mon_rm_fifo.blocking_get_export);
rm_.rm_ap. connect (rm_sc_fifo.analysis_export);
sc.rm_port. connect (rm_sc_fifo.blocking_get_export);
rx_agt.ap. connect(sc_mon_fifo.analysis_export);
sc.dut_port.connect(sc_mon_fifo.blocking_get_export);

endfunction

task env::configure_phase(uvm_phase phase);
super.configure_phase(phase);
endtask

task env::main_phase(uvm_phase phase);
super,main_phase(phase);
endtask

之后是rm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class rm extends uvm_component;

uvm_blocking_get_port #(my_transaction) port;
uvm_analysis_port #(my_transaction) rm_ap;

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

`uvm_component_utils(rm)

endclass

function rm::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void rm::build_phase(uvm_phase phase);
super.build_phase(phase);
port = new("port", this);
rm_ap = new("rm_ap",this);
endfunction

task rm::main_phase(uvm_phase phase);

my_transaction tr;
my_transaction send_tr;

super.main_phase(phase);

while(l)begin
port.get(tr);
send_tr = new("send_tr");
send_tr = tr;
send_tr.c = send_tr.a + send_tr.b;
rm_ap.write(send_tr);
end

endtask
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class scoreboard extends extends uvm_scoreboard; 

my_transaction rm_queue[$];
uvm_blocking_get_port #(my_transaction) rm_port;
uvm_blocking_get_port #(my_transaction) dut_port;
`uvm_component_utils(scoreboard)

extern function new(string name, uvm_component parent);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);
extern virtual task main_phase(uvm_phase phase);

endclass

function scoreboard::new(string name, uvm_component parent);
super.new(name,parent);
endfunction

function void scoreboard::build_phase(uvm_phase phase);
super.build_phase(phase);
rm_port = new("rm_port ",this);
dut_port = new("dut_port", this);
endfunction

function void scoreboard::connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction

task scoreboard::main_phase(uvm_phase phase);

my_transaction rm_tr, dut_tr, chk_tr;

super.main_phase(phase);

fork

while(l)begin
rm_port.get(rm_tr);
rm_queue.push_back(rm_tr);
end

while(l)begin
dut_port.get(dut_tr);
if (rm_queue.size() > 0)begin
chk_tr = rm_queue.pop_front();
if(dut_tr.compare(chk_tr)) begin
`uvm_info("scoreboard", "ok", UVM_L0W);
dut_tr.print ();
chk_tr.print ();
end else begin
`uvm_error("scoreboard", "fail");
end
end

join

endtask
作者

Mch Wang

发布于

2021-01-24

更新于

2021-10-03

许可协议

评论