Separating SystemVerilog nets before applying force - system-verilog

I want to force a signal down a hierarchy from my testbench. The modules are automatically created from schematics (changing design is not possible), and they are mostly based on wire type.
A code example can be found on EDA play ground.
//top level module
module dummy1(input A, output B);
dummy2 u_dummy2(A, B);
always #(A)
begin
assert (A == 1'b0) else $error("Force reached this level");
end
endmodule
module dummy2(input A, output B);
dummy3 u_dummy3(A, B);
endmodule
module dummy3(input A, output B);
assign B = A;
endmodule
If I force A in dummy3, it will change A in dummy2 and dummy1 which is something expected. I want to know if there is a way to separate A in dummy3 from A in dummy2 so that force is not applied to top level module.
module dummy_tb;
logic A, B;
dummy1 u_dummy1(A, B);
initial
begin
A = 0;
$display("step0: A=%b B=%b", u_dummy1.A,u_dummy1.B);
#1;
//force A1 to 1
force u_dummy1.u_dummy2.u_dummy3.A = 1'b1;
#1;
$display("step1: A=%b B=%b", u_dummy1.A,u_dummy1.B);
release u_dummy1.u_dummy2.u_dummy3.A;
#1;
$display("step2: A=%b B=%b", u_dummy1.A,u_dummy1.B);
//TODO: find something to separate A in u_dummy3 from A in u_dummy2, then force
end
endmodule

I can't think of a way to "separate" the nets without a change to the Verilog source code for the design modules, but you could achieve a similar effect by also forcing A in dummy2:
#1;
//force A1 to 1
force u_dummy1.u_dummy2.u_dummy3.A = 1'b1;
force u_dummy1.u_dummy2.A = 1'b0; // <-------- add this line
#1;
edaplayground

I think that this behavior results from a couple of quotes from the standard:
23.3.3 Port connection rules:
Each port connection shall be a continuous assignment of source to sink, where one connected item shall be
a signal source and the other shall be a signal sink. The assignment shall be a continuous assignment from
source to sink for input or output ports.
This makes dummy3.A the sink and dummy_tb.A the source.
10.6.2 The force and release procedural statements: A force procedural statement on a net shall override all drivers of the net—gate outputs, module outputs,
and continuous assignments—until a release procedural statement is executed on the net. When released,
the net shall immediately be assigned the value determined by the drivers of the net.
This makes dummy_tb.A a driver to the dummy3.A; So, basically verilog is forced to force all input ports on the way.
As a result, there is no way to do what you want without either forcing the port in the above level of hierarchy to a different value or to force outputs of continuous assignments in the low level module (force dummy3.B).

Related

recomend the way to write a monitor in UVM with defferent event polarity

I am trying to implement a monitor for VDU(Video display unit) and the way the VDU can be programmed says that sync signals have controllable polarity. This means than according to VDU settings monitor should react on #posedge or #negedge event. Is there any way to pass the type (means posesge or negedge) via configuration data base or do something like this. Instead of write if(truth) #posedge else #negedge. And assertion also needs to be controlled this way but assertion at list designed to take event type as an argument but I am no sure config data base calls are allowed inside interface.
On option is to conditionally trigger an event. For example, you can have the bellow in you interface:
event mon_clk_ev;
bit mon_polarity;
always #(posedge clk) if ( mon_polarity) ->mon_clk_ev;
always #(negedge clk) if (!mon_polarity) ->mon_clk_ev;
Then you can use mon_clk_ev are the clock event in your monitor, interface, clocking block, or assertion.
mon_polarity could be assigned by your monitor, uvm_config_db, or other logic.
Example using uvm_config_db (Note using uvm_bitstream_t so it can be assigned with the uvm_set_config_int plusarg):
initial begin
start_of_simulation_ph.wait_for_state( UVM_PHASE_STARTED, UVM_GTE );
if (!uvm_config_db#(uvm_bitstream_t)::exists(null,"","mon_polarity")) begin
// default if not in database
uvm_config_db#(uvm_bitstream_t)::set(null,"*","mon_polarity",1'b1);
end
forever begin
void'(uvm_config_db#(uvm_bitstream_t)::get(null,"","mon_polarity",mon_polarity));
uvm_config_db#(uvm_bitstream_t)::wait_modified(null,"","mon_polarity");
end
end
You should write your code assuming positive polarity, but feed them through an xor operator.
logic signal; // your signal from DUT
logic signal_corrected; // signal with positive polarity
bit signal_polarity; // 0 = positive ; 1 = negative
assign signal_corrected = signal ^ signal_polarity;
Now you can use signal_corrected in your assertions. You can certainly call uvm_config_db#(bit)::get() from the interface if it has been set in your testbench. You might need to use uvm_config_db#(bit)::wait_modified() to wait for it to be set before you get it.

I can't compile a .sv file (SystemVerilog)

I'm learning SystemVerilog for the university. I installed the extensions in Visual Studio Code for syntax highlighting: SystemVerilog, Verilog-HDL/SystemVerilog/Bluespec SystemVerilog (Names of extensions).
I installed the compiler Icarus Verilog and inserted the address in the environment variables (PATH).
So I copied this code:
module adder
(s, b, c_in, sum, c_out);
input logic [7:0] a;
input logic [7:0] b;
input logic c_in;
output logic [7:0] sum;
output logic c_out;
logic [8:0] result;
assign result = a + b + c_in;
assign sum = result [7:0];
assign c_out = result[8];
endmodule: adder
And tried to run it, but it gave me this error:
Module end labels require SystemVerilog.
I even tried to compile from the cmd with the same result.
A thing that I noticed is that when I do the same thing with a .v file (Verilog), it works.
I get a compile error in your port list. Change:
(s, b, c_in, sum, c_out);
to:
(a, b, c_in, sum, c_out);
You didn't declare a in the list, and you use a in the code. s is not in the code.
After that change, your code is legal SystemVerilog syntax, and it compiles without errors on multiple simulators on edaplayground.
I did get different compile errors from yours with Icarus Verilog 0.10.0 on edaplayground. Perhaps you are compiling with a different version. Keep in mind that iverilog does not support all SV features yet.
If the module label is still causing problems for you, you can simply remove it because it is optional. Change:
endmodule: adder
to:
endmodule
Regarding the file extensions (.v and .sv), some compilers will automatically enable SV features when you use .sv; perhaps some even require .sv. Since your code uses an SV keyword (logic), you must have SV features enabled to compile.
Here is a version of your code that does not rely on SV features:
module adder
(a, b, c_in, sum, c_out);
input [7:0] a;
input [7:0] b;
input c_in;
output [7:0] sum;
output c_out;
wire [8:0] result;
assign result = a + b + c_in;
assign sum = result [7:0];
assign c_out = result[8];
endmodule
Using logic in the port declarations is optional, and you can declare result as a wire.

How to use a parameter to add or remove a signal from a system verilog interface and modport

Here is a snippet of some interface code that has some parameterized sizes to it. The fourth parameter, HAS_BURST is something I have experimented with, but it has only resulted in compilation errors.
Effectively I am looking for a way to ADD/REMOVE a signal from a interface based on parameter. Is there a way to have a generic interface with removable signals?
interface axi_if
#(parameter ID_WIDTH = 4,
ADDR_WIDTH = 40,
DATA_WIDTH = 64,
HAS_BURST = 0)
();
logic aw_ready;
logic aw_valid;
logic [ID_WIDTH-1:0] aw_bits_id;
logic [ADDR_WIDTH-1:0] aw_bits_addr;
logic [7:0] aw_bits_len;
logic [2:0] aw_bits_size;
generate
if (HAS_BURST)
logic [1:0] aw_bits_burst;
endgenerate
logic [2:0] aw_bits_size;
modport slave (
output aw_ready,
input aw_valid,
input aw_bits_id,
input aw_bits_addr,
input aw_bits_len,
generate
if (HAS_BURST)
input aw_bits_burst,
endgenerate
input aw_bits_size
);
modport master (
input aw_ready,
output aw_valid,
output aw_bits_id,
output aw_bits_addr,
output aw_bits_len,
generate
if (HAS_BURST)
output aw_bits_burst,
endgenerate
output aw_bits_size
);
endinterface
`endif
No, there isn't. Ports aren't valid in generate blocks. Parameters can be used to asjust the width of a port but not remove it entirely. You could use an `ifdef to compile it conditionally but that's an all-or-none solution. There can't be some instances with the signal and others without it.
Having the signal unconditionally present is fine in many situations and it's the easiest way to handle this problem. Tie any unused inputs to logic 0 and unused outputs can remain unconnected.
If neither of these options work there's no other way than to define two different interfaces. Doing this by hand quickly becomes unmaintainable. If there are two variations now you can be sure a third one will be needed soon, then a fourth, a fifth... Many chip design companies have SystemVerilog code generators which create customized modules for each instance.

Multidriven nets: Synthesis ok, Simulation fails

I have a fundamental understanding problem with System Verilog. I am working on a processor design, where some bus systems should be shared between several processing units (System Verilog modules). With an arbiter only one module at a time should be active, driving the bus, while all other are high impedance.
I got rid of the multidriven nets warnings in Vivado during synthesis and there are not anymore any bus conflicts, but the simulator gives a warning, that the bus signals 'might' be multidriven. I made a tiny example code and I would expect to get for 'data' '11', when 'select' is '10'?
While simulation stops at all in Vivado, it works with Cadence simulator, but with wrong results - screenshot simulation
testbench.sv
`timescale 1ns / 1ps
module testbench_top();
logic [1:0] select;
logic [1:0] data;
top top_inst(.*);
initial
begin
select = 0;
#2 select = 1;
#2 select = 2;
#2 select = 0;;
end
initial
begin
$monitor("t=%3d s=%b,d=%b\n",$time,select,data);
end
endmodule
design.sv
`timescale 1ns / 1ps
module top
(
input logic [1:0] select,
output logic [1:0] data
);
driver_1 driver_1_inst(.*);
driver_2 driver_2_inst(.*);
endmodule
module driver_1
(
input logic [1:0] select,
output logic [1:0] data
);
always_comb
begin
if (select == 2'b10)
data = 2'b11;
else
data = 'z;
end
endmodule
module driver_2
(
input logic [1:0] select,
output logic [1:0] data
);
always_comb
begin
if (select == 2'b01)
data = 2'b01;
else
data = 'z;
end
endmodule
I'm assuming you expect the value of data signal the top module, which is driven by the two outputs of your driver modules, to be resolved (e.g. when one drive 'z, the other gets the bus.
This will happen if you declare the top.data signal as output wire logic [1:0] data.
Section 23.2.2.3 Rules for determining port kind, data type, and direction of the IEEE 1800-2012 standard states that
For output ports, the default port kind depends on how the data type
is specified: — If the data type is omitted or declared with the
implicit_data_type syntax, the port kind shall default to a net of
default net type. — If the data type is declared with the explicit
data_type syntax, the port kind shall default to variable.
In your case, the second clause applies, since you declared data as output logic[1:0], meaning that it was interpreted as a variable and not a net. Multiple values on variables aren't resolved (and in some tools are also illegal).

How do I sign extend in SystemVerilog?

Below is the code I have for my module:
module sext(input in[3:0], output out[7:0]);
always_comb
begin
if(in[3]==1'b0)
assign out = {4'b0000,in};
else
assign out = {4'b1111,in};
end
endmodule
For some reason this is not working. Instead of sign extending it is zero extending. Any ideas to why this might be the case?
I'm going to assume you meant (input [3:0] in, output [7:0] out). If that is true, then all you needed to write is
module sext(input signed [3:0] in, output signed [7:0] out);
assign out = in;
endmodule
You could also write
module sext(input [3:0] in, output [7:0] out);
assign out = 8'(signed'(in));
endmodule
And perhaps you don't even need to write this as a separate module.
Few things you need to take care is,
you haven't declared a data type for in and out, so by default they are wire and wire can't be used at LHS inside procedural block. Refer Section 6.5 Nets and variables (SV LRM 1800-2012). So either use a continuous assignment or declare it as a variable (i.e. reg/logic etc.).
The assignment of unpacked array is illegal in your example, so either use packed array or follow the instructions given in Section 10.10 Unpacked array concatenation (SV LRM 1800-2012)
It is not illegal syntax but assign used inside an always block probably does not do what you think it does. Use assign for wires and do not use it inside initial or always.
You have defined your port ranges after the name, this results in 4 and 8 1-bit arrays rather than a 4 and 8 bit value.
You have used {} for concatination, but they can also be used for replication ie {4{1'b1}}.
module sext(
input [3:0] in,
output reg [7:0] out ); //ranged defined before name
//No assign in always
//concatenation with replication
always_comb begin
out = { {4{in[3]}}, in};
end
endmodule
Or :
module sext(
input [3:0] in,
output [7:0] out ); //out left as wire
assign out = { {4{in[3]}}, in};
endmodule
I have seen your code.
There are some mistake in your code that you have to take care whiling writing the code.
You have use unpacked array so your targeted elements and actual elements are not match.
ERROR : Number of elements in target expression does not match the number of
elements in source expression.
This error can solve by using packed array.So, your targeted elements and actual elements are matched.
Here is link from where you will get better understanding regarding packed and unpacked array.
LINK : [http://www.testbench.in/SV_09_ARRAYS.html][1]
2.Another thing that you have to take care is you are storing some value in out signal(variable) like assign out = {4'b0000,in};
So you have to use reg data type to sore the value.
ERROR : Non reg type is not valid on the left hand side of this assignment
When you use reg data type then you can store value in out data type.
So, your problem is solved.
Here I also provide code which will run fine.
module sext(input [3:0]in, output reg [7:0]out);
always_comb
begin
if(in[3]==1'b0)
assign out = {4'b0000,in};
else
assign out = {4'b1111,in};
end
endmodule