Faulty data from DUT

The value generated by the sequence is first sent to the monitor and then to the interface. However, it does not match the value observed on the monitor and scoreboard. What should I do in this case?
image

Simplified order of stages:

  1. Sequence is randomized, and pushed to the agent Sequencer’s queue.
  2. The driver of the agent gets/pulls the sequence from the Sequencer queue, and drives it on the DUT ports (also may be named “pin wiggle”).
  3. The Monitor collects the transaction which was pushed by the Driver to the DUT through the Interface.

So if the monitor collected/captured Date: 00
It is either a bug in the Driver code of the pin wiggle, or in the Monitor code which collects the transaction from the pins/ports.

First of all, thank you for your answer. I reviewed the classes you specified again but I did not see any mistakes. I added the codes of the relevant classes below. Can you take a look? include "uvm_macros.svh" import uvm_pkg::*; include “seq_item.sv”

class dff_driver extends uvm_driver#(dff_seq_item);

`uvm_component_utils(dff_driver);

virtual dff_intf intf;
dff_seq_item tx;

function new(string name = “dff_driver”, uvm_component parent);
super.new(name, parent);
`uvm_info(“Driver Class”, “constructor”, UVM_MEDIUM)
endfunction : new

function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db#(virtual dff_intf)::get(this, “”, “vintf”, intf))
`uvm_fatal(“no_inif in driver”,“virtual interface get failed from config db”);
endfunction : build_phase

task run_phase(uvm_phase phase);

  `uvm_info("driver Class", "run_phase", UVM_MEDIUM)
  tx = dff_seq_item::type_id::create("tx"); 

  seq_item_port.get_next_item(tx);
  @(posedge intf.clk)
  intf.data <= tx.data;
  seq_item_port.item_done();
  `uvm_info("Driver Class", $sformatf("Sending Data: %h", tx.data), UVM_MEDIUM)

endtask

endclass

include "uvm_macros.svh" import uvm_pkg::*; include “seq_item.sv”

class dff_monitor extends uvm_monitor;

`uvm_component_utils(dff_monitor);

virtual dff_intf intf;
uvm_analysis_port #(dff_seq_item) item_collected_port;

dff_seq_item tx;

function new(string name = “dff_monitor”, uvm_component parent);
super.new(name, parent);
item_collected_port = new(“item_collected_port”, this);
`uvm_info(“Monitor Class”, “constructor”, UVM_MEDIUM)
endfunction : new

function void build_phase(uvm_phase phase);
super.build_phase(phase);

if(!uvm_config_db#(virtual dff_intf)::get(this, “”, “vintf”, intf))
`uvm_fatal(“no_inif in driver”,“virtual interface get failed from config db”);

`uvm_info(get_name(), $sformatf("In the monitor build phase "),UVM_LOW)
endfunction : build_phase

task run_phase(uvm_phase phase);

tx = dff_seq_item::type_id::create("tx"); 

phase.raise_objection(this);

@(posedge intf.clk)
tx.data = intf.data;

item_collected_port.write(tx);
phase.drop_objection(this);

`uvm_info("Monitor Class", $sformatf("Captured Data from DUT: %h", tx.data), UVM_MEDIUM)

endtask

endclass

please read this post and format your code, for better readability.

`include "uvm_macros.svh" 
import uvm_pkg::*; 
`include "seq_item.sv"

class dff_driver extends uvm_driver#(dff_seq_item); 

`uvm_component_utils(dff_driver); 

virtual dff_intf intf;
dff_seq_item tx;


function new(string name = "dff_driver", uvm_component parent); 
   super.new(name, parent);
   `uvm_info("Driver Class", "constructor", UVM_MEDIUM)
endfunction : new 

function void build_phase(uvm_phase phase);
   super.build_phase(phase);
   if(!uvm_config_db#(virtual dff_intf)::get(this, "", "vintf", intf))
      `uvm_fatal("no_inif in driver","virtual interface get failed from config db");
endfunction : build_phase

task run_phase(uvm_phase phase);
    //forever begin
      `uvm_info("driver Class", "run_phase", UVM_MEDIUM)
      tx = dff_seq_item::type_id::create("tx"); 

      seq_item_port.get_next_item(tx);
      @(posedge intf.clk)
      intf.data <= tx.data;
      seq_item_port.item_done();
      `uvm_info("Driver Class", $sformatf("Sending Data: %h", tx.data), UVM_MEDIUM)
    //end
endtask



endclass
`include "uvm_macros.svh" 
import uvm_pkg::*; 
`include "seq_item.sv"

class dff_monitor extends uvm_monitor; 

`uvm_component_utils(dff_monitor); 

virtual dff_intf intf;
uvm_analysis_port #(dff_seq_item) item_collected_port; 

dff_seq_item tx;

function new(string name = "dff_monitor", uvm_component parent); 
   super.new(name, parent);
   item_collected_port = new("item_collected_port", this);
   `uvm_info("Monitor Class", "constructor", UVM_MEDIUM)
endfunction : new

function void build_phase(uvm_phase phase);
   super.build_phase(phase);
   
   if(!uvm_config_db#(virtual dff_intf)::get(this, "", "vintf", intf))
      `uvm_fatal("no_inif in driver","virtual interface get failed from config db");
   
   `uvm_info(get_name(), $sformatf("In the monitor build phase "),UVM_LOW)
endfunction : build_phase


task run_phase(uvm_phase phase);

    tx = dff_seq_item::type_id::create("tx"); 
    
    phase.raise_objection(this);

    @(posedge intf.clk)
    tx.data = intf.data;

    item_collected_port.write(tx);
    phase.drop_objection(this);

    `uvm_info("Monitor Class", $sformatf("Captured Data from DUT: %h", tx.data), UVM_MEDIUM)

endtask

endclass

I added the codes as you requested.

Please pay attention your monitor runs only once.
it is not iterative.

I used the forever structure for the relevant part of the solution, but the result did not change. Now I will add the DUT and top module codes below, would you take a look at them?

library ieee;
use ieee.std_logic_1164.all;

entity uart_transmitter is
generic(baud_rate : integer := 9600);
port(
	send : in std_logic; 
   	clk : in std_logic;
	data : in std_logic_vector (7 downto 0);
	ready : out std_logic;
	uart_tx : out std_logic
);
end entity;

architecture uart_transmit of uart_transmitter is

constant baud_timer : integer := 100000000 / baud_rate;
constant bit_index_max : integer := 10;

type state_type is (RDY, LOAD_BIT, SEND_BIT);

signal state : state_type := RDY;
signal timer : integer := 0;
signal tx_data : std_logic_vector (9 downto 0);
signal bitIndex : integer range 0 TO bit_index_max := 0;
signal txBit : std_logic := '1';

begin
process(clk)
begin 
if rising_edge(clk) then

case state is 

when RDY => 
	if send = '1' then 
	tx_data <= '1' & data & '0';
	state <= LOAD_BIT;
	end if;
	timer <= 0;
	bitIndex <= 0; 
	txBit <= '1';
when LOAD_BIT =>
	state <= SEND_BIT;
	bitIndex <= bitIndex + 1;
	txBit <= tx_data(bitIndex);	
when SEND_BIT =>
	if(timer = baud_timer) then
	timer <= 0;
	if(bitIndex = bit_index_max) then
	state <= RDY;
	else state <= LOAD_BIT;
	end if;
	else timer <= timer + 1;
	end if;	

end case;
end if;
end process;

uart_tx <= txBit;
ready <= '1' when (state = RDY) else '0';

end uart_transmit;
`timescale 1ns/1ns

`include "uvm_macros.svh"
import uvm_pkg::*;
`include "interface.sv"
`include "test.sv"

module top;

logic clk;
logic [7:0] data;
logic send;
logic ready;
logic uart_tx;

dff_intf intf(.clk(clk));

uart_transmitter dut( 
      .clk(intf.clk),
      .send(intf.send),
      .data(intf.data),
      .ready(intf.ready),
      .uart_tx(intf.uart_tx)
);

initial begin
   clk = 0;
   forever #10 clk = ~clk;
end

initial begin
     #100; 
     send = 1;
     #20; 
     send = 0;
  end

initial begin
   uvm_config_db#(virtual dff_intf)::set(null,"*","vintf",intf);
   $dumpfile("dump.vcd");  
   $dumpvars(0, top);  
   run_test("dff_test");

end
endmodule 

Please post your entire environment, preferably on EDA Playground, which demonstrates your issue.

It is difficult to piece together what you are doing from the multiple posts you have made.

I added my code to the EDA Playground simulator.

Some comments:

  • Only raise objections in your test. Do not raise/drop objections in any other components
  • Your driver needs a forever loop in the run_phase() so that it will get all the transactions from the sequencer. If you don’t have this loop, your sequence will never finish and your test will never end.
  • You want to use blocking assignments in your driver and monitor. Using non-blocking assignments will result in incorrect behavior.