1.top.sv
1 module top;
2 import uvm_pkg::*;
3 import tinyalu_pkg::*;
4 `include "tinyalu_macros.svh"
5 `include "uvm_macros.svh"
6
7 tinyalu_bfm bfm();
8 tinyalu DUT (.A(bfm.A), .B(bfm.B), .op(bfm.op),
9 .clk(bfm.clk), .reset_n(bfm.reset_n),
10 .start(bfm.start), .done(bfm.done), .result(bfm.result));
11
12
13 initial begin
14 uvm_config_db #(virtual tinyalu_bfm)::set(null, "*", "bfm", bfm);
15 run_test();
16 end
17
18 endmodule : top
2.tinyalu_bfm.sv
1 interface tinyalu_bfm;
2 import tinyalu_pkg::*;
3
4 byte unsigned A;
5 byte unsigned B;
6 bit clk;
7 bit reset_n;
8 wire [2:0] op;
9 bit start;
10 wire done;
11 wire [15:0] result;
12 operation_t op_set;
13
14
15 assign op = op_set;
16
17 task reset_alu();
18 reset_n = 1'b0;
19 @(negedge clk);
20 @(negedge clk);
21 reset_n = 1'b1;
22 start = 1'b0;
23 endtask : reset_alu
24
25
26
27 task send_op(input byte iA, input byte iB, input operation_t iop, output shortint alu_result);
28 if (iop == rst_op) begin
29 @(posedge clk);
30 reset_n = 1'b0;
31 start = 1'b0;
32 @(posedge clk);
33 #1;
34 reset_n = 1'b1;
35 end else begin
36 @(negedge clk);
37 op_set = iop;
38 A = iA;
39 B = iB;
40 start = 1'b1;
41 if (iop == no_op) begin
42 @(posedge clk);
43 #1;
44 start = 1'b0;
45 end else begin
46 do
47 @(negedge clk);
48 while (done == 0);
49 alu_result = result;
50 start = 1'b0;
51 end
52 end // else: !if(iop == rst_op)
53
54 endtask : send_op
55
56 command_monitor command_monitor_h;
57
58 function operation_t op2enum();
59 case(op)
60 3'b000 : return no_op;
61 3'b001 : return add_op;
62 3'b010 : return and_op;
63 3'b011 : return xor_op;
64 3'b100 : return mul_op;
65 default : $fatal("Illegal operation on op bus");
66 endcase // case (op)
67 endfunction : op2enum
68
69
70 always @(posedge clk) begin : op_monitor
71 static bit in_command = 0;
72 if (start) begin : start_high
73 if (!in_command) begin : new_command
74 command_monitor_h.write_to_monitor(A, B, op2enum());
75 in_command = (op2enum() != no_op);
76 end : new_command
77 end : start_high
78 else // start low
79 in_command = 0;
80 end : op_monitor
81
82 always @(negedge reset_n) begin : rst_monitor
83 if (command_monitor_h != null) //guard against VCS time 0 negedge
84 command_monitor_h.write_to_monitor($random,0,rst_op);
85 end : rst_monitor
86
87 result_monitor result_monitor_h;
88
89 initial begin : result_monitor_thread
90 forever begin : result_monitor_block
91 @(posedge clk) ;
92 if (done)
93 result_monitor_h.write_to_monitor(result);
94 end : result_monitor_block
95 end : result_monitor_thread
96
97
98 initial begin
99 clk = 0;
100 fork
101 forever begin
102 #10;
103 clk = ~clk;
104 end
105 join_none
106 end
107
108
109 endinterface : tinyalu_bfm
3.tinyalu_pkg.sv
1 package tinyalu_pkg;
2 import uvm_pkg::*;
3 `include "uvm_macros.svh"
4
5 typedef enum bit[2:0] {
6 no_op = 3'b000,
7 add_op = 3'b001,
8 and_op = 3'b010,
9 xor_op = 3'b011,
10 mul_op = 3'b100,
11 rst_op = 3'b111} operation_t;
12
13 `include "sequence_item.svh"
14 typedef uvm_sequencer #(sequence_item) sequencer;
15
16 `include "add_sequence_item.svh"
17 `include "random_sequence.svh"
18 `include "maxmult_sequence.svh"
19 `include "reset_sequence.svh"
20 `include "runall_sequence.svh"
21 `include "add_sequence.svh"
22 `include "fibonacci_sequence.svh"
23 `include "short_random_sequence.svh"
24
25
26 `include "result_transaction.svh"
27 `include "coverage.svh"
28 `include "scoreboard.svh"
29 `include "driver.svh"
30 `include "command_monitor.svh"
31 `include "result_monitor.svh"
32
33 `include "env.svh"
34 `include "parallel_sequence.svh"
35
36 `include "tinyalu_base_test.svh"
37 `include "full_test.svh"
38 `include "fibonacci_test.svh"
39 `include "parallel_test.svh"
40
41
42
43
44
45 endpackage : tinyalu_pkg
4.sequence_item.svh
1 class sequence_item extends uvm_sequence_item;
2 `uvm_object_utils(sequence_item);
3
4 function new(string name = "");
5 super.new(name);
6 endfunction : new
7
8 rand byte unsigned A;
9 rand byte unsigned B;
10 rand operation_t op;
11 shortint unsigned result;
12
13 constraint op_con {op dist {no_op := 1, add_op := 5, and_op:=5,
14 xor_op:=5,mul_op:=5, rst_op:=1};}
15
16 constraint data { A dist {8'h00:=1, [8'h01 : 8'hFE]:=1, 8'hFF:=1};
17 B dist {8'h00:=1, [8'h01 : 8'hFE]:=1, 8'hFF:=1};}
18
19 function bit do_compare(uvm_object rhs, uvm_comparer comparer);
20 sequence_item tested;
21 bit same;
22
23 if (rhs==null) `uvm_fatal(get_type_name(),
24 "Tried to do comparison to a null pointer");
25
26 if (!$cast(tested,rhs))
27 same = 0;
28 else
29 same = super.do_compare(rhs, comparer) &&
30 (tested.A == A) &&
31 (tested.B == B) &&
32 (tested.op == op) &&
33 (tested.result == result);
34 return same;
35 endfunction : do_compare
36
37 function void do_copy(uvm_object rhs);
38 sequence_item RHS;
39 assert(rhs != null) else
40 $fatal(1,"Tried to copy null transaction");
41 super.do_copy(rhs);
42 assert($cast(RHS,rhs)) else
43 $fatal(1,"Faied cast in do_copy");
44 A = RHS.A;
45 B = RHS.B;
46 op = RHS.op;
47 result = RHS.result;
48 endfunction : do_copy
49
50 function string convert2string();
51 string s;
52 s = $sformatf("A: %2h B: %2h op: %s = %4h",
53 A, B, op.name(), result);
54 return s;
55 endfunction : convert2string
56
57 endclass : sequence_item
5.base_test & tests
1 `ifdef QUESTA
2 virtual class tinyalu_base_test extends uvm_test;
3 `else
4 class tinyalu_base_test extends uvm_test;
5 `endif
6
7 env env_h;
8 sequencer sequencer_h;
9
10 function void build_phase(uvm_phase phase);
11 env_h = env::type_id::create("env_h",this);
12 endfunction : build_phase
13
14 function void end_of_elaboration_phase(uvm_phase phase);
15 sequencer_h = env_h.sequencer_h;
16 endfunction : end_of_elaboration_phase
17
18 function new (string name, uvm_component parent);
19 super.new(name,parent);
20 endfunction : new
21
22 endclass
23
24 class fibonacci_test extends tinyalu_base_test;
25 `uvm_component_utils(fibonacci_test);
26
27 task run_phase(uvm_phase phase);
28 fibonacci_sequence fibonacci;
29 fibonacci = new("fibonacci");
30
31 phase.raise_objection(this);
32 fibonacci.start(sequencer_h);
33 phase.drop_objection(this);
34 endtask : run_phase
35
36 function new(string name, uvm_component parent);
37 super.new(name,parent);
38 endfunction : new
39
40 endclass
41
42 class parallel_test extends tinyalu_base_test;
43 `uvm_component_utils(parallel_test);
44
45 parallel_sequence parallel_h;
46
47 function new(string name, uvm_component parent);
48 super.new(name,parent);
49 parallel_h = new("parallel_h");
50 endfunction : new
51
52 task run_phase(uvm_phase phase);
53 phase.raise_objection(this);
54 parallel_h.start(sequencer_h);
55 phase.drop_objection(this);
56 endtask : run_phase
57
58 endclass
59
60 class full_test extends tinyalu_base_test;
61 `uvm_component_utils(full_test);
62
63 runall_sequence runall_seq;
64
65 task run_phase(uvm_phase phase);
66 runall_seq = new("runall_seq");
67 phase.raise_objection(this);
68 runall_seq.start(null); //virtual sequence;
69 phase.drop_objection(this);
70 endtask : run_phase
71
72
73 function new (string name, uvm_component parent);
74 super.new(name,parent);
75 endfunction : new
76
77 endclass
6.env.svh
1 class env extends uvm_env;
2 `uvm_component_utils(env);
3
4 sequencer sequencer_h;
5 coverage coverage_h;
6 scoreboard scoreboard_h;
7 driver driver_h;
8 command_monitor command_monitor_h;
9 result_monitor result_monitor_h;
10
11 function new (string name, uvm_component parent);
12 super.new(name,parent);
13 endfunction : new
14
15 function void build_phase(uvm_phase phase);
16 // stimulus
17 sequencer_h = new("sequencer_h",this);
18 driver_h = driver::type_id::create("driver_h",this);
19 // monitors
20 command_monitor_h = command_monitor::type_id::create("command_monitor_h",this);
21 result_monitor_h = result_monitor::type_id::create("result_monitor",this);
22 // analysis
23 coverage_h = coverage::type_id::create ("coverage_h",this);
24 scoreboard_h = scoreboard::type_id::create("scoreboard",this);
25 endfunction : build_phase
26
27 function void connect_phase(uvm_phase phase);
28
29 driver_h.seq_item_port.connect(sequencer_h.seq_item_export);
30
31 command_monitor_h.ap.connect(coverage_h.analysis_export);
32 command_monitor_h.ap.connect(scoreboard_h.cmd_f.analysis_export);
33 result_monitor_h.ap.connect(scoreboard_h.analysis_export);
34 endfunction : connect_phase
35
36 endclass : env
7.driver,coverage,scoreboard略
8.fibonacci_sequence.svh
1 class fibonacci_sequence extends uvm_sequence #(sequence_item);
2 `uvm_object_utils(fibonacci_sequence);
3
4 function new(string name = "fibonacci");
5 super.new(name);
6 endfunction : new
7
8
9 task body();
10 byte unsigned n_minus_2=0;
11 byte unsigned n_minus_1=1;
12 sequence_item command;
13
14 command = sequence_item::type_id::create("command");
15
16 start_item(command);
17 command.op = rst_op;
18 finish_item(command);
19
20 `uvm_info("FIBONACCI", " Fib(01) = 00", UVM_MEDIUM);
21 `uvm_info("FIBONACCI", " Fib(02) = 01", UVM_MEDIUM);
22 for(int ff = 3; ff<=14; ff++) begin //斐波那契数列
23 start_item(command);
24 command.A = n_minus_2;
25 command.B = n_minus_1;
26 command.op = add_op;
27 finish_item(command);
28 n_minus_2 = n_minus_1;
29 n_minus_1 = command.result; //command.result=command.A+command.B;
30 `uvm_info("FIBONACCI", $sformatf("Fib(%02d) = %02d", ff, n_minus_1),
31 UVM_MEDIUM);
32 end
33 endtask : body
34 endclass : fibonacci_sequence
9.reset_sequence.svh
1 class reset_sequence extends uvm_sequence #(sequence_item);
2 `uvm_object_utils(reset_sequence)
3
4 sequence_item command;
5
6 function new(string name = "reset");
7 super.new(name);
8 endfunction : new
9
10 task body();
11 command = sequence_item::type_id::create("command");
12 start_item(command);
13 command.op = rst_op;
14 finish_item(command);
15 endtask : body
16 endclass : reset_sequence
10.short_random_sequence.svh
1 class short_random_sequence extends uvm_sequence #(sequence_item);
2 `uvm_object_utils(short_random_sequence);
3
4 sequence_item command;
5
6 function new(string name = "short_random_sequence");
7 super.new(name);
8 endfunction : new
9
10
11
12 task body();
13 repeat (14) begin : short_random_loop
14 command = sequence_item::type_id::create("command");
15 start_item(command);
16 assert(command.randomize());
17 finish_item(command);
18 // Moved relative to the book example so as to show result
19 `uvm_info("SHORT RANDOM", $sformatf("random command: %s", command.convert2string), UVM_MEDIUM)
20 end : short_random_loop
21 endtask : body
22 endclass : short_random_sequence
11.parallel_sequence.svh
1 class parallel_sequence extends uvm_sequence #(uvm_sequence_item);
2 `uvm_object_utils(parallel_sequence);
3
4 protected reset_sequence reset;
5 protected short_random_sequence short_random;
6 protected fibonacci_sequence fibonacci;
7
8 function new(string name = "parallel_sequence");
9 super.new(name);
10 reset = reset_sequence::type_id::create("reset");
11 fibonacci = fibonacci_sequence::type_id::create("fibonacci");
12 short_random = short_random_sequence::type_id::create("short_random");
13 endfunction : new
14
15 task body();
16 reset.start(m_sequencer);
17 fork
18 fibonacci.start(m_sequencer);
19 short_random.start(m_sequencer);
20 join
21 endtask : body
22 endclass : parallel_sequence