这是我的设计和测试平台环境代码。
这是设计模块:
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
接口.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
交易.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
生成器.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
驱动程序.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
监视器.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
记分板.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
环境.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
测试.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
通过在 eda 中运行此代码(代码链接:https://edaplayground.com/x/F7jS)我得到以下输出
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.
正如我预期的那样,当监视器运行时,out2=35,但没有给出。
请建议我需要在代码中更改一些内容?
显示器有问题。
task main();
repeat(1)
#3;
第一个问题是延迟:
#3;
main
任务在时间0开始运行。#3
延迟将时间提前3个时间单位(3ns)。 也就是说,当您在监视器中构造 trans
对象时。 当您查看波形时,out2
在 3ns 处为 0。 您需要等到 out2
在 25ns 时刻变为 'h35。 您可以通过将延迟更改为:
#30ns;
第二个问题是您注释掉了从接口采样
out2
信号的代码。 由于您从未更改 trans.out2
的值,因此无论初始延迟是多少,它都保持默认值 0。
您需要取消注释这些行:
trans.out0 = vif.out0;
trans.out1 = vif.out1;
trans.out2 = vif.out2;
还有一个问题是显示器不应该设置接口信号。 您应该从监视器中删除这些行:
vif.out0 = trans.out0;
vif.out1 = trans.out1;
vif.out2 = trans.out2;
在驱动程序中,不应在接口中设置“out”信号。 删除这些行:
vif.out0 <= trans.out0;
vif.out1 <= trans.out1;
vif.out2 <= trans.out2 ;
查看此更新的EDA Playground。 这是我得到的输出,显示 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