Hello,
I’m building a basic UVM driver-monitor transaction flow.
The sequencer send a transaction to dut every clock cycle. the interface hold a req.val bit. Sequencer randomly drive val=0 or val=1
The monitor use wait(val) to only generate transaction when this cycle see a “valid” input on interface.
The issue is, when there’s a val=0 cycle followed by a val=1 cycle, at the val=1 cycle(@30, @40), the monitor code execute twice(@50). No duplicate when consecutive val=1 (@160, @170, @180)
if I replace wait(val) with if(val) however, this issue goes away.
Could anyone explain why this is happening, what’s wrong with using wait()?
//sequencer
...
task body();
// get interface
if(!uvm_config_db #(virtual alu_if)::get(p_sequencer, "", "alu_if", vif)) begin
uvm_report_fatal("", "");
end
repeat(30) begin // control test length. use for loop?
@(vif.mon_cb) begin
`uvm_create(req) // req is default parameer of type tr
if($urandom_range(5,0) < 2) begin
req.randomize();
req.val = 1;
start_item(req);
finish_item(req);
end
else begin
req.randomize();
req.val = 0;
start_item(req);
finish_item(req);
end
...
// driver
class alu_drv extends uvm_driver #(alu_op_tr);
...
task run_phase(uvm_phase phase);
super.run_phase(phase);
forever begin
if(!vif.drv_cb.reset) begin
// req is template typed internal
seq_item_port.get_next_item(req); //blocking
if(req) begin
vif.drv_cb.val <= req.val;
vif.drv_cb.Opcode <= req.Opcode;
vif.drv_cb.SrcA <= req.SrcA;
vif.drv_cb.SrcB <= req.SrcB;
end
seq_item_port.item_done();
end
@(vif.drv_cb);
end
endtask
endclass: alu_drv
// Monitor
class alu_monitor extends uvm_monitor;
...
task run_phase(uvm_phase phase);
// get intf
if(!uvm_config_db #(virtual alu_if)::get(this,"","alu_if", intf)) begin
uvm_report_fatal("", "");
end
forever begin
alu_op_tr tr;
@(intf.mon_cb);
tr=new(); // temp var
wait(intf.mon_cb.val && !intf.mon_cb.reset); // trans twice!!!
//if(intf.mon_cb.val && !intf.mon_cb.reset)
begin
tr.val = intf.mon_cb.val;
tr.Opcode = intf.mon_cb.Opcode;
tr.SrcA = intf.mon_cb.SrcA;
mon_cnt=mon_cnt+1;
`uvm_info("alu_mon:", $sformatf("[TIME===%4t] monitor alu: [cnt %4d] val:%d Opc:0x%x SrcA:0x%x", $time, mon_cnt, tr.val, tr.Opcode, tr.SrcA), UVM_LOW)
alu_op_ap.write(tr);
end
end
endtask
endclass
// interface
interface alu_if (
input CCLK,
input reset,
input val,
input [3:0] Opcode,
input [7:0] SrcA,
input [7:0] SrcB,
input [15:0] Result,
input [1:0] ResEn
);
clocking drv_cb @(posedge CCLK);
input CCLK;
input reset;
inout val;
inout Opcode;
inout SrcA;
inout SrcB;
endclocking
clocking mon_cb @(posedge CCLK);
input CCLK;
input reset;
input val;
input Opcode;
input SrcA;
input SrcB;
input Result;
input ResEn;
endclocking
endinterface
// top
module tb_top();
logic clk;
logic reset;
int of;
int cycle;
logic [7:0] SrcA;
logic [7:0] SrcB;
logic [3:0] Opcode;
// dut
alu dut(.CCLK(clk), .reset(reset));
// interface
alu_if intf (.CCLK(clk), .reset(reset), .val(dut.val), .Opcode(dut.Opcode), .SrcA(dut.SrcA),
.SrcB(dut.SrcB), .Result(dut.Result), .ResEn(dut.ResEn)
);
...
// log
UVM_INFO @ 0: reporter [RNTST] Running test alu_test...
UVM_INFO uvm_tb.sv(274) @ 0: uvm_test_top.alu_sb [alu_sb:] [TIME=== 0] process model: size: 0
UVM_INFO uvm_tb.sv(274) @ 0: uvm_test_top.alu_sb [alu_sb:] [TIME=== 0] process model: size: 0
<cycle: 1>
UVM_INFO uvm_tb.sv(274) @ 10: uvm_test_top.alu_sb [alu_sb:] [TIME=== 10] process model: size: 0
<cycle: 2>
UVM_INFO uvm_tb.sv(274) @ 20: uvm_test_top.alu_sb [alu_sb:] [TIME=== 20] process model: size: 0
<cycle: 3>
UVM_INFO uvm_tb.sv(274) @ 30: uvm_test_top.alu_sb [alu_sb:] [TIME=== 30] process model: size: 0
UVM_INFO uvm_tb.sv(80) @ 30: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 30] seq generated: val:0 Opc:0x9 SrcA:0x73 SrbB:0x1d
<cycle: 4>
UVM_INFO uvm_tb.sv(274) @ 40: uvm_test_top.alu_sb [alu_sb:] [TIME=== 40] process model: size: 0
UVM_INFO uvm_tb.sv(80) @ 40: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 40] seq generated: val:1 Opc:0x6 SrcA:0x49 SrbB:0xdc
<cycle: 5>
UVM_INFO uvm_tb.sv(207) @ 50: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 50] monitor alu: [cnt 1] val:1 Opc:0x6 SrcA:0x49
UVM_INFO uvm_tb.sv(263) @ 50: uvm_test_top.alu_sb [alu_sb:] [TIME=== 50] alu_sb_ap_export: alu_op_tr recived, entry size: 1. Opcode:0x6 SrcA:0x49
UVM_INFO uvm_tb.sv(207) @ 50: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 50] monitor alu: [cnt 2] val:1 Opc:0x6 SrcA:0x49
UVM_INFO uvm_tb.sv(263) @ 50: uvm_test_top.alu_sb [alu_sb:] [TIME=== 50] alu_sb_ap_export: alu_op_tr recived, entry size: 2. Opcode:0x6 SrcA:0x49
UVM_INFO uvm_tb.sv(274) @ 50: uvm_test_top.alu_sb [alu_sb:] [TIME=== 50] process model: size: 2
UVM_INFO uvm_tb.sv(80) @ 50: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 50] seq generated: val:0 Opc:0xc SrcA:0xff SrbB:0xbe
<cycle: 6>
UVM_INFO uvm_tb.sv(274) @ 60: uvm_test_top.alu_sb [alu_sb:] [TIME=== 60] process model: size: 2
UVM_INFO uvm_tb.sv(80) @ 60: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 60] seq generated: val:1 Opc:0x0 SrcA:0x48 SrbB:0x86
<cycle: 7>
UVM_INFO uvm_tb.sv(207) @ 70: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 70] monitor alu: [cnt 3] val:1 Opc:0x0 SrcA:0x48
UVM_INFO uvm_tb.sv(263) @ 70: uvm_test_top.alu_sb [alu_sb:] [TIME=== 70] alu_sb_ap_export: alu_op_tr recived, entry size: 3. Opcode:0x0 SrcA:0x48
UVM_INFO uvm_tb.sv(207) @ 70: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 70] monitor alu: [cnt 4] val:1 Opc:0x0 SrcA:0x48
UVM_INFO uvm_tb.sv(263) @ 70: uvm_test_top.alu_sb [alu_sb:] [TIME=== 70] alu_sb_ap_export: alu_op_tr recived, entry size: 4. Opcode:0x0 SrcA:0x48
UVM_INFO uvm_tb.sv(274) @ 70: uvm_test_top.alu_sb [alu_sb:] [TIME=== 70] process model: size: 4
UVM_INFO uvm_tb.sv(80) @ 70: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 70] seq generated: val:0 Opc:0x9 SrcA:0xca SrbB:0x8c
...
<cycle: 16>
UVM_INFO uvm_tb.sv(207) @ 160: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 160] monitor alu: [cnt 7] val:1 Opc:0xd SrcA:0x48
UVM_INFO uvm_tb.sv(263) @ 160: uvm_test_top.alu_sb [alu_sb:] [TIME=== 160] alu_sb_ap_export: alu_op_tr recived, entry size: 7. Opcode:0xd SrcA:0x48
UVM_INFO uvm_tb.sv(207) @ 160: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 160] monitor alu: [cnt 8] val:1 Opc:0xd SrcA:0x48
UVM_INFO uvm_tb.sv(263) @ 160: uvm_test_top.alu_sb [alu_sb:] [TIME=== 160] alu_sb_ap_export: alu_op_tr recived, entry size: 8. Opcode:0xd SrcA:0x48
UVM_INFO uvm_tb.sv(274) @ 160: uvm_test_top.alu_sb [alu_sb:] [TIME=== 160] process model: size: 8
UVM_INFO uvm_tb.sv(80) @ 160: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 160] seq generated: val:1 Opc:0xb SrcA:0xfa SrbB:0x8f
<cycle: 17>
UVM_INFO uvm_tb.sv(207) @ 170: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 170] monitor alu: [cnt 9] val:1 Opc:0xb SrcA:0xfa
UVM_INFO uvm_tb.sv(263) @ 170: uvm_test_top.alu_sb [alu_sb:] [TIME=== 170] alu_sb_ap_export: alu_op_tr recived, entry size: 9. Opcode:0xb SrcA:0xfa
UVM_INFO uvm_tb.sv(274) @ 170: uvm_test_top.alu_sb [alu_sb:] [TIME=== 170] process model: size: 9
UVM_INFO uvm_tb.sv(80) @ 170: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 170] seq generated: val:1 Opc:0xd SrcA:0xb3 SrbB:0x24
<cycle: 18>
UVM_INFO uvm_tb.sv(207) @ 180: uvm_test_top.chk_env.alu_mon [alu_mon:] [TIME=== 180] monitor alu: [cnt 10] val:1 Opc:0xd SrcA:0xb3
UVM_INFO uvm_tb.sv(263) @ 180: uvm_test_top.alu_sb [alu_sb:] [TIME=== 180] alu_sb_ap_export: alu_op_tr recived, entry size: 10. Opcode:0xd SrcA:0xb3
UVM_INFO uvm_tb.sv(274) @ 180: uvm_test_top.alu_sb [alu_sb:] [TIME=== 180] process model: size: 10
UVM_INFO uvm_tb.sv(80) @ 180: uvm_test_top.stim_env.alu_op_sqr@@op_seq [alu_seq:] [TIME=== 180] seq generated: val:0 Opc:0x5 SrcA:0xcf SrbB:0x0c