UVM验证平台
时间:2024-01-04 15:07:01
参考:《UVM实战》 张强 着
文章目录
- UVM 框架
- DUT
- testbench top
-
- interface
- my_case0
-
- base_test
-
- env
-
- agent
-
- tarnsaction
- sequence
- sequencer
- driver
- monitor
- reference_model
- scoreboard
UVM 框架
DUT
1 module dut(clk, 2 rst_n, 3 rxd, 4 rx_dv, 5 txd, 6 tx_en); 7 input clk; 8 input rst_n; 9 input[7:0] rxd; 10 input rx_dv; 11 output [7:0] txd; 12 output tx_en; 13 14 reg[7:0] txd; 15 reg tx_en; 16 17 always @(posedge clk) begin 18 if(!rst_n) begin 19 txd <= 8'b0; 20 tx_en <= 1'b0; 21 end 22 else begin 23 txd <= rxd; 24 tx_en <= rx_dv; 25 end 26 end 27 endmodule
testbench top
1 `timescale 1ns/1ps 2 `include "uvm_macros.svh" 3 4 import uvm_pkg::*;
5 `include "my_if.sv"
6 `include "my_transaction.sv"
7 //`include "my_sequence.sv"
8 `include "my_driver.sv"
9 `include "my_monitor.sv"
10 `include "my_sequencer.sv"
11 `include "my_agent.sv"
12 `include "my_model.sv"
13 `include "my_scoreboard.sv"
14 `include "my_env.sv"
15 `include "base_test.sv"
16 `include "my_case0.sv"
17 `include "my_case1.sv"
18
19 module top_tb;
20
21 reg clk;
22 reg rst_n;
23 reg[7:0] rxd;
24 reg rx_dv;
25 wire[7:0] txd;
26 wire tx_en;
27
28 my_if input_if(clk, rst_n);
29 my_if output_if(clk, rst_n);
30
31 dut my_dut(.clk(clk),
32 .rst_n(rst_n),
33 .rxd(input_if.data),
34 .rx_dv(input_if.valid),
35 .txd(output_if.data),
36 .tx_en(output_if.valid));
37
38 initial begin
39 clk = 0;
40 forever begin
41 #100 clk = ~clk;
42 end
43 end
44
45 initial begin
46 rst_n = 1'b0;
47 #1000;
48 rst_n = 1'b1;
49 end
50
51 initial begin
52 //run_test("my_env");
53 run_test();
54 end
55
56 initial begin
57 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
58 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);
59 uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);
60 end
61
62 endmodule
interface
1 `ifndef MY_IF__SV
2 `define MY_IF__SV
3
4 interface my_if(input clk, input rst_n);
5
6 logic [7:0] data;
7 logic valid;
8 endinterface
9
10 `endif
my_case0
1 `ifndef MY_CASE0__SV
2 `define MY_CASE0__SV
3 class case0_sequence extends uvm_sequence #(my_transaction);
4 my_transaction m_trans;
5
6 function new(string name= "case0_sequence");
7 super.new(name);
8 endfunction
9
10 virtual task body();
11 if(starting_phase != null)
12 starting_phase.raise_objection(this);
13 repeat (10) begin
14 `uvm_do(m_trans)
15 end
16 #100;
17 if(starting_phase != null)
18 starting_phase.drop_objection(this);
19 endtask
20
21 `uvm_object_utils(case0_sequence)
22 endclass
23
24
25 class my_case0 extends base_test;
26
27 function new(string name = "my_case0", uvm_component parent = null);
28 super.new(name,parent);
29 endfunction
30 extern virtual function void build_phase(uvm_phase phase);
31 `uvm_component_utils(my_case0)
32 endclass
33
34
35 function void my_case0::build_phase(uvm_phase phase);
36 super.build_phase(phase);
37
38 uvm_config_db#(uvm_object_wrapper)::set(this,
39 "env.i_agt.sqr.main_phase",
40 "default_sequence",
41 case0_sequence::type_id::get());
42 endfunction
43
44 `endif
base_test
1 `ifndef BASE_TEST__SV
2 `define BASE_TEST__SV
3
4 class base_test extends uvm_test;
5
6 my_env env;
7
8 function new(string name = "base_test", uvm_component parent = null);
9 super.new(name,parent);
10 endfunction
11
12 extern virtual function void build_phase(uvm_phase phase);
13 extern virtual function void report_phase(uvm_phase phase);
14 `uvm_component_utils(base_test)
15 endclass
16
17
18 function void base_test::build_phase(uvm_phase phase);
19 super.build_phase(phase);
20 env = my_env::type_id::create("env", this);
21 //uvm_config_db#(uvm_object_wrapper)::set(this,
22 //"env.i_agt.sqr.main_phase",
23 //"default_sequence",
24 // my_sequence::type_id::get());
25 endfunction
26
27 function void base_test::report_phase(uvm_phase phase);
28 uvm_report_server server;
29 int err_num;
30 super.report_phase(phase);
31
32 server = get_report_server();
33 err_num = server.get_severity_count(UVM_ERROR);
34
35 if (err_num != 0) begin
36 $display("TEST CASE FAILED");
37 end
38 else begin
39 $display("TEST CASE PASSED");
40 end
41 endfunction
42
43 `endif
env
1 `ifndef MY_ENV__SV
2 `define MY_ENV__SV
3
4 class my_env extends uvm_env;
5
6 my_agent i_agt;
7 my_agent o_agt;
8 my_model mdl;
9 my_scoreboard scb;
10
11 uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;
12 uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
13 uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;
14
15 function new(string name = "my_env", uvm_component parent);
16 super.new(name, parent);
17 endfunction
18
19 virtual function void build_phase(uvm_phase phase);
20 super.build_phase(phase);
21 i_agt = my_agent::type_id::create("i_agt", this);
22 o_agt = my_agent::type_id::create("o_agt", this);
23 i_agt.is_active = UVM_ACTIVE;
24 o_agt.is_active = UVM_PASSIVE;
25 mdl = my_model::type_id::create("mdl", this);
26 scb = my_scoreboard::type_id::create("scb", this);
27 agt_scb_fifo = new("agt_scb_fifo", this);
28 agt_mdl_fifo = new("agt_mdl_fifo", this);
29 mdl_scb_fifo = new("mdl_scb_fifo", this);
30
31 endfunction
32
33 extern virtual function void connect_phase(uvm_phase phase);
34
35 `uvm_component_utils(my_env)
36 endclass
37
38 function void my_env::connect_phase(uvm_phase phase);
39 super.connect_phase(phase);
40 i_agt.ap.connect(agt_mdl_fifo.analysis_export);
41 mdl.port.connect(agt_mdl_fifo.blocking_get_export);
42 mdl.ap.connect(mdl_scb_fifo.analysis_export);
43 scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
44 o_agt.ap.connect(agt_scb_fifo.analysis_export);
45 scb.act_port.connect(agt_scb_fifo.blocking_get_export);
46 endfunction
47
48 `endif
agent
1 `ifndef MY_AGENT__SV
2 `define MY_AGENT__SV
3
4 class my_agent extends uvm_agent ;
5 my_sequencer sqr;
6 my_driver drv;
7 my_monitor mon;
8
9 uvm_analysis_port #(my_transaction) ap;
10
11 function new(string name, uvm_component parent);
12 super.new(name, parent);
13 endfunction
14
15 extern virtual function void build_phase(uvm_phase phase);
16 extern virtual function void connect_phase(uvm_phase phase);
17
18 `uvm_component_utils(my_agent)
19 endclass
20
21
22 function void my_agent::build_phase(uvm_phase phase);
23 super.build_phase(phase);
24 if (is_active == UVM_ACTIVE) begin
25 sqr = my_sequencer::type_id::create("sqr",this);
26 drv = my_driver::type_id::create("drv", this);
27 end
28 mon = my_monitor::type_id::create("mon", this);
29 endfunction
30
31 function void my_agent::connect_phase(uvm_phase phase);
32 super.connect_phase(phase);
33 if(is_active == UVM_ACTIVE)begin
34 drv.seq_item_port.connect(sqr.seq_item_export);
35 end
36 ap = mon.ap;
37 endfunction
38
39 `endif
tarnsaction
1 `ifndef MY_TRANSACTION__SV
2 `define MY_TRANSACTION__SV
3
4 class my_transaction extends uvm_sequence_item;
5
6 rand bit[47:0] dmac;
7 rand bit[47:0] smac;
8 rand bit[15:0] ether_type;
9 rand byte pload[];
10 rand bit[31:0] crc;
11
12 constraint pload_cons{
13 pload.size >= 46;
14 //pload.size <= 1500;
15 pload.size <= 200;
16 dmac == 48'h01_02_03_04_05_06;
17 smac == 48'h60_50_40_30_20_10;
18 }
19
20
21 function bit[31:0] calc_crc();
22 return 32'h0;
23 endfunction
24
25 function void post_randomize();
26 crc = calc_crc;
27 endfunction
28
29 //`uvm_object_utils(my_transaction)
30 `uvm_object_utils_begin(my_transaction)
31 `uvm_field_int(dmac,UVM_ALL_ON)
32 `uvm_field_int(smac,UVM_ALL_ON)
33 `uvm_field_int(ether_type,UVM_ALL_ON)
34 `uvm_field_array_int(pload,UVM_ALL_ON)
35 `uvm_field_int(crc,UVM_ALL_ON)
36 `uvm_object_utils_end
37
38 function new(string name = "my_transaction");
39 super.new();
40 endfunction
41
42 /*function void my_print(); 43 $display("dmac = %0h", dmac); 44 $display("smac = %0h", smac); 45 $display("ether_type = %0h", ether_type); 46 for(int i = 0; i < pload.size; i++) begin 47 $display("pload[%0d] = %0h", i, pload[i]); 48 end 49 $display("crc = %0h", crc); 50 endfunction 51 52 function void my_copy(my_transaction tr); 53 if(tr == null) 54 `uvm_fatal("my_transaction", "tr is null!!!!") 55 dmac = tr.dmac; 56 smac = tr.smac; 57 ether_type = tr.ether_type; 58 pload = new[tr.pload.size()]; 59 for(int i = 0; i < pload.size(); i++) begin 60 pload[i] = tr.pload[i]; 61 end 62 crc = tr.crc; 63 endfunction 64 65 function bit my_compare(my_transaction tr); 66 bit result; 67 68 if(tr == null) 69 `uvm_fatal("my_transaction", "tr is null!!!!") 70 result = ((dmac == tr.dmac) && 71 (smac == tr.smac) && 72 (ether_type == tr.ether_type) && 73 (crc == tr.crc)); 74 if(pload.size() != tr.pload.size()) 75 result = 0; 76 else 77 for(int i = 0; i < pload.size(); i++) begin 78 if(pload[i] != tr.pload[i]) 79 result = 0; 80 end 81 return result; 82 endfunction*/
83
84 endclass
85 `endif
sequence
1 class my_sequence extends uvm_sequence #(my_transaction);
2 my_transaction m_trans;
3
4 function new(string name="my_sequence");
5 super.new(name);
6 endfunction
7
8 virtual task body();
9 if(starting_phase != null)
10 starting_phase.raise_objection(this);
11
12 repeat(10) begin
13 `uvm_do(m_trans)
14 end
15 #1000;
16
17 if(starting_phase != null)
18 starting_phase.drop_objection(this);
19 endtask
20
21 `uvm_object_utils(my_sequence)
22
23 endclass
sequencer
1 `ifndef MY_SEQUENCER__SV
2 `define MY_SEQUENCER__SV
3
4 class my_sequencer extends uvm_sequencer #(my_transaction);
5
6 function new(string name, uvm_component parent);
7 super.new(name, parent);
8 endfunction
9
10 `uvm_component_utils(my_sequencer)
11 endclass
12
13 `endif
driver
1 `ifndef MY_DRIVER__SV
2 `define MY_DRIVER__SV
3 class my_driver extends uvm_driver#(my_transaction);
4
5 virtual my_if vif;
6
7 `uvm_component_utils(my_driver)
8 function new(string name = "my_driver", uvm_component parent = null);
9 super.new(name, parent);
10 endfunction
11
12 virtual function void build_phase(uvm_phase phase);
13 super.build_phase(phase);
14 if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
15 `uvm_fatal("my_driver", "virtual interface must be set for vif!!!")
16 endfunction
17
18 extern task main_phase(uvm_phase phase);
19 extern task drive_one_pkt(my_transaction tr);
20 endclass
21
22 /*task my_driver::main_phase(uvm_phase phase); 23 my_transaction tr; 24 phase.raise_objection(this); 25 vif.data <= 8'b0; 26 vif.valid <= 1'b0; 27 while(!vif.rst_n) 28 @(posedge vif.clk); 29 for(int i = 0; i < 2; i++) begin 30 req = new("req"); 31 assert(req.randomize() with {pload.size == 200; 32 dmac == 48'h01_02_03_04_05_06; 33 smac == 48'h60_50_40_30_20_10; 34 } 35 ); 36 drive_one_pkt(req); 37 end 38 repeat(5) @(posedge vif.clk); 39 phase.drop_objection(this); 40 endtask*/
41
42 task my_driver::main_phase(uvm_phase phase);
43 vif.data <= 8'b0;
44 vif.valid <= 1'b0;
45
46 while(!vif.rst_n)
47 @(posedge vif.clk);
48
49 while(1)begin
50 seq_item_port.get_next_item(req);
51 drive_one_pkt(req);
52 seq_item_port.item_done();
53 end
54 endtask
55
56 task my_driver::drive_one_pkt(my_transaction tr);
57
58 byte unsigned data_q[];
59 int unsigned data_size;
60
61 data_size = tr.pack_bytes(data_q)/8;//fill data_q on the order in uvm_object_utils of transaction
62 `uvm_info("my_driver","begin to drive one pkt",UVM_LOW);
63 repeat(3) @(posedge vif.clk);
64 for(int i=0;i<data_size;i++)begin
65 @(posedge vif.clk);
66 vif.valid <= 1'b1;
67 vif.data <= data_q[i];
68 end
69 @(posedge vif.clk);
70 vif.valid <= 1'b0;
71 repeat(10) @(posedge vif.clk);
72 `uvm_info("my_driver","end drive one pkt",UVM_LOW);
73 endtask
74
75 `endif
monitor
1 `ifndef MY_MONITOR__SV
2 `define MY_MONITOR__SV
3 class my_monitor extends uvm_monitor;
4
5 virtual my_if vif;
6
7 uvm_analysis_port #(my_transaction) ap;
8
9 `uvm_component_utils(my_monitor)
10 function new(string name = "my_monitor", uvm_component parent = null);
11 super.new(name, parent);
12 endfunction
13
14 virtual function void build_phase(uvm_phase phase);
15 super.build_phase(phase);
16 if(!uvm_config_db#(virtual my_if)::get(this, "", "vif", vif))
17 `uvm_fatal("my_monitor", "virtual interface must be set for vif!!!")
18 ap = new("ap", this);
19 endfunction
20
21 extern task main_phase(uvm_phase phase);
22 extern task collect_one_pkt(my_transaction tr);
23 endclass
24
25 task my_monitor::main_phase(uvm_phase phase);
26 my_transaction tr;
27 while(1) begin
28 tr = new("tr");
29 collect_one_pkt(tr);
30 ap.write(tr);
31 end
32 endtask
33
34 /*task my_monitor::collect_one_pkt(my_transaction tr); 35 bit[7:0] data_q[$]; 36 int psize; 37 while(1) begin 38 @(posedge vif.clk); 39 if(vif.valid) break; 40 end 41 42 `uvm_info("my_monitor", "begin to collect one pkt", UVM_LOW); 43 while(vif.valid) begin 44 data_q.push_back(vif.data); 45 @(posedge vif.clk); 46 end 47 //pop dmac 48 for(int i = 0; i < 6; i++) begin 49 tr.dmac = {tr.dmac[39:0], data_q.pop_front()}; 50 end 51 //pop smac 52 for(int i = 0; i < 6; i++) begin 53 tr.smac = {tr.smac[39:0], data_q.pop_front()}; 54 end 55 //pop ether_type 56 for(int i = 0; i < 2; i++) begin 57 tr.ether_type = {tr.ether_type[7:0], data_q.pop_front()}; 58 end 59 60 psize = data_q.size() - 4; 61 tr.pload = new[psize]; 62 //pop payload 63 for(int i = 0; i < psize; i++) begin 64 tr.pload[i] = data_q.pop_front(); 65 end 66 //pop crc 67 for(int i = 0; i < 4; i++) begin 68 tr.crc = {tr.crc[23:0], data_q.pop_front()}; 69 end 70 `uvm_info("my_monitor", "end collect one pkt", UVM_LOW); 71 endtask*/
72
73 task my_monitor::collect_one_pkt(my_transaction tr);
74 byte unsigned data_q[$];
75 byte unsigned data_array[];
76
77 logic [8-1:0] data;
78 logic valid=0;
79 int data_size;
80
81 while(1) begin
82 @(posedge vif.clk);
83 if(vif.valid) break;
84 end
85
86
87 `uvm_info("my_monitor","begin to collect one pkt",UVM_LOW);
88 while(vif.valid)begin
89 data_q.push_back(vif.data);
90 @(posedge vif.clk);
91 end
92
93 data_size = data_q.size();
94 data_array = new[data_size];
95 for(int i=0;i<data_size;i++)begin
96 data_array[i] = data_q[i];
97 end
98
99 tr.pload = new[data_size-18];
100 data_size = tr.unpack_bytes(data_array)/8;
101 `uvm_info("my_monitor","end collect one pkt",UVM_LOW);
102 endtask
103
104 `endif
reference_model
1 `ifndef MY_MODEL__SV
2 `define MY_MODEL__SV
3
4 class my_model extends uvm_component;
5
6 uvm_blocking_get_port #(my_transaction) port;
7 uvm_analysis_port #(my_transaction) ap;
8
9 extern function new(string name, uvm_component parent);
10 extern function void build_phase(uvm_phase phase);
11 extern virtual task main_phase(uvm_phase phase);
12
13 `uvm_component_utils(my_model)
14 endclass
15
16 function my_model::new(string name, uvm_component parent);
17 super.new(name, parent);
18 endfunction
19
20 function void my_model::build_phase(uvm_phase phase);
21 super.build_phase(phase);
22 port = new("port", this);
23 ap = new("ap", this);
24 endfunction
25
26 task my_model::main_phase(uvm_phase phase);
27 my_transaction tr;
28 my_transaction new_tr;
29 super.main_phase(phase);
30 while(1) begin
31 port.get(tr);
32 new_tr = new("new_tr");
33 //new_tr.my_copy(tr);
34 new_tr.copy(tr);
35 `uvm_info("my_model", "get one transaction, copy and print it:", UVM_LOW)
36 //new_tr.my_print();
37 new_tr.print();
38 ap.write(new_tr);
39 end
40 endtask
41
42 `endif
scoreboard
1 `ifndef MY_SCOREBOARD__SV
2 `define MY_SCOREBOARD__SV
3 class my_scoreboard extends uvm_scoreboard;
4 my_transaction expect_queue[$];
5 uvm_blocking_get_port #(my_transaction) exp_port;
6 uvm_blocking_get_port #(my_transaction) act_port;
7 `uvm_component_utils(my_scoreboard)
8
9 extern function new(string name, uvm_component parent = null);
10 extern virtual function void build_phase(uvm_phase phase);
11 extern virtual task main_phase(uvm_phase phase);
12 endclass
13
14 function my_scoreboard::new(string name, uvm_component parent = null);
15 super.new(name, parent);
16 endfunction
17
18 function void my_scoreboard::build_phase(uvm_phase phase);
19 super.build_phase(phase);
20 exp_port = new("exp_port", this);
21 act_port = new("act_port", this);
22 endfunction
23
24 task my_scoreboard::main_phase(uvm_phase phase);
25 my_transaction get_expect, get_actual, tmp_tran;
26 bit result;
27
28 super.main_phase(phase);
29 fork
30 while (1) begin
31 exp_port.get(get_expect);
32 expect_queue.push_back(get_expect);
33 end
34 while (1) begin
35 act_port.get(get_actual);
36 if(expect_queue.size() > 0) begin
37 tmp_tran = expect_queue.pop_front();
38 //result = get_actual.my_compare(tmp_tran);
39 result = get_actual.compare(tmp_tran);
40 if(result) begin
41 `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
42 end
43 else begin
44 `uvm_error("my_scoreboard", "Compare FAILED");
45 $display("the expect pkt is");
46 //tmp_tran.my_print();
47 tmp_tran.print();
48 $display("the actual pkt is");
49 //get_actual.my_print();
50 get_actual.print();
51 end
52 end
53 else begin
54 `uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");
55 $display("the unexpected pkt is");
56 //get_actual.my_print();
57 get_actual.print();
58 end
59 end
60 join
61 endtask
62
63 `endif