I'm trying to compile a small UVM verification environment in EDA playground.
I'm getting this error:
EDA playground ERROR VCP5294 "Undefined package uvm_pkg.
The code attached below:
import uvm_pkg::*;
`include "reg_pkg.sv"
module testbench;
reg rst;
reg clk;
always #50 clk = ~clk;
initial begin
rst=0;
clk=0;
#100;
rst = 1;
`uvm_info("TESTBENCH",$sformatf("rst raised"),UVM_NONE);
end
reg_if reg_if_i();
assign reg_if_i.clk = clk;
assign reg_if_i.rst = rst;
WriteRegisters WriteRegisters_i(
.clk(reg_if_i.clk),
.rst(reg_if_i.rst),
.bus_en(reg_if_i.bus_en),
.bus_wr_rd(reg_if_i.bus_wr_rd),
.bus_data(reg_if_i.bus_data),
.bus_addr(reg_if_i.bus_addr)
);
initial begin
uvm_config_db#(virtual mux_if)::set(null,"*","reg_if_i",reg_if_i);
$dumpvars(0, testbench);
end
initial begin
run_test("reg_test1");
end
endmodule
Do you know why I get this error?
When using UVM on EDA Playground, you need to explicitly select a UMV library version in the left side panel. Currently "UVM/OVM" is set to None.
When I set it to UVM 1.2, the error goes away, as you can see below:
[2023-01-08 09:29:19 EST] vlib work && vlog '-timescale' '1ns/1ns' +incdir+$RIVIERA_HOME/vlib/uvm-1.2/src -l uvm_1_2 -err VCP2947 W9 -err VCP2974 W9 -err VCP3003 W9 -err VCP5417 W9 -err VCP6120 W9 -err VCP7862 W9 -err VCP2129 W9 design.sv testbench.sv && vsim -c -do "vsim +access+r; run -all; exit"
VSIMSA: Configuration file changed: `/home/runner/library.cfg'
ALIB: Library "work" attached.
work = /home/runner/work/work.lib
MESSAGE "Pass 1. Scanning modules hierarchy."
MESSAGE_SP VCP2124 "Package uvm_pkg found in library uvm_1_2."
Here is the modified EDA Playgound link.
It is also helpful to look at the examples in the left side panel: Examples -> UVM -> UVM Hello World
Related
I wanted to wait on the output variable of a task.
eg: wait(user_defined_task_name(output_variable_type_name) == 1)
In this example shown below, my intention is to make wait statement to be active from 0ns to 3ns (basically from the beginning of timestamp till t2=1)
Here is a working example;
class cl;
task run(output bit t);
$display("time=%0t , t=%0b",$realtime, t);
#1;
$display("time=%0t , t=%0b",$realtime, t);
#2;
t = 1;
$display("time=%0t , t=%0b",$realtime, t);
endtask
endclass
class c2 extends cl;
bit t2;
task run1();
wait(run(t2) == 1); // error from this line, what am i violating here?
$display("t2 working t2=%0b time = %0t", t2, $realtime);
endtask
endclass
module tmp;
c2 c2_h=new;
initial begin
c2_h.run1();
$display("test msg");
end
endmodule
eda output log:
Top Level Modules:
tmp TimeScale is 1 ns / 1 ns
Error-[XMREF] Cross-module reference resolution error testbench.sv, 19
Cross-module reference resolution error is found. Function is
expected, but actual target is not a function. Source info:
run(this.t2)
1 error CPU time: .116 seconds to compile Exit code expected: 0,
received: 1
A couple of problems with your code. A task does not return a value and cannot be used in an expression. You can only call it as a stand alone statement. But if you change run to a function functions cannot consume time.
In your particular example, you do not change the value of the t argument until the end of the task, and output arguments are copied out upon exiting the task, so you might as well just call the task run(t2) as a statement and it will block until returning.
task run1();
run(t2);
$display("t2 working t2=%0b time = %0t", t2, $realtime);
endtask
If on the otherhand run set the t argument somewhere in the middle of the task, and you want to continue the run1 task as soon as that happened, the you would have use a fork/join_none and a ref argument instead.
class cl;
task run(ref bit t);
$display("time=%0t , t=%0b",$realtime, t);
#1;
$display("time=%0t , t=%0b",$realtime, t);
#2;
t = 1;
#2;
$display("time=%0t , t=%0b",$realtime, t);
endtask
endclass
class c2 extends cl;
bit t2;
task run1();
fork
run(t2);
join_none
wait(t2 == 1);
$display("t2 working t2=%0b time = %0t", t2, $realtime);
endtask
endclass
When I run your code on the Cadence simulator, I get a different message:
xmvlog: *E,INVCTX The task 'run' cannot be used in this context.
Using the nchelp utility to get more information on that message:
A task or void function cannot be passed as an actual argument
because they do not return a value that can be used. They also cannot
be used as part of an expression.
In your simple example, there seems to be no need to use wait. You can simply call the task on its own:
task run1();
run(t2);
$display("t2 working t2=%0b time = %0t", t2, $realtime);
endtask
I´m new to systemverilog and trying to build a systemverilog testbench.
I have a DUT that should be connected to one of two external modules via a multiplexer. I want to switch the connection during simulation and I want to use systemverilog interfaces for the connection between the DUT and the multiplexer as well as the connection between multiplexer and the two external modules. The signals in the interface are bidirectional.
I am facing trouble writing the multiplexer. I´m getting an error for the current implementation that the LHS of the expression can´t be a wire. If I change the type in the interface to logic, I get an error that this is not possible with bidirectional signals.
I tried to google, but I didn´t find any tutorials on connecting interface to interface. Is this not possible? Or is there a better way of doing what I´m trying to do?
So far I have the following:
interface flash_connect_interface;
wire interface_f_cle;
wire interface_f_ale;
endinterface: flash_connect_interface
module flash_connect_testbench_top;
[...]
// Interfaces
flash_connect_interface flash_connect_interface_i0();
flash_connect_interface flash_connect_interface_i1();
flash_connect_interface flash_connect_interface_i2();
// Connecting DUT to interface
flash_connect flash_connect_i0(
.flash_connect_interface_i(flash_connect_interface_i0),
);
// Multiplexer
flash_connect_mux mux1(
.flash_connect_interface_i_0(flash_connect_interface_i0),
.flash_connect_interface_i_1(flash_connect_interface_i1),
.flash_connect_interface_i_2(flash_connect_interface_i2),
.select(sel)
);
nand_model nand_model0 (
.Cle (flash_connect_interface_i1.interface_f_cle),
.Ale (flash_connect_interface_i1.interface_f_ale),
);
nand_model nand_model1 (
.Cle (flash_connect_interface_i2.interface_f_cle),
.Ale (flash_connect_interface_i2.interface_f_ale),
);
[...]
endmodule // end testbench_top
module flash_connect_mux(
flash_connect_interface flash_connect_interface_i_0,
flash_connect_interface flash_connect_interface_i_1,
flash_connect_interface flash_connect_interface_i_2,
input select
);
always_comb begin
// *** Here is the problem ***
if (select == 1'b0) flash_connect_interface_i_1 = flash_connect_interface_i_0;
else flash_connect_interface_i_2 = flash_connect_interface_i_0;
end
endmodule
The interfaces in this case is just bundle of wires . There seems nothing apparently wrong with your code. But if you are trying to assign interface directly to each other based on the select signal it will not work. You will need to assign all the wires individually based on the select signal. There is nothing special to mux interfaces.
The code below does the muxing.
interface flash_connect_interface;
wire interface_f_cle;
wire interface_f_ale;
endinterface: flash_connect_interface
module nand_model ( inout Cle , inout Ale ) ; // Sample nand model
reg r = 1;
assign Cle = r?1:1'bz;
assign Ale = r?1:1'bz;
endmodule
module flash_connect_mux ( flash_connect_interface flash_connect_interface_i_0 , flash_connect_interface flash_connect_interface_i_1 , flash_connect_interface
flash_connect_interface_i_2 ,input [3:0] select ) ;
// Interconnect interface assignment
assign flash_connect_interface_i_0.interface_f_cle = (select== 0) ? flash_connect_interface_i_1.interface_f_cle : flash_connect_interface_i_2.interface_f_cle;
assign flash_connect_interface_i_0.interface_f_ale = (select== 0) ? flash_connect_interface_i_1.interface_f_ale : flash_connect_interface_i_2.interface_f_ale;
endmodule
module flash_connect ( flash_connect_interface flash_connect_interface_i ) ;
//check flash_connect_interface_i.interface_f_cle ;
//check flash_connect_interface_i.interface_f_ale ;
endmodule
module flash_connect_testbench_top;
reg [3:0] select ;
// Interfaces
flash_connect_interface flash_connect_interface_i0();
flash_connect_interface flash_connect_interface_i1();
flash_connect_interface flash_connect_interface_i2();
// Connecting DUT to interface
flash_connect flash_connect_i0(
.flash_connect_interface_i(flash_connect_interface_i0)
);
// Multiplexer
flash_connect_mux mux1(
.flash_connect_interface_i_0(flash_connect_interface_i0),
.flash_connect_interface_i_1(flash_connect_interface_i1),
.flash_connect_interface_i_2(flash_connect_interface_i2),
.select(select)
);
nand_model nand_model0 (
.Cle (flash_connect_interface_i1.interface_f_cle),
.Ale (flash_connect_interface_i1.interface_f_ale)
);
nand_model nand_model1 (
.Cle (flash_connect_interface_i2.interface_f_cle),
.Ale (flash_connect_interface_i2.interface_f_ale)
);
endmodule // end testbench_top
Link to interface tutorial -
https://www.doulos.com/knowhow/sysverilog/tutorial/interfaces/
I have an system verilog interface
interface add_sub_if(
input bit clk,
input [7:0] a,
input [7:0] b,
input doAdd,
input [8:0] result
);
clocking dut_cb #(posedge clk);
output a;
output b;
output doAdd;
input result;
endclocking // cb
modport dut(clocking dut_cb);
endinterface: add_sub_if
And i have a SV module which uses this interface
module dummy(add_sub_if.dut _if);
....
endmodule: dummy
What is the ideal way to hook up this in my TB?
If i instantiate the interface, i need to create wires.
If i use bind then also i need to do a port mapping of the individual signals, that beats the convenience of having an interface.
Another add on question is, how to assign one such interface to another interface?
Thanks in advance,
Rajdeep
You can find a simple example of an interface definition and usage in the IEEE Std 1800-2012 Section 3.5 (Interfaces). It shows how to define the interface and hook it up to the design (the way you have already done it). It also shows how the interface can be instantiated (and connected) inside a top level module/wrapper (I copied the code below directly from the spec for your convenience):
interface simple_bus(input logic clk); // Define the interface
logic req, gnt;
logic [7:0] addr, data;
logic [1:0] mode;
logic start, rdy;
endinterface: simple_bus
module memMod(simple_bus a); // simple_bus interface port
logic avail;
// When memMod is instantiated in module top, a.req is the req
// signal in the sb_intf instance of the 'simple_bus' interface
always #(posedge clk) a.gnt <= a.req & avail;
endmodule
module cpuMod(simple_bus b); // simple_bus interface port
...
endmodule
module top;
logic clk = 0;
simple_bus sb_intf(.clk(clk)); // Instantiate the interface
memMod mem(.a(sb_intf)); // Connect interface to module instance
cpuMod cpu(.b(sb_intf)); // Connect interface to module instance
endmodule
Once you have the interface hooked up, then you can have drive/sample all the signals from a testcase program (just remember that you have to pass the interface to it). In this case, it would be be something like:
program testcase(simple_bus tb_if);
initial begin
tb_if.mode <= 0;
repeat(3) #20 tb_if.req <= 1'b1;
[...]
$finish;
end
endprogram
For a real-world example, you can check the source code of a UVM testbench that is available on my GitHub page. The interface hook-up is done in the xge_test_top.sv file.
Here is fsm dut with testbench.
This fsm dut performs state transition 1 - 0 - 1 - 0 in sequence.
Test bench verifies dut is properly working or not.
verilog module code(dut) :
module melay_fsm(o,clk,rst,i);
output o;
input i,clk,rst;
reg o;
reg [1:0]state;
// [1:0]state;
always#(posedge clk,posedge rst)
begin
if(rst)
begin
state <=2'b00;
end
else
begin
case(state)
2'b00:
begin
if(i)
state<=2'b01;
else
state<=2'b00;
end
2'b01:
begin
if(!i)
state<=2'b10;
else
state<=2'b01;
end
2'b10:
begin
if(i)
state<=2'b11;
else
state<=2'b00;
end
2'b11:
begin
if(!i)
state<=2'b00;
else
state<=2'b01;
end
endcase
end
end
always#(posedge clk,negedge rst)
begin
if(rst)
o<=1'b0;
else if(state==2'b11 && i==0)
o<=1'b1;
else
o<=1'b0;
end
endmodule
System verilog module code(testbench) :
interface melay_intf(input bit clk);
logic o,rst,i;
wire clk;
clocking c1#(posedge clk);
input o;
output i,rst;
endclocking
modport tes(clocking c1);
endinterface
module top;
bit clk;
always
#1 clk = ~clk;
melay_intf i1(clk);
melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
melay_tes(i1);
endmodule
program melay_tes(melay_intf i1);
initial
#100 $finish;
initial
begin
i1.rst <= 0;
#4 i1.rst <= 1;
#4 i1.rst <= 0;
i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
repeat(10)
begin
i1.i = 1;
#2 i1.i = $urandom_range(0,1);
end
end
initial
$monitor("output = %d clk = %d rst = %d i = %d",i1.o,i1.clk,i1.rst,i1.i);
initial
begin
$dumpfile("mem.vcd");
$dumpvars();
end
endprogram
Important thing to note down here is connection of signals in top module.
melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
Please, observe properly how I bind interface with testbench and dut.
Please, observe following things.
I defines interface with all the dut's signals.
I took instance(i1) of interface(melay_intf) in top module.
I took instance (a1) of dut (melay_fsm) in top module.
Now observes melay_fsm a1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i))
All the dut's signals are connected with interface.
I passed instance of interface(i1) in testbench. melay_tes(i1)
So, testbench can access interface signals and interface signals are connected to dut's signals.
Now, you can access dut's signals in your test bench with help of interface.
I think now you can understand proper flow.
Please ask the question if you have any doubt.
You can bind interface in system verilog module.
Here, I provides sample code with help of that you can understood how to bind interface in system verilog module and with dut.
Here I provides verilog module and system verilog module. Main part of code is interface from which verilog and system verilog module are connected.
verilog module code(dut) :
module dff(qn,d,clk,reset);
output qn;
input d,clk,reset;
reg qn;
always#(posedge clk,negedge reset)
begin
if (!reset)
begin
qn=1'bx;
end
else if (d==0)
begin
qn=0;
end
else if (d==1)
begin
qn=1;
end
end
endmodule
System verilog module code(testbench) :
interface melay_intf(input bit clk);
logic o,clk,rst,i;
clocking c1#(posedge clk);
input o;
output i,rst;
endclocking
endinterface
module top;
bit clk;
always
#1 clk = ~clk;
melay_intf i1(clk);
dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i));
melay_tes(i1.tes);
endmodule
program melay_tes(melay_intf i1);
initial
#100 $finish;
initial
begin
i1.rst <= 0;
#4 i1.rst <= 1;
#4 i1.rst <= 0;
i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
#2 i1.i = 1;
#2 i1.i = 0;
repeat(10)
begin
i1.i = 1;
#2 i1.i = $urandom_range(0,1);
end
end
initial
$monitor("output = %d clk = %d rst = %d i = %d",i1.o,i1.clk,i1.rst,i1.i);
initial
begin
$dumpfile("mem.vcd");
$dumpvars();
end
endprogram
Here important part is interface and in it I used clocking block for synchronization purpose. Here clocking c1#(posedge clk); so all signals which are mention inside the clocking block which are i,o,rst.All this signal change its value at every posedge of clk signal.
Here dff d1(.o(i1.o),.clk(i1.clk),.rst(i1.rst),.i(i1.i)); Important thing that you find in top module I made connection between verilog signals and system verilog signals.
You can find verilog module name is "dff". I took the instance of dff verilog module and made the connection. Here i1.o,i1.clk,i1.rst,i1.i is system verilog signals which are connected to o,clk,rst,i signals of verilog module of with dot convention.
I have a problem with the following source. When it is compiled in gfortran, it does not work properly and then two error message showed up.
How do I solve this problem?
Any comment would be very helpful.
Thanks in advance.
program driver
integer i,ln,n,e,count,x,a,b,total
character driverid*12,var*12,ch*12
parameter (n=720321)
c parameter (n=55062)
dimension var(n),a(n),b(n)
write(*,*) 'input run id(text)'
read(*,55) driverid
55 format(a)
ln=index(driverid,' ')-1
open(6,file=driverid(1:ln)//'.out',form='formatted'
+,status='unknown')
open(1,file=driverid(1:ln)//'.txt',status='old')
do i=1,2
read(1,*)
end do
read(1,*) (var(i),i=1,n)
close(1)
total=0
count=1
do i=1,n
b(i)=0
read(var(i),*,iostat=e) x
if (e .eq. 0) then
a(count)=x
count=count+1
else
ln=index(var(i),' ')-1
if (var(i)(ln-1:ln-1) .eq. 'r') then
var(i)=var(i)(1:ln-2)
else
var(i)=var(i)(1:ln-1)
end if
read(var(i),'(i)') b(count-1)
end if
end do
do i=1,count
total=total+1+b(i)
end do
do i=1,total
write(6,'(10i)') (a(i),j=1,b(i))
end do
close(6)
end
Error message is following as
$ gfortran driver.f
driver.f:43.23:
read(var(i),'(i)') b(count-1)
1
Error: Nonnegative width required in format string at (1)
driver.f:53.20:
write(6,'(10i)') (a(i),j=1,b(i))
1
Error: Nonnegative width required in format string at (1)
When specifying a format for an integer, you must specify the field width. If you want to have it flexible, you can set it to zero:
write(6, "(10I0)") ...
I am trying to make a module (a DSP in my case) with a standardized memory interface in SystemVerilog, and would like the variables in the module to size automatically based on the bus widths in the attached interface. My rationale: this makes the code more portable by allowing it to auto-size to any connected interface, instead of requiring an HDL coder to pass in parameters that tell the module the widths of all the interface busses that will connect to it (not that this would be terrible, it just seems cleaner without the parameters).
I can't seem to get this to work, however. Here's an example that illustrates the problem; the following synthesizes in Quartus II 12.1:
// Top level module with some 15-bit ports
module top ( input [14:0] data_in,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
test_interface my_interface(); // Initialize the interface
test_module my_module(.*); // Initialize & connect module
endmodule
// Define a simple interface:
interface test_interface ();
logic [8:0] my_port;
endinterface
// Define the module:
module test_module ( input [14:0] data_in,
test_interface my_interface,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
localparam width1 = $size(data_in); // should be 15
localparam width2 = $size(my_interface.my_port); // should be 9
logic [width1-1:0] auto_sized1; // gets correct size (14:0)
logic [width2-1:0] auto_sized2; // **PROBLEM**: gets size of 0:0!
always_comb begin
auto_sized1 = 5; // ok
auto_sized2 = 5; // problem; value now truncated to 1
data_out1 = data_in + width1; // Yields data_in + 15 (ok)
data_out2 = data_in + width2; // Yields data_in + 9 (ok...!)
data_out3 = data_in + auto_sized1; // Yields data_in + 5 (ok)
data_out4 = data_in + auto_sized2; // Yields data_in + 1 (problem)
end
endmodule
Note that width2 does eventually get the correct value (9) - just too late for it to correctly set the width of auto_sized2. I initially thought that $size was simply evaluated after all variables had been assigned their widths, but this doesn't seem to be the case either since $size(data_in) works just fine for setting the width of auto_sized1.
Any thoughts? Again, it's not critical to the project's success, I'm mostly curious at this point!
Thanks -
Looks like a compiler bug. I'd probably use a parameter in the interface definition.
module top ( input [14:0] data_in,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
test_interface #(.port_size(8)) my_interface(); // Initialize the interface
test_module my_module(.*); // Initialize & connect module
endmodule
interface test_interface ();
parameter port_size = 1;
logic [port_size-1:0] my_port;
endinterface
module test_module ( input [14:0] data_in,
test_interface my_interface,
output [14:0] data_out1, data_out2,
data_out3, data_out4 );
localparam width1 = $size(data_in);
localparam width2 = my_interface.port_size;
endmodule