Can I use bind inside generate block - system-verilog

I've a simple assertion:
Lets say
assert #(posedge clk) (a |=> b);
I generally connect it with design signals using separate binding module
module bind_module;
bind dut assertion a1 (.*);
endmodule
I've a situation: dut has a bus of 45bits, each bit is generated / driven individually but all of them follow same assertion.
Can I use bind statement inside generate block? (for a range of 0 to 44) and then instead of .* use .a (in_bus[i]), .b (out_bus[i])

Assuming you intend the following:
genvar i;
generate
for(i=0; i<45; i=i+1) begin : gen_asrt
bind dut assertion a1( .a(in_bus[i]), .b(out_bus[i]), .* );
end
This will not work for 2 reasons:
The instance name a1 is being clobbered on each loop. Each instance name within a module needs to be unique. Quoting from IEEE std 1800-2012 § 23.11 'Binding auxiliary code to scopes or instances':
It is legal for more than one bind statement to bind a bind_instantiation into the same target scope. However, it shall be an error for a bind_instantiation to introduce an instance name that clashes with another name in the module name space of the target scope (see 3.13). This applies to both preexisting names as well as instance names introduced by other bind statements. The latter situation will occur if the design contains more than one instance of a module containing a bind statement.
i in the bind statement is referring to an i variable name within the scope of dut, not the genvar i. Again, quoting from IEEE std 1800-2012 § 23.11 'Binding auxiliary code to scopes or instances':
When an instance is bound into a target scope, the effect will be as if the instance was present at the very end of the target scope. In other words, all declarations present in the target scope or imported into the target scope are visible to the bound instance. Wildcard import candidates that have been imported into the scope are visible, but a bind statement cannot cause the import of a wildcard candidate. Declarations present or imported into $unit are not visible in the bind statement.
How to bind this kind of checker:
You could create one module that handles the generate statements, then instantiate that module with a bind statement. Example:
module bind_assertions #(parameter SIZE=1) ( input clock, input [SIZE-1:0] a,b );
genvar i;
generate
for(i=0; i<SIZE; i=i+1) begin : gen_asrt
assertion a1_even( .a(a[i]), .b(b[i]), .* );
end
endgenerate
endmodule
bind dut bind_assertions#(45) a1( .a(in_bus), .b(out_bus), .* );
Technically, you could bind an array of instances. It is legal syntax according to &sect 23.11's Syntax 23-9 plus Appendix A.4.1.1 'Module instantiation'. However it this seems to fail on all the simulators I currently have access to. Example (if it works on your simulator):
bind dut assertion a1[44:0]( .a(in_bus[44:0]), .b(out_bus[44:0]), .* );
Can bind exist within a generate block?
IEEE std 1800-2012 § 27.3 'Generate construct syntax' does mention bind_directive within the syntax for generate constructs is given in Syntax 27-1. Like binding an array of instances, not all simulators support this feature yet. IEEE std 1800-2009 § 27.3 also mentions bind_directive but IEEE std 1800-2005 (first IEEE version of SystemVerilog) does not. Example (if it works on your simulator):
parameter DO_BIND=1;
generate
if(DO_BIND==1) begin
bind dut bind_assertions#(45) a1( .a(in_bus), .b(out_bus), .* );
end
endgenerate

Related

Hierarchical paths to access local variables in bind files?

It's a common methodology to keep assertions, cover points, etc. separate from the design by putting them in a separate module or interface, and use bind to attach them to the design, e.g.,
module foo (input a);
wire b = a;
endmodule
interface foo_assertions (input a, b);
initial #1 assert (b == a);
endinterface
bind foo foo_assertions i_foo_assertions(.*);
One problem with this is that it requires maintenance of the port list in foo_assertions. However, if foo has a bar submodule, signals inside bar can be accessed conveniently using hierarchical references in the assertions file relative to foo, e.g., assert (i_bar.sig == a).
Is there a way to use the hierarchical path syntax for accessing variables declared directly in foo as well, eliminating the need for the port list in foo_assertions? Note that foo is not necessarily the top-level module, so $root.b will not work. It looks like foo.b works, however is this safe when multiple instances of foo exist at the top level?
Verilog has always had upwards name referencing which is why foo.b works (See section 23.8 in the IEEE 1800-2017 SystemVerilog LRM). It does not matter how many instances of foo there are, as long as you only bind foo_assertions into a module named foo. Each upward reference applies to the specific instance that reference is underneath.
When referring to the top-level module in a hierarchical path, you have been using an upwards reference without necessarily realizing it.

verilog_mode autoreginput behavior when using assignment

I wonder if the following case is possible.
I have :
module a(
input [2:0] a_i
);
endmodule
module b ();
/*AUTOREGINPUTS*/
a u_a(/*AUTOINST*/)
endmodule
It expands to:
module b ();
/*AUTOREGINPUTS*/
reg [2:0] a_i;
a u_a(/*AUTOINST*/
.a_i(a_i))
endmodule
But if I modify adding the line assign a_i = '0;, then it does not expands AUTOREGINPUTS anymore. Is there a way to expand it even if I'm doing an assignment ?
The short answer is because when running verilog-auto to fill in /*AUTOREGINPUT*/ will exclude any signal that is already declared and by adding assign a_i = '0;, you are declaring a_i.
In Verilog, explicit variable declarations are not required and will take on the default nettype if left undeclared under certain circumstances. So, if I had the following:
module x;
assign myVar = '0;
endmodule
myVar will be implicitly declared to be a net with the default nettype (which by default is wire). You can read more in the System-Verilog LRM (IEEE1800-2009 Section 6.10). One recommendation to avoid typos generating implicitly declared variables is to change the default nettype with the `default_nettype macro to none (ie `default_nettype none on the top of every file); doing this forces all variables to be explicitly declared or the compiler/synthesizer will throw an error.
verilog-mode mode in emacs is aware of implicit declaration and, as such, will not autogenerate anything declared. Thus, when you add the assign statement, you are declaring a_i and so the autogenerator will not "redefine" a_i.
To avoid this, I can only recommend running the generator before you assign any of the variables to be autogenerated. Im not sure if it handles `default_nettype none correctly, but I would assume not.
Also note, it should be /*AUTOREGINPUT*/, not /*AUTOREGINPUTS*/, no 's' at the end.

system verilog disabling `ifndef blocks in specific instances

In a system verilog design, I have a top-module, sub-module and a sub-sub module. sub-sub module instantiated in sub-module instantiated in top module.Top module also has an instance of sub-sub module.The hierarchy tree is shown below
The sub-sub module definition has some code written in a 'ifndef block like this
module sub_sub()
{
...........
`ifndef OFF
<code to avoid>
`endif
...........
}
How can I disable the code to avoid only in sub-sub module instance1 during compilation?
I used `define OFF in sub-module instance but it disables code to avoid from all instances.
The cleaner solution is to pass a parameter and use a generate-if/case statement. Example:
module sub_sub #(parameter OFF=0) ( ... );
generate
if (OFF) begin
<code to avoid>
end
endgenerate
endmodule
module sub ( ... );
...
sub_sub #( .OFF(1'b1) ) inst ( ... );
endmodule
module top ( ... );
...
sub inst0 ( ... );
sub_sub #( .OFF(1'b0) ) inst1 ( ... );
endmodule
Technically the the if (OFF) does not need to be in an explicit generate-endgenerate; it is inferred otherwise. It is recommended for human readability.
For full detail on generate blocks, refer to IEEE Std 1800-2012 § 27. Generate constructs
The scope of `define macros, and most other compiler directives is a compilation unit. A compilation unit is a stream of source text that a compiler parses. A macro gets defined at the point it appears in the compilation unit and is visible from that point onward.
The scopes defined by modules and other namespaces are irrelevant because macros are pre-processed before any Verilog or SystemVerilog syntax gets recognized. This means you can never have instance specific control over macro definitions.
If you want instance specific control over your code, you need to define parameters with instance specific overrides. Then you can use generate-if/case constructs to control the code you want to execute. If the generate construct is too restrictive for you, you can use procedural-if/case statements and optimization will remove branches not taken as a result of constant parameters.
The best way is to modify your sub_sub module using parameter as suggested in other answers.
However, this may not be practical if you can't edit/modify the sub_sub module, for example, it may be an encrypted IP.
In this case, one solution is to create wrapper nested module for each sub_sub module. You can do as follows:
// Wrapper for sub_sub with OFF defined
module sub_sub_wrapper1;
`define OFF
`include "sub_sub.v"
`undef OFF
endmodule
// Wrapper for sub_sub without OFF defined
module sub_sub_wrapper2;
`include "sub_sub.v"
endmodule
////////////////
module sub;
sub_sub_wrapper1 subsub1();
endmodule
module top;
sub sub1();
sub_sub_wrapper2 subsub2();
endmodule
Quick sample
In this case of course I am assuming you are able to edit your top and sub module. And just note that nested module is only supported in system-verilog.

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

What to_unsigned does?

Could someone please explain me how VHDL's to_unsigned works or confirm that my understanding is correct?
For example:
C(30 DOWNTO 0) <= std_logic_vector (to_unsigned(-30, 31))
Here is my understanding:
-30 is a signed value, represented in bits as 1111111111100010
all bits should be inverted and to it '1' added to build the value of C
0000000000011101+0000000000000001 == 0000000000011111
In IEEE package numeric_std, the declaration for TO_UNSIGNED:
-- Id: D.3
function TO_UNSIGNED (ARG, SIZE: NATURAL) return UNSIGNED;
-- Result subtype: UNSIGNED(SIZE-1 downto 0)
-- Result: Converts a non-negative INTEGER to an UNSIGNED vector with
-- the specified SIZE.
You won't find a declared function to_unsigned with an argument or size that are declared as type integer. What is the consequence?
Let's put that in a Minimal, Complete, and Verifiable example:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity what_to_unsigned is
end entity;
architecture does of what_to_unsigned is
signal C: std_logic_vector (31 downto 0);
begin
C(30 DOWNTO 0) <= std_logic_vector (to_unsigned(-30, 31));
end architecture;
A VHDL analyzer will give us an error:
ghdl -a what_to_unsigned.vhdl
what_to_unsigned.vhdl:12:53: static constant violates bounds
ghdl: compilation error
And tell us -30 (line 12:character 53) has a bounds violation. Meaning in this case the numerical literal converted to universal_integer doesn't convert to type natural in the function to_unsigned.
A different tool might tell us a bit more graphically:
nvc -a what_to_unsigned.vhdl
** Error: value -30 out of bounds 0 to 2147483647 for parameter ARG
File what_to_unsigned.vhdl, Line 12
C(30 DOWNTO 0) <= std_logic_vector (to_unsigned(-30, 31));
^^^
And actually tells us where in the source code the error is found.
It's safe to say what you think to_unsigned does is not what the analyzer thinks it does.
VHDL is a strongly typed language, you tried to provide a value to place where that value is out of range for the argument ARG in function TO_UNSIGNED declared in IEEE package numeric_std.
The type NATURAL is declared in package standard and is made visible by an inferred declaration library std; use std.standard.all; in the context clause. (See IEEE Std 1076-2008, 13.2 Design libraries):
Every design unit except a context declaration and package STANDARD is
assumed to contain the following implicit context items as part of its
context clause:
library STD, WORK; use STD.STANDARD.all;
The declaration of natural found in 16.3 Package STANDARD:
subtype NATURAL is INTEGER range 0 to INTEGER'HIGH;
A value declared as a NATURAL is a subtype of INTEGER that has a constrained range excluding negative numbers.
And about here you can see you have the ability to answer this question with access to a VHDL standard compliant tool and referencing the IEEE Std 1076-2008, IEEE Standard VHDL Language Reference Manual.
The TL:DR; detail
You could note that 9.4 Static expressions, 9.4.1 General gives permission to evaluate locally static expressions during analysis:
Certain expressions are said to be static. Similarly, certain discrete ranges are said to be static, and the type marks of certain subtypes are said to denote static subtypes.
There are two categories of static expression. Certain forms of expression can be evaluated during the analysis of the design unit in which they appear; such an expression is said to be locally static.
Certain forms of expression can be evaluated as soon as the design hierarchy in which they appear is elaborated; such an expression is said to be globally static.
There may be some standard compliant tools that do not evaluate locally static expressions during analysis. "can be" is permissive not mandatory. The two VHDL tools demonstrated on the above code example take advantage of that permission. In both tools the command line argument -a tells the tool to analyze the provided file which is if successful, inserted into the current working library (WORK by default, see 13.5 Order of analysis, 13.2 Design libraries).
Tools that evaluate bounds checking at elaboration for locally static expressions are typically purely interpretive and even that can be overcome with a separate analysis pass.
The VHDL language can be used for formal specification of a design model used in formal proofs within the bounds specified by Annex D Potentially nonportable constructs and when relying on pure functions only (See 4.Subprograms and packages, 4.1 General).
VHDL compliant tools are guaranteed to give the same results, although there is no standardization of error messages nor limitations placed on tool implementation methodology.
to_unsigned is for converting between different types:
signal i : integer := 2;
signal u : unsigned(3 downto 0);
...
u <= i; -- Error, incompatible types
u <= to_unsigned(i, 4); -- OK, conversion function does the right thing
If you try to convert a negative integer, this is an error.
u <= to_unsigned(-2, 4); -- Error, does not work with negative numbers
If you simply want to invert an integer, i.e. 2 becomes -2, 5 becomes -5, just use the - operator:
u <= to_unsigned(-i, 4); -- OK as long as `i` was negative or zero
If you want the absolute value, a function for this is provided by the numeric_std library.
u <= to_unsigned(abs(i), 4);