Here is my design and testbench environment code.
This is design module:
module router_1x3 (
input wire clk,
input wire rst,
input wire [7:0] data_in, // 8-bit data input
input wire [1:0] sel, // 2-bit select signal
output reg [7:0] out0, // Output channel 0
output reg [7:0] out1, // Output channel 1
output reg [7:0] out2 // Output channel 2
);
always @(posedge clk or posedge rst) begin
if (rst) begin
out0 <= 8'b0; // Reset output 0
out1 <= 8'b0; // Reset output 1
out2 <= 8'b0; // Reset output 2
end else begin
case (sel)
2'b00: begin
out0 <= data_in;
out1 <= 8'b0;
out2 <= 8'b0;
end
2'b01: begin
out0 <= 8'b0;
out1 <= data_in;
out2 <= 8'b0;
end
2'b10: begin
out0 <= 8'b0;
out1 <= 8'b0;
out2 <= data_in;
end
default: begin
out0 <= 8'b0;
out1 <= 8'b0;
out2 <= 8'b0;
end
endcase
end
end
endmodule
interface.sv
interface intf();
logic clk;
logic rst;
logic [7:0] data_in;
logic [1:0] sel;
logic [7:0] out0;
logic [7:0] out1;
logic [7:0] out2;
endinterface
transaction.sv
class transaction;
rand bit [7:0] data_in;
rand bit [1:0] sel;
bit [7:0] out0;
bit [7:0] out1;
bit [7:0] out2;
constraint valid_sel {sel <= 2'b10;}
function void display(string name);
$display("---------- %s --------- %t", name, $time);
$display("data_in=%h, sel=%h, out0=%h, out1=%h, out2=%h",
data_in, sel, out0, out1, out2);
endfunction
endclass
generator.sv
class generator;
transaction tx;
mailbox gen2drv;
// Constructor
function new(mailbox gen2drv);
this.gen2drv = gen2drv;
endfunction
task main();
tx = new();
if (tx.randomize()) begin
tx.display("generator");
gen2drv.put(tx);
end
endtask
endclass
driver.sv
class driver;
transaction trans;
virtual intf vif;
mailbox gen2driv;
function new(virtual intf vif, mailbox gen2driv);
this.vif = vif;
this.gen2driv = gen2driv;
endfunction
task main();
repeat(1)
begin
gen2driv.get(trans);
trans.display("Driver");
// vif.data_in = trans.data_in;
// vif.sel = trans.sel;
// vif.out0 = trans.out0;
// vif.out1 = trans.out1;
// vif.out2 = trans.out2 ;
vif.data_in <= trans.data_in;
vif.sel <= trans.sel;
vif.out0 <= trans.out0;
vif.out1 <= trans.out1;
vif.out2 <= trans.out2 ;
end
endtask
endclass
monitor.sv
class monitor;
virtual intf vif;
mailbox mon2sbc;
transaction trans;
function new(virtual intf vif, mailbox mon2sbc);
this.vif = vif;
this.mon2sbc = mon2sbc;
endfunction
task main();
repeat(1)
#3;
begin
trans = new();
trans.data_in = vif.data_in;
trans.sel = vif.sel;
// trans.out0 = vif.out0;
// trans.out1 = vif.out1;
// trans.out2 = vif.out2;
vif.out0 = trans.out0;
vif.out1 = trans.out1;
vif.out2 = trans.out2;
mon2sbc.put(trans);
#1
trans.display("Monitor");
end
endtask
endclass
scoreboard.sv
class scoreboard;
mailbox mon2sbc;
transaction trans;
function new(mailbox mon2sbc);
this.mon2sbc = mon2sbc;
endfunction
task main();
repeat(1)
begin
mon2sbc.get(trans);
trans.display("Scoreboard");
end
endtask
endclass
environment.sv
`include "transaction.sv"
`include "generator.sv"
`include "driver.sv"
`include "scoreboard.sv"
`include "monitor.sv"
class environment;// it's complete environment of dut
// which is contain all component of testbench and connect tham
generator gen;
driver driv;
monitor mon;
scoreboard scb;
mailbox m1;
mailbox 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_none
endtask
task run;
test();
#100
$finish;
endtask
endclass
test.sv
`include "environment.sv"
program test(intf i_intf);//this connect interface to testbech environment
environment env;
initial
begin
env = new(i_intf);
env.run();
end
endprogram
testbenchtop.sv
// Code your testbench here
// or browse Examples
`include "interface.sv"
`include "test.sv"
module tbench_top;
intf router_vif();
test t1(router_vif);
router_1x3 dut (
.clk(router_vif.clk),
.rst(router_vif.rst),
.data_in(router_vif.data_in),
.sel(router_vif.sel),
.out0(router_vif.out0),
.out1(router_vif.out1),
.out2(router_vif.out2)
);
// Clock generation
initial begin
router_vif.clk = 0;
forever #5 router_vif.clk = ~router_vif.clk;
end
// Reset logic
initial begin
router_vif.rst = 1;
#20;
router_vif.rst = 0;
end
initial
begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
by running this code in eda (link of code: https://edaplayground.com/x/F7jS) i get following output
ERNEL: ASDB file was created in location /home/runner/dataset.asdb
# KERNEL: ---------- generator --------- 0
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=00
# KERNEL: ---------- Driver --------- 0
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=00
# KERNEL: ---------- Scoreboard --------- 3
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=00
# KERNEL: ---------- Monitor --------- 4
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=00
# RUNTIME: Info: RUNTIME_0068 environment.sv (44): $finish called.
As I expected when monitor runs, out2=35, but it's not given.
Please suggest me something which I need to change in my code?
There are problems in the monitor.
task main();
repeat(1)
#3;
The first problem is the delay:
#3;
The main
task starts running at time 0. The #3
delay advances time by 3 time units (3ns). That is when you construct the trans
object in the monitor. When you look at waveforms, out2
is 0 at 3ns. You need to wait until out2
changes to 'h35 at time 25ns. You can do so by changing the delay to:
#30ns;
The second problem is that you commented out the code that samples the out2
signals from the interface. Since you never change the value of trans.out2
, it remains at its default value of 0, no matter what the initial delay is.
You need to uncomment these lines:
trans.out0 = vif.out0;
trans.out1 = vif.out1;
trans.out2 = vif.out2;
Another problem is that the monitor should not set interface signals. You should remove these lines from the monitor:
vif.out0 = trans.out0;
vif.out1 = trans.out1;
vif.out2 = trans.out2;
In the driver, you should not set the "out" signals in the interface. Delete these lines:
vif.out0 <= trans.out0;
vif.out1 <= trans.out1;
vif.out2 <= trans.out2 ;
This is the output I get, which shows out2=35:
# KERNEL: ---------- Scoreboard --------- 30.000000 ns
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=35
# KERNEL: ---------- Monitor --------- 31.000000 ns
# KERNEL: data_in=35, sel=2, out0=00, out1=00, out2=35