admin管理员组

文章数量:1122832

I have written a SystemVerilog testbench environment with a driver, monitor, and scoreboard. However, during simulation, the DUT output (gray) often mismatches the expected Gray code computed by the scoreboard.

Design Module
---------------------------------------------------
`timescale 1ns / 1ps
module binary_to_gray(input [3:0] binary, output [3:0] gray);
  assign gray[3] = binary[3];                  // MSB remains the same
  assign gray[2] = binary[3] ^ binary[2];      // XOR for bit 2
  assign gray[1] = binary[2] ^ binary[1];      // XOR for bit 1
  assign gray[0] = binary[1] ^ binary[0];      // XOR for bit 0
endmodule
-----------------------------------------------------
Top_Testbench Module
-----------------------------------------------------
// Code your testbench here
// or browse Examples
`timescale 1ns / 1ps
`include "interface.sv"
`include "test"

module top_tb;             // Top-level testbench module
  intf i_intf(); // Interface instantiation
  test t1(i_intf); // Test instantiation

  // Instantiate the DUT (Device Under Test)
  binary_to_gray DUT(
    .binary(i_intf.binary),
    .gray(i_intf.gray)
  );
endmodule
-------------------------------------------------------
Environment Module
--------------------------------------------------------
`timescale 1ns / 1ps
`include "transaction.sv"
`include "generator.sv"
`include "driver.sv"
`include "monitor"
`include "scoreboard"
class environment;
  generator gen;
  driver driv;
  monitor mon;
  scoreboard scb;
  mailbox m1, m2;
  virtual intf vif;

  function new(virtual intf vif);
    this.vif = vif;
    m1 = new();
    m2 = new();
    gen = new(m1);
    driv = new(vif, m1);
    mon = new(vif, m2);
    scb = new(m2);
  endfunction

  task test();
    fork
      gen.main();
      driv.main();
      mon.main();
      scb.main();
    join
  endtask
endclass
------------------------------------------------------------
Driver Module
-----------------------------------------------------------------
`timescale 1ns / 1ps
class driver;
  virtual intf vif;
  mailbox gen2driv;

  function new(virtual intf vif, mailbox gen2driv);
    this.vif = vif;
    this.gen2driv = gen2driv;
  endfunction

  task main();
  transaction trans;
  repeat(5) begin
    gen2driv.get(trans);       // Receive transaction
    vif.binary = trans.binary; // Drive input to DUT
    #10;                       // Increased propagation delay
    trans.gray = vif.gray;     // Capture output
    trans.display("Driver");
  end
endtask
endclass

------------------------------------------------------------------
Generator Module
----------------------------------------------------------------
`timescale 1ns / 1ps
class generator;
  transaction trans;
  mailbox gen2driv;

  function new(mailbox gen2driv);
    this.gen2driv = gen2driv;
  endfunction

  task main();
    repeat(5) begin
      trans = new();
      if (!trans.randomize()) $error("Failed to randomize transaction!");
      trans.display("Generator");
      gen2driv.put(trans);       // Send transaction to driver
    end
  endtask
endclass
--------------------------------------------------------------------
Interface Module
--------------------------------------------------------------------
`timescale 1ns / 1ps
interface intf();
  logic [3:0] binary;
  logic [3:0] gray;
endinterface
---------------------------------------------------------------------
Transaction Module
--------------------------------------------------------------------
`timescale 1ns / 1ps
class transaction;
  rand bit [3:0] binary; // Randomizable binary input
  bit [3:0] gray;        // Output to store Gray code

  function void display(string name);
    $display("--------------------------");
    $display("%s", name);
    $display("--------------------------");
    $display("Binary = %b", binary);
    $display("Gray = %b", gray);
    $display("--------------------------");
  endfunction
endclass

----------------------------------------------------------------------
test module
---------------------------------------------------------------------
`timescale 1ns / 1ps
`include "environment.sv"

program test(intf i_intf);
  environment env;

  initial begin
    env = new(i_intf);
    env.test();
    $finish;
  end
endprogram
---------------------------------------------------------------------
Monitor Module
------------------------------------------------------------------------
`timescale 1ns / 1ps

class monitor;
  virtual intf vif;        // Virtual interface for DUT connections
  mailbox mon2scb;         // Mailbox to send transactions to the scoreboard

  // Constructor
  function new(virtual intf vif, mailbox mon2scb);
    this.vif = vif;
    this.mon2scb = mon2scb;
  endfunction

  // Main task to observe DUT behavior
task main();
  transaction trans;
  repeat(5) begin
    #10;                       // Increased propagation delay (align with Driver)
    trans = new();             // Initialize the transaction object
    trans.binary = vif.binary; // Capture binary input
    trans.gray = vif.gray;     // Capture Gray code output
    trans.display("Monitor");  // Display the transaction details
    mon2scb.put(trans);        // Send the transaction to the scoreboard
  end
endtask

endclass
-----------------------------------------------------------------------
Scoreboard Module
-----------------------------------------------------------------------
`timescale 1ns / 1ps
class scoreboard;
  mailbox mon2scb;
  logic [3:0] expected_gray; // Declare at the class level

  function new(mailbox mon2scb);
    this.mon2scb = mon2scb;
  endfunction

  task main();
    transaction trans;
    repeat(5) begin
      mon2scb.get(trans);        // Receive transaction
      expected_gray[3] = trans.binary[3];
      expected_gray[2] = trans.binary[3] ^ trans.binary[2];
      expected_gray[1] = trans.binary[2] ^ trans.binary[1];
      expected_gray[0] = trans.binary[1] ^ trans.binary[0];

      if (trans.gray == expected_gray)
        $display("PASS: Binary = %b, Gray = %b", trans.binary, trans.gray);
      else
        $error("FAIL: Binary = %b, Expected Gray = %b, DUT Gray = %b",
                trans.binary, expected_gray, trans.gray);
    end
  endtask
endclass

Here's an example of the errors:

FAIL: Binary = 1111, Expected Gray = 1000, DUT Gray = 1100
FAIL: Binary = 0001, Expected Gray = 0001, DUT Gray = 1100

What could be causing this mismatch, and how can I fix it? Is there an issue with my DUT implementation, testbench timing, or some other aspect?

Additional Details:

The simulation tool used is Synopsys VCS. All modules are instantiated and connected through a virtual interface. The errors occur inconsistently across different binary input values.

I have written a SystemVerilog testbench environment with a driver, monitor, and scoreboard. However, during simulation, the DUT output (gray) often mismatches the expected Gray code computed by the scoreboard.

Design Module
---------------------------------------------------
`timescale 1ns / 1ps
module binary_to_gray(input [3:0] binary, output [3:0] gray);
  assign gray[3] = binary[3];                  // MSB remains the same
  assign gray[2] = binary[3] ^ binary[2];      // XOR for bit 2
  assign gray[1] = binary[2] ^ binary[1];      // XOR for bit 1
  assign gray[0] = binary[1] ^ binary[0];      // XOR for bit 0
endmodule
-----------------------------------------------------
Top_Testbench Module
-----------------------------------------------------
// Code your testbench here
// or browse Examples
`timescale 1ns / 1ps
`include "interface.sv"
`include "test"

module top_tb;             // Top-level testbench module
  intf i_intf(); // Interface instantiation
  test t1(i_intf); // Test instantiation

  // Instantiate the DUT (Device Under Test)
  binary_to_gray DUT(
    .binary(i_intf.binary),
    .gray(i_intf.gray)
  );
endmodule
-------------------------------------------------------
Environment Module
--------------------------------------------------------
`timescale 1ns / 1ps
`include "transaction.sv"
`include "generator.sv"
`include "driver.sv"
`include "monitor"
`include "scoreboard"
class environment;
  generator gen;
  driver driv;
  monitor mon;
  scoreboard scb;
  mailbox m1, m2;
  virtual intf vif;

  function new(virtual intf vif);
    this.vif = vif;
    m1 = new();
    m2 = new();
    gen = new(m1);
    driv = new(vif, m1);
    mon = new(vif, m2);
    scb = new(m2);
  endfunction

  task test();
    fork
      gen.main();
      driv.main();
      mon.main();
      scb.main();
    join
  endtask
endclass
------------------------------------------------------------
Driver Module
-----------------------------------------------------------------
`timescale 1ns / 1ps
class driver;
  virtual intf vif;
  mailbox gen2driv;

  function new(virtual intf vif, mailbox gen2driv);
    this.vif = vif;
    this.gen2driv = gen2driv;
  endfunction

  task main();
  transaction trans;
  repeat(5) begin
    gen2driv.get(trans);       // Receive transaction
    vif.binary = trans.binary; // Drive input to DUT
    #10;                       // Increased propagation delay
    trans.gray = vif.gray;     // Capture output
    trans.display("Driver");
  end
endtask
endclass

------------------------------------------------------------------
Generator Module
----------------------------------------------------------------
`timescale 1ns / 1ps
class generator;
  transaction trans;
  mailbox gen2driv;

  function new(mailbox gen2driv);
    this.gen2driv = gen2driv;
  endfunction

  task main();
    repeat(5) begin
      trans = new();
      if (!trans.randomize()) $error("Failed to randomize transaction!");
      trans.display("Generator");
      gen2driv.put(trans);       // Send transaction to driver
    end
  endtask
endclass
--------------------------------------------------------------------
Interface Module
--------------------------------------------------------------------
`timescale 1ns / 1ps
interface intf();
  logic [3:0] binary;
  logic [3:0] gray;
endinterface
---------------------------------------------------------------------
Transaction Module
--------------------------------------------------------------------
`timescale 1ns / 1ps
class transaction;
  rand bit [3:0] binary; // Randomizable binary input
  bit [3:0] gray;        // Output to store Gray code

  function void display(string name);
    $display("--------------------------");
    $display("%s", name);
    $display("--------------------------");
    $display("Binary = %b", binary);
    $display("Gray = %b", gray);
    $display("--------------------------");
  endfunction
endclass

----------------------------------------------------------------------
test module
---------------------------------------------------------------------
`timescale 1ns / 1ps
`include "environment.sv"

program test(intf i_intf);
  environment env;

  initial begin
    env = new(i_intf);
    env.test();
    $finish;
  end
endprogram
---------------------------------------------------------------------
Monitor Module
------------------------------------------------------------------------
`timescale 1ns / 1ps

class monitor;
  virtual intf vif;        // Virtual interface for DUT connections
  mailbox mon2scb;         // Mailbox to send transactions to the scoreboard

  // Constructor
  function new(virtual intf vif, mailbox mon2scb);
    this.vif = vif;
    this.mon2scb = mon2scb;
  endfunction

  // Main task to observe DUT behavior
task main();
  transaction trans;
  repeat(5) begin
    #10;                       // Increased propagation delay (align with Driver)
    trans = new();             // Initialize the transaction object
    trans.binary = vif.binary; // Capture binary input
    trans.gray = vif.gray;     // Capture Gray code output
    trans.display("Monitor");  // Display the transaction details
    mon2scb.put(trans);        // Send the transaction to the scoreboard
  end
endtask

endclass
-----------------------------------------------------------------------
Scoreboard Module
-----------------------------------------------------------------------
`timescale 1ns / 1ps
class scoreboard;
  mailbox mon2scb;
  logic [3:0] expected_gray; // Declare at the class level

  function new(mailbox mon2scb);
    this.mon2scb = mon2scb;
  endfunction

  task main();
    transaction trans;
    repeat(5) begin
      mon2scb.get(trans);        // Receive transaction
      expected_gray[3] = trans.binary[3];
      expected_gray[2] = trans.binary[3] ^ trans.binary[2];
      expected_gray[1] = trans.binary[2] ^ trans.binary[1];
      expected_gray[0] = trans.binary[1] ^ trans.binary[0];

      if (trans.gray == expected_gray)
        $display("PASS: Binary = %b, Gray = %b", trans.binary, trans.gray);
      else
        $error("FAIL: Binary = %b, Expected Gray = %b, DUT Gray = %b",
                trans.binary, expected_gray, trans.gray);
    end
  endtask
endclass

Here's an example of the errors:

FAIL: Binary = 1111, Expected Gray = 1000, DUT Gray = 1100
FAIL: Binary = 0001, Expected Gray = 0001, DUT Gray = 1100

What could be causing this mismatch, and how can I fix it? Is there an issue with my DUT implementation, testbench timing, or some other aspect?

Additional Details:

The simulation tool used is Synopsys VCS. All modules are instantiated and connected through a virtual interface. The errors occur inconsistently across different binary input values.

Share Improve this question edited Dec 3, 2024 at 12:49 toolic 61.8k19 gold badges79 silver badges126 bronze badges asked Nov 22, 2024 at 15:51 Kotupalli Venkata Siva TejaKotupalli Venkata Siva Teja 211 silver badge1 bronze badge 0
Add a comment  | 

1 Answer 1

Reset to default 1

The timing of the monitor is incorrect. Add a delay before you start creating the transactions from the interface signals. For example, add #5:

  // Main task to observe DUT behavior
task main();
  transaction trans;
  #5;
  repeat(5) begin
    #10;                       // Increased propagation delay (align with Driver)

The problem with your code is you have a simulation race condition. You are sampling the interface signals at the same time they are changing. The added delay guarantees that you will sample them when they are stable.

本文标签: verilogBinarytoGray code module failing testbench verification with mismatched outputsStack Overflow